如何检查对象是否是has_one或has_many的结果?

时间:2015-07-01 11:03:56

标签: ruby-on-rails ruby activerecord

我基于has_onehas_many关系动态构建查询。所以,我最终可以得到一个对象或CollectionProxy。如何根据此结果测试查询是使用has_one还是has_many关系?

我想过检查类型,但CollectionProxy的类型是相关模型类型的子类。

此动态查询涉及调用对象的属性,该属性可以是has_onehas_many关系。类似的东西:

class User < ActiveRecord::Base
  has_one :profile
  has_many :names

user = User.new
attr = 'profile' # or 'names'
user.send(attr) # I want to check whether this is a result of which of the two relations

3 个答案:

答案 0 :(得分:4)

您可以使用Active Record的reflection

User.reflect_on_association(:profile)
#=> #<ActiveRecord::Reflection::HasOneReflection:0x007fd2b76705c0 ...>

User.reflect_on_association(:names)
#=> #<ActiveRecord::Reflection::HasManyReflection:0x007fd2b767de78 ...>

case声明中:

klass = User
attr = :profile

case klass.reflect_on_association(attr)
when ActiveRecord::Reflection::HasOneReflection
  # ...
when ActiveRecord::Reflection::HasManyReflection
  # ...
end

这基于模型中的关联声明(user.rb),即无需访问数据库。

答案 1 :(得分:2)

您可以实际检查结果的类型。您只需检查它是ActiveRecord :: Base还是ActiveRecord :: Associations :: CollectionProxy。

按照你的例子:

class User < ActiveRecord::Base
  has_one :profile
  has_many :names

user = User.new
attr = 'profile'
user.send(attr).is_a? ActiveRecord::Base # true
user.send(attr).is_a? ActiveRecord::Associations::CollectionProxy # false

attr = 'names'
user.send(attr).is_a? ActiveRecord::Base # false
user.send(attr).is_a? ActiveRecord::Associations::CollectionProxy # true

这是在Rails 4.1.4上测试的,但是从Rails 3开始,这些类显然是相同的。

答案 2 :(得分:0)

考虑像这样使用dst

try

这样post.try(:owner) 关系将返回has_oneowner则不会。

在某些情况下,它可能是不确定的,但对大多数情况来说应该足够了。

has_many只是一个例子:

owner
如果上课class Post has_one :owner class Owner belongs_to :post post = Post.create ... post.try(:owner) owner,则

返回Post;如果上课has_one :owner nil

,则返回Post

对于您的示例: has_many :owners