Rails如何确定关联关系是has_one还是has_many?

9

想知道是否有一种简单的方法来动态确定模型的关联是“has_one”还是“has_many”关系(即这是否是与一个对象或多个对象的关联)。

我正在使用MongoMapper,因此我可以通过以下方式检查类klass是否具有与之相关联的一个或多个关系的关联模型assoc

klass.associations[:assoc].is_a? MongoMapper::Plugins::Associations::OneAssociation
klass.associations[:assoc].is_a? MongoMapper::Plugins::Associations::ManyAssociation

但这种方法似乎有些笨重,而且不通用(即无法适用于ActiveRecord关联)。我还希望避免加载任何对象,因此我相当确定instance.assoc.is_a? Array也行不通。 有什么想法吗?

你解决这个问题了吗?我刚找到同样的问题,但只涉及 ActiveRecord - MCB
1个回答

12

更新:我偶然发现了反射类方法,可以使用http://api.rubyonrails.org/classes/ActiveRecord/Reflection/ClassMethods.html链接。

您可以使用 reflect_on_all_associations 方法获取所有的has_manybelongs_to等关联对象。也可以在reflect_on_association中添加一个关联对象,它将告诉您它是has_manyhas_one等之一。具体地说:

Model.reflect_on_association(:assoc).macro

这应该足以应对所有情况。它实际上并没有解决我目前正在处理的问题,但应该可以解决这个问题。


它并不完美,但可以根据你的类名工作。考虑一个名为User的类,它has_one另一个名为UserAttributes的类。不幸的是,你需要通过user.user_attributes来访问它,这会导致respond_to?(assoc_name.singularize)调用返回false。你可能会争辩(而且你可能是正确的),你应该将这个类重命名为UserAttributeSet或类似的名称,这样singularize就能正常工作了,但不能保证你只通过实例名称是单数还是复数就能正确获取关联类型。 - pariser
好的,拥有一个复数化的模型名称将违反Rails的命名约定(http://itsignals.cascadia.com.au/?p=7),因此您永远不应该拥有一个名为UserAttributes的模型。它应该始终是UserAttribute。因此,单数或复数应反映出具有has_one或has_many关系。任何其他问题都应在获取输入的逻辑中处理。 - MCB
1
确实,你是对的 - 这里有更好的方法来证明这并不涵盖每种情况:考虑模型 Fish,其中关联名称 "fish" 是不可数的。这意味着单词 "fish" 是名词的单数和复数形式(即 "fish".singularize == "fish".pluralize),因此通过这种方式,您无法知道模型是 has_one :fish 还是 has_many :fish - pariser
是的,但那是非常特殊的情况。你有鹿和那个,我甚至想不出另一个例子。通常情况下,除非绝对必须避免边缘情况,否则我不会用同形异义词来命名表。 - MCB

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接