在Rails外部包含用户模型时,未定义的方法'设计'

时间:2012-05-18 14:26:25

标签: ruby-on-rails ruby activerecord devise

我正在开发一个包含两个部分的应用程序:一个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中添加了devise gem,但错误仍在继续。如果我理解正确的话,Devise就是一个Rails引擎,这就是为什么它只是通过要求gem来加载它。

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

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

如何用设计解决问题?是否有更好的方法将Rails模型包含在另一个应用程序中,而不是我目前用来避免保留两个gemfiles的应用程序?感谢

3 个答案:

答案 0 :(得分: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

答案 1 :(得分:3)

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

我同意这种一般架构感觉不对。

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

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

这有帮助吗?

答案 2 :(得分:0)

您可以将加载模型的时间转移到父应用初始化步骤,而不是在宝石自行加载时。

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

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

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

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

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

的Gemfile:

gem 'shared_code'

控制台:

rails generate shared_code:install

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

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

发电机的详细信息:

您可以通过创建如下的生成器来创建shared_code:install命令:

LIB /发电机/ 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