属性:id, :first_name, :last_name, and :email
を持つUser
モデルがあるとしましょう。私のアプリケーションでは、ゲストユーザーにはUser's email and last_name
が表示されません。ユーザーのリストが必要な場合に特定の値を選択する方法は知っていますが、特定のユーザーの特定の属性を取得する方法はわかりません
User.find_by(id: 5).select(:id, :first_name).
その解決策の1つはユーザーです
User.find_by(id: 5).attributes.slice('id', 'first_name')
しかし、その後、私はARレコードの代わりにハッシュを取得します。私はそれをできた
User.select(:id, :first_name).find_by(id: 1)
しかし、最初にユーザーを知る必要があるため、どのフィルターをフィルター処理する必要があるかがわかりません。
私たちを手伝ってくれますか?
アクティブなレコードインスタンスではなく配列が必要な場合は、Chocoが言ったことは機能します。アクティブなレコードインスタンスが必要な場合は、以下を実行します。
_User.where(id: 5).select(:id, :first_name).take
_
詳細はこちらをご覧ください。あなたがどれだけ知っているかわからないので、私はあなたがより多くではなくより少ない知識を仮定します。
上でやっていることはメソッドチェーンであることに気づいていると思います。つまり、メソッドを呼び出してから、最初のメソッドの結果で別のメソッドを呼び出しています。例えば:
_User.find_by(id: 5).attributes.slice('id', 'first_name')
_
User
クラスで_find_by_id
_メソッドを呼び出しています。このメソッドは、User
クラス(つまり、アクティブなレコードインスタンス)のインスタンスを返します。そのインスタンスにはattributes
というメソッドがあり、これを呼び出します。 attributes
メソッドは、前のアクティブレコードインスタンスのフィールドを表すHash
クラスのインスタンスを返します。 Hash
にはslice
メソッドがあり、このメソッドを順番に呼び出します。 slice
メソッドは、指定したフィールドのサブセットを含むHash
の別のインスタンスを返します。
したがって、明確にするべき概念は、メソッドをチェーンするとき、同じもので後続の各メソッドを呼び出すのではなく、チェーン内の前のメソッドの戻り値で呼び出すということです。
OK、それで邪魔にならないように:
すべてのfind
メソッドは、データベースを照会し、Active Recordモデルの単一のインスタンス、またはActive Recordモデルの複数のインスタンスを含むプレーンRuby配列を返すことを目的としています。
他の多くのメソッド-select
、where
などは、すぐにデータベースにヒットすることはなく、アクティブなレコードインスタンスを返すことを意図していません。それらはすべて_ActiveRecord::Relation
_のインスタンスを返します。 _ActiveRecord::Relation
_は、特定の条件に一致する可能性のあるレコードのグループのようなもので、追加の条件を追加できます。これは、「発生を待機しているデータベースクエリ」、または「まだ発生していない可能性があるデータベースクエリ」のようなものです。
_ActiveRecord::Relation
_でwhere
、order
、select
などのメソッドを呼び出すと、_ActiveRecord::Relation
_のインスタンスが返されます。つまり、同じクラスのインスタンスを取得し、そのクラスのメソッドをチェーンできます。素敵な例:User.where(name: 'Fred').select(:id, :name).order('name ASC')
_ActiveRecord::Relation
_のインスタンスは非常にスマートであり、each
、all
、take
など、今すぐレコードが必要であることを明確に示すメソッドを呼び出すまで、データベースにアクセスすることはありません。
それで、ここで計画していたよりもずっと長く行ったので、まとめます。以下に、最初に言及したコードを示します。詳細は、以下のコメントで詳しく説明します。
_User.where(id: 5).select(:id, :first_name).take
_
分解する:
_my_relation = User.where(id: 5)
# The database will not have been hit yet - my_relation
# is a query waiting to happen
my_second_relation = my_relation.select(:id, :first_name)
# The database has STILL not been hit.
# the relation now contains both the conditions
# from the previous my_relation, and the new 'select'
# criteria we specified
my_user = my_second_relation.take
# OK, 'take' means we want the first record
# matching all our criteria,
# so my_second_relation will hit the database
# to get it, and then return an Active Record
# instance (ie, an instance of the User class)
_
うわー...私は予想よりも長く行った。そのうちのいくつかが役に立つことを願っています!
これを試して:
User.where(id: 5).pluck(:id, :first_name)
idとfirst_nameの値を含む配列を返します
これも同様に機能します
User.select(:id, :first_name).find(5)