Rails:include不包含 [英] Rails :include doesn't include
问题描述
我的模特:
class Contact < ActiveRecord::Base
has_many :addresses
has_many :emails
has_many :websites
accepts_nested_attributes_for :addresses, :emails, :websites
attr_accessible :prefix, :first_name, :middle_name, :last_name, :suffix,
:nickname, :organization, :job_title, :department, :birthday,
:emails_attributes
end
class Email < ActiveRecord::Base
belongs_to :contact
validates_presence_of :account
validates_format_of :account, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create
attr_accessible :contact_id, :account, :label
end
如果我运行以下查询,则会按预期返回emails
:
c = Contact.find(3)
Contact Load (3.2ms) SELECT `contacts`.* FROM `contacts` LIMIT 1
=> #<Contact id: 3, prefix: nil, first_name: "Micah", middle_name: nil, last_name: "Alcorn", suffix: nil, nickname: nil, organization: nil, job_title: nil, department: nil, birthday: nil, created_at: "2011-07-04 23:50:04", updated_at: "2011-07-04 23:50:04">
c.emails
Email Load (4.4ms) SELECT `emails`.* FROM `emails` WHERE `emails`.`contact_id` = 3
=> [#<Email id: 3, contact_id: 3, account: "not@real.address", label: "work", created_at: "2011-07-04 23:50:04", updated_at: "2011-07-04 23:50:04">]
但是,尝试建立:include
关系不会:
c = Contact.find(3, :include => :emails)
Contact Load (0.5ms) SELECT `contacts`.* FROM `contacts` WHERE `contacts`.`id` = 3 LIMIT 1
Email Load (0.8ms) SELECT `emails`.* FROM `emails` WHERE `emails`.`contact_id` IN (3)
=> #<Contact id: 3, prefix: nil, first_name: "Micah", middle_name: nil, last_name: "Alcorn", suffix: nil, nickname: nil, organization: nil, job_title: nil, department: nil, birthday: nil, created_at: "2011-07-04 23:50:04", updated_at: "2011-07-04 23:50:04">
如您所见,正在执行SQL,但未返回电子邮件.我打算返回所有包含电子邮件的联系人,因此:joins
不会有任何好处.我想念什么?
电子邮件在那里.您尝试过c.emails
吗?您会发现,电子邮件将在那里,而Rails不会执行其他数据库查询.
:include
所做的事情被称为急切加载",这基本上意味着Rails将尝试一种尽力而为的方法,即用对象的关系预填充对象,这样,当您实际请求该关系时,就不需要其他数据库查询了./p>
在此处查看"关联的快速加载"部分: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
您可能还需要查看以下RailsCast:
http://railscasts.com/episodes/181-include-vs-joins
My models:
class Contact < ActiveRecord::Base
has_many :addresses
has_many :emails
has_many :websites
accepts_nested_attributes_for :addresses, :emails, :websites
attr_accessible :prefix, :first_name, :middle_name, :last_name, :suffix,
:nickname, :organization, :job_title, :department, :birthday,
:emails_attributes
end
class Email < ActiveRecord::Base
belongs_to :contact
validates_presence_of :account
validates_format_of :account, :with => /\A([^@\s]+)@((?:[-a-z0-9]+\.)+[a-z]{2,})\Z/i, :on => :create
attr_accessible :contact_id, :account, :label
end
If I run the following query, the emails
are returned as expected:
c = Contact.find(3)
Contact Load (3.2ms) SELECT `contacts`.* FROM `contacts` LIMIT 1
=> #<Contact id: 3, prefix: nil, first_name: "Micah", middle_name: nil, last_name: "Alcorn", suffix: nil, nickname: nil, organization: nil, job_title: nil, department: nil, birthday: nil, created_at: "2011-07-04 23:50:04", updated_at: "2011-07-04 23:50:04">
c.emails
Email Load (4.4ms) SELECT `emails`.* FROM `emails` WHERE `emails`.`contact_id` = 3
=> [#<Email id: 3, contact_id: 3, account: "not@real.address", label: "work", created_at: "2011-07-04 23:50:04", updated_at: "2011-07-04 23:50:04">]
However, attempting to :include
the relationship does not:
c = Contact.find(3, :include => :emails)
Contact Load (0.5ms) SELECT `contacts`.* FROM `contacts` WHERE `contacts`.`id` = 3 LIMIT 1
Email Load (0.8ms) SELECT `emails`.* FROM `emails` WHERE `emails`.`contact_id` IN (3)
=> #<Contact id: 3, prefix: nil, first_name: "Micah", middle_name: nil, last_name: "Alcorn", suffix: nil, nickname: nil, organization: nil, job_title: nil, department: nil, birthday: nil, created_at: "2011-07-04 23:50:04", updated_at: "2011-07-04 23:50:04">
As you can see, the SQL is being executed, but the emails are not being returned. I intend to return all contacts with each containing email(s), so :joins
won't do any good. What am I missing?
The emails are there. Did you try c.emails
? You will find that the emails will be there without Rails doing an additional DB query.
The thing that :include
does is called eager loading, which basically means Rails will try a best effort method of prepopulating your objects with their relations, so that when you actually ask for the relation no additional DB queries are needed.
See the section "Eager loading of associations" here: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html
You might also want to check out this RailsCast:
http://railscasts.com/episodes/181-include-vs-joins
这篇关于Rails:include不包含的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!