Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
371 views
in Technique[技术] by (71.8m points)

sql - Rails includes with conditions

Is is possible in Rails > 3.2 to add conditions to the join statement generated by the includes method?

Let's say I have two models, Person and Note. Each person has many notes and each note belong to one person. Each note has an attribute important.

I want to find all the people preloading only the notes that are important. In SQL that will be:

SELECT *
FROM people
LEFT JOIN notes ON notes.person_id = people.id AND notes.important = 't'

In Rails, the only similar way to do that is using includes (note: joins won't preload notes) like this:

Person.includes(:notes).where(:important, true)

However, that will generate the following SQL query which returns a different result set:

SELECT *
FROM people
LEFT JOIN notes ON notes.person_id = people.id
WHERE notes.important = 't'

Please, notice that the first resultset includes all the people and the second one only the people associated to important notes.

Also notice that :conditions are deprecated since 3.1.

See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Reply

0 votes
by (71.8m points)

According to this guide Active Record Querying

You can specify conditions on includes for eager loading like this

Person.includes(:notes).where("notes.important", true)

It recommends to use joins anyway.

A workaround for this would be to create another association like this

class Person < ActiveRecord::Base
  has_many :important_notes, :class_name => 'Note', 
           :conditions => ['important = ?', true]
end

You would then be able to do this

Person.find(:all, include: :important_notes)

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
OGeek|极客中国-欢迎来到极客的世界,一个免费开放的程序员编程交流平台!开放,进步,分享!让技术改变生活,让极客改变未来! Welcome to OGeek Q&A Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...