Rails:在具有警告的子文件夹中组织模型:由B::A引用的顶级常量A



今天我决定重组大量与用户相关的模型,但我遇到了一个问题。

在我有这样的结构之前:

app/models/user.rb
app/models/user_info.rb
app/models/user_file.rb
...

所以我把所有的user_模型都移到用户子文件夹中,如下所示:

app/models/user.rb
app/models/user/info.rb
app/models/user/file.rb
...

并将其定义更改为

class User::Info < ActiveRecord::Base
class User::File < ActiveRecord::Base
...

User模型没有改变(除了关联)。

除了User::File型号外,一切都很好。当我试图访问这个模型时,我得到了以下错误:

warning: toplevel constant File referenced by User::File

事实上,它返回了标准的ruby文件类。

我做错了什么?

UPD1:

root# rails c
Loading development environment (Rails 3.2.13)
2.0.0p195 :001 > User::File
(irb):1: warning: toplevel constant File referenced by User::File
 => File
2.0.0p195 :002 > User::Info
 => User::Info(...)

UPD2:

2.0.0p195 :001 > User::SomeModel
NameError: uninitialized constant User::SomeModel
2.0.0p195 :002 > User::IO
(irb):2: warning: toplevel constant IO referenced by User::IO
 => IO 
2.0.0p195 :003 > User::Kernel
(irb):3: warning: toplevel constant Kernel referenced by User::Kernel
 => Kernel 

我的应用程序没有任何IO或内核类,除了ruby默认类。

UPD3:

# app/models/user.rb
class User < ActiveRecord::Base
  has_many :files, class_name: 'User::File'
  ..
end
# app/models/user/file.rb
class User::File < ActiveRecord::Base
  belongs_to :user
  # some validations, nothing serious
end

更新:今年的圣诞礼物是Ruby 2.5.0的发布,这个错误不会再发生了。使用Ruby 2.5+,您要么会得到您要求的常量,要么会出现错误。对于较旧的Ruby版本,请阅读:

您的User::File类未加载。您必须要求它(例如在user.rb中)。

当ruby/rails看到User::Info并对其进行求值时,会发生以下情况(简化了;只定义了User)。

  • 检查是否定义了User::Info-它(尚未)
  • 检查是否定义了Info-它(尚未)
  • uninitialized constant->执行rails魔术来查找user/info.rb文件并要求它
  • 返回User::Info

现在让我们再次对User::File 进行此操作

  • 检查是否定义了User::File-它(尚未)
  • 检查是否定义了File——确实如此(因为ruby有一个内置的File类)
  • 产生警告,因为我们被要求User::File,但得到了::File
  • 返回::File

我们观察到,rails魔术自动需要文件来存储(但)未知常量,但它不适用于User::File,因为File不是未知的。

尝试将类引用为User::File,以将其与常规ruby文件区分开来。当不明确时,您可以使用::File来引用这些文件

最新更新