丢失rails命名空间模型中的命名空间信息

时间:2012-04-04 13:12:05

标签: ruby-on-rails activerecord namespaces

使用rails scaffolding创建命名空间模型时,会得到两个文件。例如,这个脚手架:

rails generate model Staff::Location name:string address:string

生成这些文件:

/app/models/staff.rb    
module Staff
  def self.table_name_prefix
    "staff_"
  end
  ...

/app/models/staff/location.rb
class Staff::Location < ActiveRecord::Base
  ...

我在开发模式下遇到问题,其中rails卸载Staff模块并且从不重新加载它。由于缺少table_name_prefix,这会导致一些恼人的错误,例如Location无法访问它的表。当我不直接访问模型时,例如通过多态关系,问题似乎就出现了。

我似乎无法在一致的基础上加载模块。这是进行命名空间模型的最佳实践方法吗?如果是的话,我错过了什么?

2 个答案:

答案 0 :(得分:2)

虽然我无法在Rails 3.2.2中重现这个问题,但我之前遇到过类似的问题。在开发模式中解决此问题的一般方法是通过ActionDispatch回调。将其添加到config/environments/development.rb

MyApp::Application.configure do
  ActionDispatch::Callbacks.before do
    load Rails.root.join('app', 'models', 'staff.rb')
  end
end

您在该块中执行的任何操作都将在每个请求之前执行,因此确保您只在开发模式下执行。†否则,您将在生产中遇到性能损失

我在staff.rb文件和Staff模块本身内部记录了一条消息,并且每条请求的日志中都显示了这两条消息。


†我尝试使用to_prepare回调,因为这似乎是the documented way to execute code before each request only when cache_classes is false。但这似乎只是在重新启动应用程序后执行。至少有one other open Stack Overflow question regarding this,尽管他使用的语法与我使用的略有不同。如果您可以to_prepare开始工作,我建议不要使用before

答案 1 :(得分:2)

大约一年后,我终于找到了这个问题的答案。这个答案专门针对rails 3.1。我不确定它是否是rails 3.2中的问题。

设置模型时会出现问题。如果使用scaffolding,则不会生成任何帮助文件。这通常位于/app/helpers/staff/location_helper.rb中。有两种方法可以设置此文件:

module Staff::LocationHelper
  ...
end

module Staff
  module LocationHelper
    ...
  end
end

在rails 3.1中,特别是对于帮助程序,您必须使用第一个解决方案。您不必将它用于在rails项目的其他部分中使用命名空间的其他模块。事实上,红宝石中的一些结构需要第二种解决方案。

如果在声明帮助程序时使用第二个解决方案,则在某些情况下,帮助程序文件中的Staff模块将覆盖/app/models/staff.rb中的模块。它会默默地用文件中的空Staff模块替换它。这种情况不会100%发生,因为帮助程序并不总是被加载。