在建立belongs_to :author
这样的关系时,我总是使用:class_name => 'User'
选项,但我从不喜欢它。它不是语义,IMO。
所以我在想我的User
模型的别名。 "嗯",我想,"模型只是一个常数,所以让我们给它起另一个名字。
然后我写了Author = User
并将其保存在app/models/author.rb
。
看起来很好,并且除了一个以外的所有目的都很好。当我尝试使用我的关系时,请说post.build_author
我得到uninitialized constant Post::Author
。
为什么ruby找不到常量Author
?
似乎Post
无法联系到它,所以我尝试了这个:
class Post
def author_class_test
Author
end
end
=> Post.new.author_class_test
=> User(...)
所以,我认为Post
可以"看" Author
。但是在处理关系时,有没有人知道为什么会这样?
提前致谢。
更新
所以,出于好奇我尝试了这个:
class Post
Author = User
...
end
然后又Post.new.build_author
又让我uninitialized constant Post::Author
。但至少现在我知道他对我撒谎。 :P
跟踪在此处结束:https://github.com/rails/rails/blob/master/activerecord/lib/active_record/inheritance.rb#L142
我开始认为它是ActiveRecord不考虑的边缘情况。
答案 0 :(得分:0)
我看到你可以这样做的一种方法是创建一个存储这些别名的模块。
例如:
module UserAliases
Author = User
end
class User < ActiveRecord::Base
include UserAliases
# ...
end
将模块放在应用程序的某个位置,需要它并将其包含在您的模型中,这应该可以解决问题。如果有效,请告诉我。
答案 1 :(得分:0)
您应该使用Class.new
。
您可以在回溯中看到,rails正在尝试使用compute_type
构建关联类型。要使compute_type
起作用,类名必须正确。
让我们谈谈在定义一个类时我们究竟在做什么。
class A
def self.foo
puts "#{self.name} foo"
end
end
这是定义类的最常用方法,但它实际上只是将块传递给Class.new
的别名。 Class.new
也接受一个参数,您可以提供另一个类。将类传递给Class.new
时,它会生成一个新类,并将传入的类设置为其超类。一个例子将清除这一点:
B = Class.new(A)
C = A
此处我们有B
和C
,它们都与A具有相同的行为。但是,在将A
分配给C
和设置之间存在一些重要的区别A
作为B
的超类。与你相关的是:
A.foo
B.foo
C.foo
#=> A foo
#=> B foo
#=> A foo
您会看到我们何时使用作业,C
没有使用您提供的名称。当我们使用Class.new
时,我们告诉B
采用我们给出的名称,而不是与分配类相同的名称。
你实际上是在创建一个行为类似于User
的类,即使你问它的名字是什么,但是你仍然在没有设置类名的情况下调用关联Author
。
请改为:
Author = Class.new(User)