【问题标题】:Is it possible to ask for only certain columns from an ActiveRecord association?是否可以只要求 ActiveRecord 关联中的某些列?
【发布时间】:2013-04-13 06:40:51
【问题描述】:

考虑

def Foo
  has_one :user
end

假设我只想要一个FooUser 的名称,而不是任何其他列。所以我想要

SELECT name FROM "users" WHERE "prices"."id" = 123

但是做foo.user.name会给我

SELECT * FROM "users" WHERE "prices"."id" = 123

是否有任何巧妙的方法可以使用关联来仅获取一列?如果没有,那么我必须这样做:

User.where(id: foo.user_id).pluck(:name).first

【问题讨论】:

    标签: ruby-on-rails ruby activerecord associations


    【解决方案1】:

    一般情况下,您可以使用 .select 方法指定要选择的列,例如:

    User.select(:name).where(...)
    

    这将只返回名称列中的值。您可以将其链接到关联上,但不能链接到实例上。因此,正如 meagar 通过否决其他答案(包括 Mori 已删除的答案)非常激进地指出的那样,在 has_one 关系中,您不能将其链接到关联上(因为在这种情况下它不是关联)。但是,您可以构建一个自定义范围,如下所示:

    class Foo < ActiveRecord::Base
      has_one :bar
      scope :bar_name, lambda {Bar.select(:name).where(:foo_id=> id)}
    end
    

    以上内容未经测试,因此您可能需要对其进行调整,但一般来说,这种方法可以让您执行以下操作:

    foo.bar_name
    

    ...不从 Bar 加载所有列。

    【讨论】:

    • 这个范围是否具有代表性?范围通常返回一个 ActiveRecord::Relation,无论是否为空。一个方法会更合适(或委托?)
    • 嗯,这是一个 ActiveRecord 查询方法链,所以我认为它正在返回一个关系——唯一奇怪的是它会返回一个建立在 Bar 类而不是 Foo 类上的关系- 但是一旦你去了something.otherthing.where(),无论如何你都会这样做。不过,定义一个方法也是实现此目的的好方法。我从来不需要做这样的事情,所以我真的没有一个参考框架来说明哪个更好或为什么更好。
    【解决方案2】:

    不,对于您的has_one,但对于has_many 是。

    has_one 关联返回的对象不是一个范围,您可以在其上链接其他方法,例如select,例如has_many。它是模型的实际实例,实例化它必然涉及select *

    如果您只想选择名称,则必须直接访问 User 模型并使用 select

    相反,如果您的Foo 有许多users,您可以使用foo.users.select("name") 或任何其他可链接的方法,因为foo.users 将是一个实际 ActiveRecord 关联,而不是模型实例。

    【讨论】:

      猜你喜欢
      • 2011-05-09
      • 2011-03-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2013-11-18
      • 2012-12-22
      • 1970-01-01
      • 2023-01-15
      相关资源
      最近更新 更多