缺少Rails table_name_prefix

时间:2012-01-18 13:37:49

标签: ruby-on-rails model module prefix

我有以下目录结构

models/foo/setting.rb
models/foo.rb

foo.rb内容

 module Foo
  def self.table_name_prefix
    'foo_'
  end
 end

和setting.rb内容

class Foo::Setting < ActiveRecord::Base
end

当我调用Foo::Setting.find…时,我收到错误SQLException: no such table: settings,这确实是正确的,因为该表名为foo_settings,因此rails似乎忽略为模块指定的表前缀FOO。

我可以做什么让rails考虑前缀?

4 个答案:

答案 0 :(得分:20)

您已在模块内定义了一个方法(Foo)。这并没有神奇地在嵌套在该模块中的类上定义该方法。

我会尝试像

这样的东西
class Foo < ActiveRecord::Base
  self.abstract_class = true
  self.table_name_prefix = 'foo_'
end

然后继承自Foo

class Foo::Setting < Foo
...
end

答案 1 :(得分:7)

这可能是由rails的自动加载器引起的。这样做时:

The error occurred while parsing the regular expression fragment: '/([0-9]{5}>>>HERE>>>)]'.

然后尝试使用module Foo class Bar end end ,自动加载器首先尝试找到Foo::Bar。该文件已加载,此处定义了app/models/foo/bar.rb(虽然该模块仅包含module Foo),因此自动加载器永远不会尝试加载Bar

这应该只在开发模式下进行,因为在生产模式下,所有文件在启动时都是app/models/foo.rb

AFAIK有两种解决方法:

欺骗自动加载器

使用require声明您的课程,以强制自动加载器解析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 将失败,除非您使用Foo::Bar.new.baz引用常量。例如,在定义ActiveRecord关联时,这可能会变得非常混乱。

需要模块

使用Foo::BAZ

require_dependency

这是恕我直言的正确解决方案,因为它不会破坏常量查找,但它也有点烦人,因为你必须在每个命名空间文件的顶部添加require语句。

注意:

这个bug似乎已经在rails 4中解决了。我在rails 3上使用了第二个解决方法,但是我试图重现rails 4中的bug并且它不再出现了。我认为他们修改了自动加载器的工作方式...有关详细信息,请参阅the rails guides on autoloading and reloading constants

答案 2 :(得分:1)

我有同样的问题。通过更改我的应用程序的命名空间或模型来解决它。

看看这个question。对应用程序使用与模型相同的命名空间会导致模型无法正确获取父命名空间table_name_prefix。

答案 3 :(得分:0)

只需在命名空间的模型目录中创建一个基类,并在其中包含Foo,然后从基类扩展模型。

说我有app/models/foo.rb

module Foo
  def self.table_name_prefix
    'tble_prefix_'
  end
end

然后在app/models/foo/base_record.rb

require_dependency 'foo'
module Foo
  class BaseRecord < ActiveRecord::Base
    self.abstract_class = true
  end
end

然后从BaseRecord

延伸
module Foo
  class Bar < BaseRecord

  end
end