Рекомендации по размещению классов в Rails-приложениях, которые не подходят нигде
Мне интересно, есть ли какие-либо рекомендации по размещению нестандартных файлов Ruby в Rails-приложениях, которые не соответствуют ни одному из каталогов по умолчанию (controllers
/models
и т.д.).
Я говорю о классах, которые используются контроллерами/моделями и т.д., но не являются подклассами любого из базовых классов Rails. Классы, которые включают функциональность, извлеченную из моделей, чтобы сделать их менее жирными. Некоторые из них выглядят как модели, но не являются AR-моделями, некоторые из них больше похожи на "сервисы", некоторые - что-то среднее или что-то еще.
Несколько случайных примеров:
- "стратегии", которые обрабатывают аутентификацию с помощью пароля, через facebook и т.д.
- Объекты "XParams", которые инкапсулируют параметры или объекты "XCreator", которые обрабатывают обработку параметров для выполнения некоторого сложного действия, что в итоге приводит к созданию некоторых моделей AR в конце
- которые обращаются к внешним API-интерфейсам или инкапсулируют эти запросы и ответы
- поддельные модели, которые могут быть заменены реальной моделью AR (например, гостевой пользователь)
- Задачи Resque
- классы, которые хранят и читают информацию из Redis
- которые выполняют некоторые конкретные действия, такие как обработка данных, генерация отчетов и т.д. и вызываются из задач Resque или задач грабли.
Теперь у меня их довольно много, некоторые из них добавлены в lib
, который заканчивается как куча случайных классов и модулей, некоторые пробираются в app/models
. Я хотел бы как-то это организовать, но я не знаю, с чего начать.
Должны ли только модели AR входить в app/models
? Или это нормально, чтобы добавить туда какие-либо доменные или вспомогательные модели? Как вы решаете, является ли что-то моделью?
Если все, что не вписывается в app
, перейдите в lib
? Или, может быть, я должен добавить несколько новых настраиваемых подкаталогов в app
? Какие подкаталоги и как разделить пользовательские классы?
Как вы справляетесь с этим в своих проектах? Я знаю, что каждый проект немного отличается, но должно быть некоторое сходство.
Ответы
Ответ 1
Хороший вопрос - у меня нет конкретного ответа для вас
но я рекомендую проверить этот пост
- http://blog.codeclimate.com/blog/2012/02/07/what-code-goes-in-the-lib-directory/
- обязательно прочитайте все комментарии
в текущем проекте у меня есть тонна объектов не-ActiveRecord в приложении/моделях, она работает, но не идеальна
я добавляю "повторно используемый" неспецифический код в lib
другие альтернативы, которые я пробовал на сторонних проектах (скажем, у нас есть куча объектов команд)
rails - это боль, когда дело касается пространств имен под приложением, по умолчанию загружает все в одно и то же пространство имен
app/
commands/
products/create_command.rb # Products::CreateCommand
products/update_price_command.rb # Products::UpdatePriceCommand
alternate, все, кроме рельсов под src или каталога app_name
app/
src/
commands/
create_product.rb # Commands::CreateProduct
update_product_price.rb # Commands::UpdateProductPrice
Я не нашел хорошего решения для этого, в идеале 2-го лучше, но было бы неплохо, если бы не было дополнительного каталога под приложением, таким образом вы открываете приложение и видите контроллеры, команды, модели и т.д..
Ответ 2
Вы затрагиваете несколько различных вариантов использования, и я думаю, что эта часть ближе всего к "правильному" ответу:
Теперь у меня их довольно много, некоторые из них добавлены в lib, который заканчивается кучей случайных классов и модулей, некоторые из них подкрадываются к приложениям/моделям. Я хотел бы как-то это организовать, но я не знаю, с чего начать.
Это очень хорошо в моей книге. Единственное, о чем вы не говорите, это извлечение различных предметов в отдельные драгоценные камни. Классы, которые общаются с внешними службами, являются отличными кандидатами на извлечение, а также стратегическими классами, если они достаточно общие. Они могут быть частными, поскольку запуск собственного сервера gem не является сложным, и вы можете, очевидно, повторно использовать их в приложениях ROR.
Последнее и самое конкретное, resque jobs, которое я загружаю в lib/jobs.
Мое эмпирическое правило - это какая-то модель, она переходит в app/models
. Если нет, то он, вероятно, принадлежит lib
или некоторому соответствующему названному подкаталогу, например. lib/jobs
, lib/extensions
, lib/external
или тому подобное.
Ответ 3
Если вам интересно, я также написал дополнительную статью об этом чуть позже, подводя итог тому, что я нашел: http://blog.lunarlogic.io/2013/declutter-lib-directory/
Ответ 4
Я помещаю любые классы моделей (например, подклассы STI) в apps/models
. Я помещаю свои другие классы в lib
, поскольку это кажется лучшим местом для их размещения. Мне легко понять, где искать. Мне также легче группировать мои тесты, так как классы модели все в одном месте.
В соответствии с Конвенцией я не могу помещать вспомогательные классы в app/models
. Если они являются классами презентаторов, они принадлежат app/helpers
. Если они не тогда, то lib
кажется лучшим местом для них.
Ответ 5
Часто мои классы находят свой путь в lib
в подкаталогах, где модули с тем же именем, что и подкаталог, отвечают за их включение. (Rails очень трогательно относится к именам файлов и именам классов, когда дело доходит до автозагрузчика.)
Другой вариант - инкапсулировать каждый модуль в свой собственный камень, а затем обратиться к драгоценному камню через ваш Gemfile. Это позволяет совместное использование кода между проектами.