【问题标题】:Rails :include doesn't includeRails :include 不包括
【发布时间】:2011-07-05 00:13:34
【问题描述】:

我的模型:

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 不会有任何好处。我错过了什么?

【问题讨论】:

    标签: ruby-on-rails-3 activerecord include nested-resources active-relation


    【解决方案1】:

    电子邮件在那里。你试过c.emails吗?你会发现没有 Rails 做额外的数据库查询,邮件就在那里。

    :include 所做的事情被称为预加载,这基本上意味着 Rails 将尽最大努力使用它们的关系预填充您的对象,因此当您实际请求关系时不需要额外的数据库查询。

    请参阅此处的“渴望加载关联”部分: http://api.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html

    您可能还想查看此 RailsCast:
    http://railscasts.com/episodes/181-include-vs-joins

    【讨论】:

    • 也许我误解了该方法的目的。我期待它在属性旁边返回每个contact 内部的emails。我的目标是在我的索引操作中提供所有联系人的 JSON 表示,包括嵌套的电子邮件属性。有什么建议吗?
    • 取决于“每个联系人内部”的含义。我想你可能误解了,但这仍然是你想要为你的案子做的事情。它只是以最适合您的方式预加载所有电子邮件。因此,当您执行Contact.find(:all, :include =&gt; :emails) 时,您将获得附加到每个联系人的电子邮件(通过关联,而不是作为联系人中的直接属性)。在此之后为什么不这样做:Contact.find(:all, :include =&gt; :emails).to_json(:include =&gt; :emails)。这应该可以解决问题。
    • 此处描述的其他 to_json() 技巧:apidock.com/rails/ActiveRecord/Serialization/to_json
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2018-07-18
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2016-02-21
    • 1970-01-01
    • 2011-01-04
    相关资源
    最近更新 更多