3

我正在开发一个由两部分组成的应用程序:一个 ruby​​ 命令行应用程序和一个用于前端的 Rails 应用程序。

我一直在 Ruby 应用程序中使用 ActiveRecord 和 Rails 模型,方法是通过以下方式单独包含它们:

Dir[File.dirname(__FILE__) + '/../../RailsApp/app/models/*.rb'].each do |file|
  filename = File.basename(file, File.extname(file))
  require_relative "../../RailsApp/app/models/" + filename
end

并且通过手动维护两个几乎相同的 Gemfile 文件的依赖关系(我认为这种方法不是最好的)

昨天我将 Devise 添加到 Rails 应用程序中,现在当 ruby​​ 应用程序尝试包含用户模型时,会undefined method devise for class <xxxxx>出现消息。

我在我的 ruby​​ 应用程序的 Gemfile 中添加了设计 gem,但错误仍然存​​在。如果我理解正确的话,Devise 是一个 Rails 引擎,这就是为什么它不只是通过需要 gem 来加载的原因。

我读到在另一个应用程序中包含 Rails 模型的更好方法是要求该environment.rb文件,但是当我尝试这样做时,ActionMailer 出现错误:

undefined method `action_mailer' for #<Rails::Application::Configuration:0xbbb54bc>

我该如何解决设计问题?有没有比我目前用来避免维护两个 gemfile 的更好的方法将 Rails 模型包含在另一个应用程序中?谢谢

4

3 回答 3

5

尽管这种架构在不久的将来必须改变,但我们设法通过在 ruby​​ 应用程序中包含 devise 及其初始化程序来解决这个错误。

# FIXME: Dependency needed in Rails but not in the engine.
require 'devise'
require_relative "../../RailsApp/config/initializers/devise.rb"

#Load all the models
于 2012-05-18T16:49:31.747 回答
3

您可以在调用模型之前尝试放置require 'devise',但我不确定这是否可行?

我同意这种通用架构感觉不对。

我会将两个应用程序共有的代码提取到一个单独的库中,然后将该库包含在两个应用程序中。最简单的做法是将自己的库制作成 Gem,然后将其包含在两个 Gemfile 中。公共 gem 将在共享库中指定。制作宝石真的很容易。可以在http://asciicasts.com/episodes/245-new-gem-with-bundler(或相关的 Railscast)上找到好的说明。

您的命令行应用程序可能不需要关心 Devise。如果您在两者中都需要一个用户模型,您可以将它包含在共享库中,然后在 Rails 应用程序中添加任何额外的功能(例如设计)。

这有帮助吗?

于 2012-05-18T15:04:19.880 回答
0

您可以将加载模型的时间移到父应用程序初始化步骤中,而不是在您的 gem 加载自身时。

正如您的其他答案所建议的那样,构建一个 shared_code gem。

将您的 shared_code 加载循环移动到初始化文件中(例如 require 'user')

在 shared_code gemspec 中列出模型的 gem 依赖项(如设计)。

在您的 shared_code gem 中,包含一个生成器以将初始化程序文件安装到使用 shared_code gem 的应用程序中。

然后在父应用程序中使用您的共享代码,

宝石文件:

gem 'shared_code'

安慰:

rails generate shared_code:install

这是相同的模式设计和其他 gem 用于在父应用程序的初始化序列中的正确时间配置自己。

如果您在 user.rb 文件本身的设计初始化程序上使用 require_relative,则在 shared_code gem 中,您将消除使用 shared_code 的两个不同父应用程序可能需要初始化设计(或应用程序和应用程序的另一个 gem)的可能性你的宝石取决于)不同。

生成器的详细信息:

您可以通过像这样创建生成器来创建 shared_code:install 命令:

lib/generators/shared_code/install_generator.rb

module SharedCode
  class InstallGenerator < Rails::Generators::Base
    source_root File.expand_path('../templates', __FILE__)
    def copy_initializer_file
      copy_file "shared_code.rb", "config/initializers/shared_code.rb"
    end
  end
end

将模型加载代码放入 lib/generators/shared_code/templates/shared_code.rb

于 2012-10-25T02:14:48.547 回答