2013-04-19 19 views
6

ActiveRecordの関連付けから特定の列のみを要求することはできますか?

def Foo 
    has_one :user 
end 

考えるのは、他の列のいずれかの私はFooUserの名前をしたいと言って、ないようにしましょう。私は1つの列のみを取得するために、関連付けを使用するための任意の滑らかな方法がある

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

をしたいが、foo.user.nameを行うと、私に

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

を与えるのだろうか?これまでわずかな値を返します

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

:あなたが好き、.selectメソッドを使用して選択したい列を指定することができます

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

答えて

4

を一般的には:いない場合は、私がしなければなりません名前列。これを関連付けにチェーンすることはできますが、インスタンスに連結することはできません。だから、meagarが他の回答(森の削除された回答を含む)をdownvotingすることによって非常に積極的に指摘したように、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からすべての列をロードせずに。

+0

これは代表的な範囲ですか?スコープは、通常、ActiveRecord :: Relationを返します。メソッドはより適切でしょうか(またはデリゲート?) – MrYoshiji

+0

これはActiveRecordクエリメソッドのチェーンなので、関係を返すと思います。代わりにBarクラスに構築されたリレーションを返すというのは奇妙なことですFooクラスの - しかし、一度あなたは '何かに行ってきた。メソッドを定義することも、これを達成するための良い方法です。私はこのようなことをする必要は決してありませんでした。だから、どちらが良いか、なぜそうなのか、という基準の枠は本当にありません。 – Andrew

1

いいえ、has_oneの場合は、has_manyの場合はyesです。

has_oneアソシエーションで返されるオブジェクトは、has_manyのように、追加のメソッドをselectのように連結できるスコープではありません。これはモデルの実際のインスタンスであり、インスタンス化するには必ずselect *が必要です。

名前だけを選択する場合は、Userモデルに直接アクセスし、selectを使用する必要があります。あなたのFooは多くのusersを持っている場合

逆に、あなたは実際 ActiveRecordの関連付けではなく、モデルのインスタンスになりfoo.usersとして、foo.users.select("name")または他のチェーン可能のいずれかの方法を使用することができます。

関連する問題