Общие модели между двумя приложениями Rails — какое идеальное решение для рабочего процесса?

В настоящее время я работаю над проектом Rails 3, который разделен на четыре части:

  • Общедоступный веб-сайт
  • Административный веб-сайт / бэкэнд
  • Модели
  • API для доступа к данным третьих лиц

Поскольку модели совместно используются тремя ключевыми компонентами, я хочу, чтобы они не находились в одном основном проекте, однако каждой части нужен доступ к моделям, но я не хочу повторять код и везде иметь разные версии.

В настоящее время у меня есть код модели в драгоценном камне, и в Gemfile каждого проекта я ссылаюсь на них со следующей строкой:

gem "my_models", :path => "../my_models/"

Однако, когда я выполняю развертывание на наших тестовых серверах, чтобы мои коллеги могли оценить систему, мне нужно извлечь модели из внешнего репозитория, поэтому я заменяю приведенную выше строку следующей:

gem "my_models", :git => "[email protected]:username/my_models.git"

Это само по себе работает хорошо, но довольно неуклюже с точки зрения «версий» (т.е. мне нужно поднимать версию каждый раз, когда я хочу развернуть изменения на тестовых серверах), переключите строку, чтобы использовать git вместо локального, и убедитесь, что я правильно загружаю файлы.

Раньше я использовал общий подмодуль git, но это было так же неудобно.

Я бы предпочел не объединять все в один мегапроект, поскольку они имеют тенденцию становиться чудовищными и сложными в обслуживании, и я также хотел бы, если это возможно, разделить задачи, поэтому любые изменения, которые я вношу на административный сайт, не имеют большого значения. шанс повлиять на другие компоненты - очевидно, что модели могут вызвать проблемы, но это риск, который я рассмотрел и понимаю.

Что бы люди там предложили, когда дело доходит до чего-то подобного? Или я делаю это совершенно неправильно?

Дополнительная информация:

Это приложение представляет собой переработанный вариант существующего веб-сайта, который следует модели «собрать все в один проект» — к сожалению, здесь есть две проблемы:

  1. Приложение было плохо разработано — я унаследовал этот проект, и когда я впервые взял его, время загрузки составляло ~ 2 минуты на страницу с одним пользователем — с тех пор оно было уменьшено, но все еще имеет проблемы.
  2. В настоящее время мы достигли предела емкости текущего сайта, и мы ожидаем, что в следующие 6 месяцев нам потребуется больше нагрузки, однако масштабирование с помощью приложения «все в одном» означает, что мы будем тратить ресурсы на масштабирование. задняя часть сайта, которая в этом не нуждается.

По сути, есть две вещи, которые я хочу разделить: интерфейс (представляющий собой общедоступный веб-сайт и API) и серверную часть — все, что я знаю о разработке программного обеспечения, говорит мне, что объединение всего этого вместе — не идеальное решение (и история показывает, мне кажется, что разделение этих двух — хороший шаг с точки зрения обеспечения производительности переднего плана).

Возможно, мне нужно посмотреть на это под другим углом — хранить модели в каждом проекте, и вместо того, чтобы делиться ими между проектами, иметь урезанный подмножество функциональности для каждой функциональной области (т.е. бэкенд должен знать, кто создал пост, но внешний интерфейс на самом деле не заботится об этом, поэтому опускайте эту логику при чтении модели).


person Matthew Savage    schedule 11.08.2011    source источник
comment
Что вам не понравилось в потоке подмодуля git? Это решение, которое сразу приходит на ум. Он решает проблему контроля версий и централизует код.   -  person Daniel Evans    schedule 28.06.2012
comment
Создание мегапроекта, вероятно, не лучшая идея. SOA и микросервисы могут быть лучшим подходом.   -  person B Seven    schedule 04.03.2015


Ответы (6)


удалить проект моделей (поместить модели в одну из других частей, я бы предложил то, что вы считаете «более важным»), поместить все проекты в один репозиторий (отдельные папки проектов) и сделать символические ссылки на модели/libs/apis/независимо

ваш код сильно связан, и вам часто нужно вносить изменения в несколько проектов одновременно (например, обновлять модели и обновлять API, которые их используют, и т. д.)

одна приятная особенность настройки с одним репозиторием и символической ссылкой заключается в том, что ваши коммиты будут менее фрагментированы и обычно будут представлять полную реализацию функций - легче отслеживать ошибки, читать историю и поддерживать кодовую базу.

также при развертывании вам не нужно читать из многих репозиториев — на одну точку отказа прямо здесь

процесс выпуска также проще с такой моделью, так как ветка теперь будет содержать объем всех проектов

есть некоторые недостатки, например, символические ссылки не работают так хорошо на окнах и еще много чего, но для меня это работает отлично

person keymone    schedule 27.06.2012
comment
очевидно, я не имею в виду, что вы должны помещать все свои проекты в одно репо. но я бы поместил туда все, что разделяет ваши модели (потому что оно, вероятно, разделяет гораздо больше). - person keymone; 28.06.2012
comment
Это на самом деле звучит как действительно хорошее решение. Я попробую это, а затем дам отзыв / голосование / награду :) - person Patrick Glandien; 28.06.2012
comment
спасибо, не стесняйтесь задавать вопросы - постараюсь помочь чем смогу - person keymone; 28.06.2012
comment
Я работаю над проектом с аналогичной настройкой, поэтому я нашел этот ответ полезным. Однако я столкнулся с кирпичной стеной при попытке развернуть общедоступный веб-сайт на Heroku. Приложение общедоступного сайта символически связывает модели и файл database.yml из приложения администратора. Heroku использует git для развертывания, а git не использует символические ссылки, поэтому я немного застрял. Я мог бы использовать жесткие ссылки, но это делает нажатие и извлечение неудобным (дублирование данных). Если у кого-то есть предложения, я весь внимание. - person cgat; 18.05.2013
comment
@cgat git отлично работает с символическими ссылками (хотя я не уверен в более старых версиях). если у вас есть проекты admin и web, попробуйте это: cd web/app; ln -s ../../admin/app/models ./models - это работает для меня - person keymone; 18.05.2013
comment
@keymone да, ты прав. Git отслеживает файлы символических ссылок, но когда я развертываю, загружаются символические ссылки, которые ссылаются на неразвернутый проект, а не сами модели. Пример: рассмотрим два проекта admin и web, хранящиеся в каталоге project (также один репозиторий git). admin имеет каталог моделей. web ссылок, как вы упомянули. Я хочу развернуть только web, а не admin. Я развертываю поддерево web с git subtree push --prefix web heroku master, но в этом случае я развертываю символическую ссылку (модели), которая никуда не ведет (поскольку admin не развернута). - person cgat; 19.05.2013
comment
@cgat Я не знаком с процессом развертывания heroku, мои сценарии capistrano настроены на получение всего репо и папки, связанной с rsync, которая правильно следует символическим ссылкам, попробуйте настроить процесс heroku, чтобы сделать то же самое, если это возможно. удачи :) - person keymone; 19.05.2013
comment
Ааа, имеет смысл. Развертывание Heroku строго зависит от git (это не похоже на то, что у вас есть сервер, на который вы можете подключиться по ssh), поэтому я не думаю, что это возможно. Это не мешает мне развертывать где-то еще :) Спасибо за ответ. - person cgat; 19.05.2013
comment
Любопытно, нашел ли @keymone или кто-либо способ заставить этот подход с символической ссылкой работать с heroku. Сейчас в этой лодке, и похоже, что частная жемчужина моделей - единственный путь. - person Ryan; 11.12.2014

Вы можете создать монтируемый движок, содержащий общие модели, и создать из него драгоценный камень. Это позволит элегантно решить проблемы с интервалом между именами. Другим приятным аспектом здесь является то, что вы также можете делиться своими активами.

Смотрите railscast, чтобы узнать подробности.

person Harish Shetty    schedule 29.06.2012

Вам по-прежнему придется управлять «версиями», отправляя изменения, которые необходимо протестировать, в удаленное репо, но вы можете использовать новую конфигурацию local Bundler 1.2.

http://gembundler.com/man/bundle-config.1.html#LOCAL-GIT-REPOS

Таким образом, он подберет ваши локальные коммиты, и вам не придется постоянно изменять свой Gemfile после развертывания.

person wprater    schedule 14.10.2012

Я знаю, что это не решение вашей конкретной проблемы. Но я действительно предлагаю вам объединить все проекты в один. Обычно все эти части находятся в одном приложении, и нет накладных расходов. Я думаю, что нет неуклюжего решения этой проблемы.

person iafonov    schedule 11.08.2011
comment
Полностью согласен. Обычно это делается, когда приложение становится огромным, и вы хотите разбить его на отдельные службы. - person Peter Brown; 11.08.2011
comment
В предыдущей итерации этого проекта все было в одном, а администрирование находилось в другом пространстве имен. Проблема в том, что он работает в рамках одного и того же процесса, поэтому, если что-то происходит в админке или API, это влияет на остальную часть сайта. - person Matthew Savage; 11.08.2011
comment
Я не согласен. Слияние всего в одно приведет к монолитному приложению, которое требует обновления всякий раз, когда изменяется какая-либо отдельная часть приложения, независимо от ее актуальности. Например, вам придется отключить свой API, чтобы развернуть изменение CSS на веб-сайте. - person Neil Middleton; 20.02.2012
comment
@ Нил, разве это не зависит от того, как вы развертываете? В конце концов, это просто файлы на жестком диске, которые можно заменить, не обязательно заменяя их все, Capistrano по умолчанию этого не делает, но теоретически вы можете заменить только измененные файлы. - person OpenCoderX; 28.06.2012
comment
@MatthewSavage Вы должны запускать несколько экземпляров сайта через Passenger или что-то подобное. Один пользователь не должен иметь возможность DOS сайта через долго выполняющийся запрос. - person meagar; 28.06.2012
comment
Во многих случаях вам понадобится отдельный API, в котором нет всего стека промежуточного программного обеспечения Rails (чтобы уменьшить рабочую нагрузку). Вам будет трудно собрать это вместе с полным веб-стеком. - person Patrick Glandien; 28.06.2012
comment
Я нашел весьма полезным разделить приложение, как он описывает. И сделали что-то очень похожее. Это значительно упрощает надлежащее масштабирование по мере использования каждого раздела приложения. - person wprater; 15.10.2012

Достаточно ли у вашего проекта покрытия кода? Если это так, я бы попытался разделить логику там, где это имеет смысл, и, если модель используется в разных проектах, просто выбрать ту, которая лучше всего подходит, и написать API поверх нее.

Затем вы можете использовать этот API для доступа к этим моделям (предпочтительно, используя что-то вроде ActiveModel) в другом проекте. У вас по-прежнему будет простой CRUD, но вся основная логика модели будет обрабатываться извне.

Однако не забудьте хорошо подумать, прежде чем разделять их. Вы хотите, чтобы ваш домен был тесным для каждого приложения, которое вы создаете из Бегемота, которого хотите разорвать на части.

Касательно двигателей:

Я использовал Engines для той же проблемы, и это действительно помогает, но мне также пришлось изменить свой Gemfile, чтобы он либо указывал на локальный путь при разработке, нажимая драгоценный камень, а затем вытягивая его в текущем проекте, что является поведением, которое вы не любит.

person Pedro Nascimento    schedule 29.06.2012

Взгляните на поддерево Git.

Это может сработать для вас.

http://igor-alexandrov.github.io/blog/2013/03/28/using-git-subtree-to-share-code-between-rails-applications/

OR

Вы можете написать задачу Rake.

Пример:-

namespace :sync do

  desc 'Copy common models and tests from Master'
  task :copy do
   source_path = '/home/project/src-path'
   dest_path = '/home/project/dest-path'

   # Copy all models & tests
   %x{cp #{source_path}/app/models/*.rb #{dest_path}/app/models/}
   %x{cp #{source_path}/spec/models/*_spec.rb #{dest_path}/spec/models/}

   # Database YML
   %x{cp #{source_path}/config/database.yml #{dest_path}/config/database.yml}

end

См. ссылку ниже.

http://hiltmon.com/blog/2013/10/14/rails-tricks-sharing-the-model/

person Amol Udage    schedule 19.10.2015