gor*_*tde 20 model module ruby-on-rails prefix
我有以下目录结构
models/foo/setting.rb
models/foo.rb
Run Code Online (Sandbox Code Playgroud)
foo.rb内容
module Foo
def self.table_name_prefix
'foo_'
end
end
Run Code Online (Sandbox Code Playgroud)
和setting.rb内容
class Foo::Setting < ActiveRecord::Base
end
Run Code Online (Sandbox Code Playgroud)
一旦我调用Foo::Setting.find…我得到一个SQLException: no such table: settings确实正确的错误,因为该表被命名,foo_settings因此rails似乎忽略为模块Foo指定的表前缀.
我可以做什么让rails考虑前缀?
Fre*_*ung 21
您已在模块(Foo)中定义了一个方法.这并没有神奇地在嵌套在该模块中的类上定义该方法.
我会尝试类似的东西
class Foo < ActiveRecord::Base
self.abstract_class = true
self.table_name_prefix = 'foo_'
end
Run Code Online (Sandbox Code Playgroud)
然后继承 Foo
class Foo::Setting < Foo
...
end
Run Code Online (Sandbox Code Playgroud)
这可能是由rails的自动加载器引起的.这样做时:
module Foo
class Bar
end
end
Run Code Online (Sandbox Code Playgroud)
然后尝试使用Foo::Bar,自动加载器首先尝试定位app/models/foo/bar.rb.文件已加载,并module Foo在此处定义(尽管是仅包含的模块Bar),因此自动加载器永远不会尝试加载app/models/foo.rb.
这应该只在开发模式下发生,因为在生产模式下,所有文件都require在启动时.
AFAIK有两种解决方法:
欺骗自动加载器
声明你的类使用class Foo::Bar,强制自动加载器解析常量查找Foo.
这有一个恼人的副作用,内部的常量查找Bar不会限制在里面Foo,例如:
# app/models/foo.rb
module Foo
BAZ = "baz"
end
# app/models/foo/bar.rb
class Foo::Bar
def baz
BAZ
end
end
Run Code Online (Sandbox Code Playgroud)
在这里,Foo::Bar.new.baz将失败,除非你引用常量使用Foo::BAZ.例如,在定义ActiveRecord关联时,这可能会变得非常混乱.
需要模块
使用require_dependency:
require_dependency 'foo'
module Foo
class Bar
end
end
Run Code Online (Sandbox Code Playgroud)
这是恕我直言的正确解决方案,因为它不会破坏常量查找,但它也有点烦人,因为你必须在每个命名空间文件的顶部添加require语句.
注意 :
这个错误似乎已经在rails 4中解决了.我在rails 3上使用了第二个解决方法,但是我试图在rails 4中重现这个bug并且它不再出现了.我认为他们修改了自动加载器的工作方式...有关详细信息,请参阅自动加载和重新加载常量的rails指南
| 归档时间: |
|
| 查看次数: |
13094 次 |
| 最近记录: |