53

我目前正在研究一个分为四个部分的 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 个月我们将需要承担更多负载 - 但是使用“一体式”应用程序进行横向扩展意味着我们将浪费资源进行横向扩展不需要它的站点的后端。

基本上有两件事我想分开 - 前端(作为公共网站和 API)和后端 - 我所知道的关于软件开发的一切都告诉我,将所有这些结合在一起并不是一个理想的解决方案(过去的历史表明我认为将这两者分开是确保前端性能的好举措)。

也许我需要从另一个角度看待这个问题——将模型保留在每个项目中,而不是在项目之间共享它们,而是为每个功能区域提供一个缩减的功能子集(即后端需要知道谁创建了一个帖子,但是前端并不真正关心这一点,因此在读取模型时省略该逻辑)。

4

6 回答 6

20

删除模型项目(将模型放入其他部分之一,我会建议您认为“更重要”的任何内容),将所有项目放入单个存储库(单独的项目文件夹)并创建到模型/库/apis/whatever 的符号链接

您的代码高度耦合在一起,您经常需要一次对几个项目进行更改(例如更新模型更新使用它们的 API 等)

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

此外,当您部署时,您不需要从许多存储库中读取 - 那里少一个故障点

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

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

于 2012-06-27T21:26:45.737 回答
8

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

观看此railscast了解更多详情。

于 2012-06-29T01:15:36.780 回答
3

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

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

这样,它将获取您的本地提交,并且您不必在部署时不断更改您的 Gemfile。

于 2012-10-14T20:36:32.213 回答
1

看看 Git 子树。

这可能对你有用..

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

或者

你可以写耙任务..

例子:-

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/

于 2015-10-19T06:45:57.980 回答
0

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

于 2011-08-11T11:19:16.003 回答
0

您的项目是否有足够的代码覆盖率?如果是这样,我会尝试在有意义的地方分离逻辑,如果一个模型用于不同的项目,只需选择一个最适合的模型并在此基础上编写一个 API。

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

不过,在拆分它们之前一定要好好考虑。您希望将您的域名牢牢固定在您创建的每个应用程序上,这些应用程序是您想要拆散的 Behemoth。

关于发动机:

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

于 2012-06-29T01:45:01.383 回答