0

我的模型:Rails的:包括不包括

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: "[email protected]", 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不會有任何好處。我錯過了什麼?

回答

1

電子郵件在那裏。你試過c.emails嗎?你會發現電子郵件將在那裏沒有Rails做額外的數據庫查詢。

:include所做的事情被稱爲預熱加載,這基本上意味着Rails將嘗試一種預填充對象與它們的關係的最佳方法,以便在實際要求關係時不需要額外的DB查詢。

參看「協會的預先加載」在這裏: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

你可能也想看看這個RailsCast:
http://railscasts.com/episodes/181-include-vs-joins

+0

也許我理解錯了方法的目的。我期待它將每個「聯繫人」中的「電子郵件」與屬性一起返回。我的目標是提供索引操作中所有聯繫人的JSON表示,包括嵌套的電子郵件屬性。有什麼建議? –

+0

取決於「每個聯繫人內部」的含義。我想你可能會誤解,但這仍然是你想要爲你的情況做的。它只是以最好的方式爲您預載所有電子郵件。所以當你做'Contact.find(:all,:include =>:emails)'時,你會得到附加到每個聯繫人的電子郵件(通過關聯,而不是聯繫人中的直接屬性)。之後,爲什麼不這樣做:'Contact.find(:all,:include =>:emails).to_json(:include =>:emails)''。這應該夠了吧。 – Casper

+1

附加'to_json()'技巧在這裏描述:http://apidock.com/rails/ActiveRecord/Serialization/to_json – Casper