两个Rails应用程序之间的共享模型 - Workflow的理想解决方案是什么?

时间:2011-08-11 11:05:03

标签: ruby-on-rails backend rails-models

我目前正在开发一个Rails 3项目,该项目分为四个部分:

  • 面向公众的网站
  • 管理网站/后端
  • 模特
  • 第三方数据访问API

由于模型在三个关键组件之间共享,我想让它们远离一个主项目,但是每个部分都需要访问模型,但我不想重复代码并且到处都有不同的版本

目前我在gem中有模型代码,在每个项目的Gemfile中我使用以下行引用它们:

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

然而,当我部署到我们的测试服务器以供我的同事评估系统时,我需要从外部存储库中提取模型,所以我将上面的行替换为以下内容:

gem "my_models", :git => "git@private.repository.com:username/my_models.git"

这在它自身运行良好,但它在'版本'方面非常笨重(即我每次希望将更改部署到测试服务器时都需要修改版本),切换线路以使用git代替本地的,并确保我正在推送文件。

以前我使用的是共享的git子模块,但这也很尴尬。

我宁愿不把所有内容都构建成一个大项目,因为这些项目往往变得怪异且难以维护,如果可能的话我也想分开关注点,因此我对管理站点所做的任何更改都没有很有可能影响其他组件 - 显然这些模型有可能导致问题,但这是我考虑和理解的风险。

当涉及到这样的事情时,那里的人们会提出什么建议?或者,我是否完全采用了错误的方式?

一些额外的背景:

这个应用程序是对现有网站的重写,遵循“将所有内容整合到一个项目中”的模式 - 不幸的是,这里有两个问题:

  1. 该应用程序开发得很糟糕 - 我继承了这个项目,当我第一次拿起它时,每个页面的加载时间约为2分钟,只有一个用户 - 这已经减少但仍然存在问题
  2. 我们目前处于当前网站的容量限制,我们预计在未来6个月内我们将需要承担更多负载 - 但是使用'all in one'应用扩展意味着我们将浪费资源在扩展不需要它的网站的后端。
  3. 基本上我想分开两件事 - 前端(公共网站和API)和后端 - 我所知道的关于软件开发的一切都告诉我,将所有这些结合在一起并不是一个理想的解决方案(和过去的历史告诉我,在确保前端表现方面,将这两者分开是一个很好的举措。)

    也许我需要从另一个角度来看待这个问题 - 在每个项目中保留模型,而不是在项目之间共享它们,每个功能区域都有一个简化的功能子集(即后端需要知道谁创建了一个发布,但前端并不真正关心这一点,因此在阅读模型时省略了这种逻辑。)

6 个答案:

答案 0 :(得分:19)

放弃模型项目(将模型放入其他部分之一,我建议您考虑“更重要”),将所有项目放入单个存储库(单独的项目文件夹)并对模型/ libs / apis /进行符号链接任何

您的代码高度耦合在一起,您经常需要同时更改少数项目(例如更新模型更新使用它们的API等)

单个repo-symlink设置的一个好处是你的提交将更少碎片,通常代表完整的功能实现 - 更容易跟踪错误,读取历史记录和维护代码库

同样在部署时,您不需要从许多存储库中读取 - 在那里少了一点失败

发布过程也比这样的模型更简单,因为分支现在将包含所有项目的范围

有一些缺点,例如符号链接在Windows上不能很好地工作,但对我来说它完美无缺

答案 1 :(得分:8)

您可以创建一个包含共享模型的可安装引擎,并从中创建一个gem。这将优雅地处理名称间距问题。这里另一个不错的方面是你也可以分享你的资产。

观看此railscast了解详情。

答案 2 :(得分:3)

您仍然需要通过将需要测试的更改推送到远程仓库来管理“版本”,但您可以使用Bundler 1.2的新local配置

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

通过这种方式,它将获取您的本地提交,并且您无需在部署时更改Gemfile。

答案 3 :(得分:0)

我知道这不是解决您特定问题的方法。但我真的建议你将所有项目合并为一个。通常将所有这些部件放在一个应用程序中并且没有开销。我认为这个问题没有尴尬的解决办法。

答案 4 :(得分:0)

您的项目是否有足够的代码覆盖率?如果确实如此,我会尝试将逻辑分开,如果在不同的项目中使用模型,只需选择一个最合适的模型并在其上编写API。

然后,您可以使用该API访问其他项目中的那些模型(最好使用类似ActiveModel的东西)。您仍然可以使用简单的CRUD,但所有核心模型逻辑都将在外部处理。

不过,在分手之前一定要好好考虑一下。你想让你的领域紧紧抓住你想要撕裂的巨兽所创建的每个应用程序。

关于引擎:

我已经使用了Engines来解决同样的问题并且它确实有所帮助,但我还必须将我的Gemfile更改为指向开发时的本地路径,推送gem,然后将其拉到当前项目上,这就是行为你不喜欢。

答案 5 :(得分:-1)

看看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/