ActiveRecord,通过多态属性查找

时间:2013-02-07 14:35:20

标签: ruby ruby-on-rails-3 activerecord active-record-query

有这个:

class Event < ActiveRecord::Base
  belongs_to :historizable, :polymorphic => true
end

user = User.create!

我可以:

Event.create!(:historizable => user)

但我不能:

Event.where(:historizable => user)
# Mysql2::Error: Unknown column 'events.historizable' in 'where clause'

我必须这样做:

Event.where(:historizable_id => user.id, :historizable_type => user.class.name)

更新

重现问题的代码:https://gist.github.com/fguillen/4732177#file-polymorphic_where_test-rb

3 个答案:

答案 0 :(得分:3)

  

这已在Rails master中实现,并将在   Rails 4.谢谢。

- @carlosantoniodasilva

答案 1 :(得分:0)

我这样做:

user.events

这是一个正确的AR查询,您可以将其与其他范围和内容链接起来:

user.events.where(<your event conditions here>)

编辑:AFAIK反过来说你必须指定两个字段(有意义:你可以有一个id为4的用户和另一个有事件的东西,比如Party,也有id 4)。

EDIT2:关于“为什么create有效且where没有”:createwhere更高级,因为前者涉及“完整的模型” “,而后者在数据库表级别管理事物。

  1. ActiveRecord的create(AFAIK)在某处使用了new + update_param的组合。
  2. update_param使用您的模型xxxx=方法分配每个属性。
  3. 在您的示例中,historizable=是由belongs_to表达式构建的方法。由于belongs_to“知道”它是多态的,它可以处理类型和id。
  4. 另一方面,当您将散列传递给where子句时,中的参数仅引用数据库字段。 Rails提供了“更高级别”访问的范围:

    class Event < ActiveRecord::Base
      ...
    
      scope :by_historizable, lambda { |h| where(:historizable_id => h.id, :historizable_type => h.class.name) }
    
    end
    
    ...
    
    Event.by_historizable(user).where(<your other queries here>)
    

    我听说在Rails 4中可能会有所改变,而where可能更“智能”。但我还没有检查过。

答案 2 :(得分:-2)

尝试:

Event.joins(:historizable).where(:historizable => {:historizable_type => user})