Как организовать модели Rails, которые слишком толстые?
Хорошая практика - перевести логику с контроллера в модель. Но в любой сложной системе это неизменно приводит к очень большому файлу, даже если большинство методов являются одним лайнером по пути Rails.
Я прибегал к разделению моделей на другие модули и включая их в исходной модели, например model_flags
, model_validation
и т.д. У кого-то есть лучший способ?
Изменить: я выбрал новый ответ, который предложил использовать ActiveConcern. Кроме того, для всех, кто заинтересован в организации кода, эта статья, Создание моделей ActiveRecord Thin, должна очень помочь.
Ответы
Ответ 1
Я понимаю, что это довольно старый вопрос, и он был отмечен как ответ, но у него все еще есть хороший сок Google, поэтому я подумал, что стоит добавить...
В Rails 3 представлен ActiveSupport:: Концерн, который может использоваться для модуляции поведения, разделяемого между моделями. Или, если на то пошло, уменьшать модели, которые стали слишком толстыми.
Сам DHH представляет собой красивый, сжатый пример:
https://gist.github.com/1014971
Ответ 2
Я бы не сделал этого по нескольким причинам.
Сначала вы нарушаете предположение, что все будет там, где они должны быть, что, вероятно, является самым большим бонусом для рельсов в первую очередь. Новый человек может идти по вашему проекту и легко перемещаться по нему, если вы вставляете модельный материал в свою модель. Если вы вытащите его, вы просто добавите задержку и некоторую путаницу, особенно если единственная логика для удаления чего-то в модуль - это уменьшить размер модели.
Во-вторых, вы почти ничего не получаете от него, и вы что-то теряете. Размер файла не имеет значения в наши дни, когда почти все редакторы и IDE облегчают боль в навигации больших файлов. Перемещение материала в модуль на самом деле снимает некоторые из этих современных возможностей и потребует от вас и ваших коллег или будущих сопровождающих перейти к нескольким файлам при работе над одной моделью.
Это говорит о том, что я подозреваю, что хардкор-рельсы лучше всего подходят для вас, так это то, что если ваша модель такая большая и сложная, то ваш дизайн испорчен, и ваша модель, вероятно, представляет собой несколько вещей, которые могут быть сделаны в отдельных моделях, а не в модулях,
Ответ 3
Хорошо, я бы не сказал, что кто-то из вас ошибается, чтобы поместить все в одну модель, но я думаю, что вполне справедливо и возможность разделить различные проблемы. Это, по крайней мере, компромисс.
И я отправляю ответ на свой вопрос, так как я нашел способ Rails сделать именно это:
http://github.com/jakehow/concerned_with
Более подробную информацию можно найти здесь:
http://m.onkey.org/2008/9/15/active-record-tips-and-tricks
Ответ 4
Ответ 5
Не имея знаний о вашей объектной модели, вам немного сложно посоветовать, но я бы сказал, что если вы абсолютно уверены, что все проверки/ассоциации/обратные вызовы нуждаются в, чтобы быть в в этом месте все еще существуют способы разложения общих форм поведения. Поэтому, хотя я бы не просто переместил большой кусок кода из одного файла и в другой, где он просто снова открывает класс, я бы сказал, что использование модулей/плагинов для описания распространенных типов поведения - хорошая идея.
Например, если вы создаете фид активности Facebook-esque, и все должно генерировать "события", возможно, вам нужно переместить это поведение "Eventable" в модуль, который при включении определяет ассоциации/валидации/и т.д.. Я бы сказал, что этот подход на самом деле повысит ясность вашего кода, так как вручную указывать эти ассоциации повсюду не так выразительно, как объявлять что-то как событие, а также безопасно (вы будете дублировать логику в кучке мест, а когда логика меняется, вы знаете остальных...)
В целом, хотя, я бы сказал, взгляните на свою объектную модель. В вашем тестовом наборе, если вы заметили, что для всех ваших тестов требуется много настроек, это может быть хорошим показателем того, что в вашей объектной модели вам что-то не хватает. Опять же, некоторый пример кода будет большим.
Ответ 6
Модули звучат разумно. Я бы не извлекал вызовы методов (проверки, обратные вызовы, плагины и т.д.) В модули, хотя я бы ограничил извлечение своими собственными методами.
И, как всегда, это поможет, если вы разместите некоторый пример кода. Мне трудно представить общую стратегию очистки моделей, это зависит от характера кода.