包含与连接表上的where子句的belongs_to关系

时间:2015-07-02 19:01:32

标签: sql ruby-on-rails activerecord

我似乎无法通过这个思考。如何使用与外卡的belongs_to关系运行where子句?

require 'pry'
require 'active_record'
require 'sqlite3'

connection = ActiveRecord::Base.establish_connection(
  adapter: 'sqlite3',
  database: ":memory:",
  verbosity: 'quiet'
)

class CreateOwners < ActiveRecord::Migration
  def change
    create_table(:owners) do |t|
      t.string :name
      t.date :birthday
    end
  end
end

class CreateDogs < ActiveRecord::Migration
  def change
    create_table(:dogs) do |t|
      t.string :name
      t.belongs_to :owner
    end
  end
end

CreateOwners.new.migrate(:up)
CreateDogs.new.migrate(:up)

class Dog < ActiveRecord::Base
  belongs_to :owner
end

class Owner < ActiveRecord::Base
  has_many :dogs
end

这会引发错误

ar = Dog.includes(:owner).where("owners.birthday < ?", Date.today)
ar.inspect #=>SQLException: no such column: owners.birthday

但是在包含之前加入似乎有用吗?

ar = Dog.joins(:owner).includes(:owner).where("owners.birthday < ?", Date.today)
ar.inspect #=> [] (which is correct)

2 个答案:

答案 0 :(得分:0)

试试这个。我认为这在你的位置上是一个简单的错字。

ar = Dog.includes(:owner).where("owner.birthday < ?", Date.today)

答案 1 :(得分:0)

所以我最终偶然发现了我的答案。这是includes通过委派给preloadeager_load而在幕后工作的方式。关于它,这是一个很好的blog post。包含未检测到包含模型上调用的where子句,因此未加入查询中的表 - 它调用preload而不是eager_load来激活一个查询,并且与joins(:owner).includes(:owner)

相同

我不知道这是AR中的错误还是我对AR的浅薄理解。

所以我的查询应该是:

Dog.eager_load(:owner).where("owner.birthday < ?", Date.today)

修改

所以我离开了一点。 eager_load调用左外连接,这不是我想要的 - 但是由于where子句我很幸运。如果你想强制一个内连接,那么连接和包含实际上是正确的方法,虽然由于某种原因仍然感觉很奇怪。

这是另一个有助于澄清的resource