2016-07-08 4 views
1

モデルUserfirst,lastおよびloginを属性として持ちます。またnameというメソッドがあり、firstlastが結合されています。選択された属性を持つハッシュの配列としてActiveRecordクエリ結果を取得します

私が望むのは、Usersレコードを繰り返して、必要な属性を持つハッシュの配列を作成することです。これと同じように:

results = [] 
User.all.map do |user| 
    record = {} 
    record["login"] = user.login 
    record["name"] = user.name 
    results << record 
end 

これを行うにはRubyでクリーンな方法はありますか?

+0

どのRDBMSを使用していますか? (MySQL、Postgres) – potashin

答えて

1

私が書くでしょう:

results = User.all.map { |u| { login: u.login, name: u.name } } 
+0

ありがとう!私は 'users.map {| u | {"login" => u.login、 "name" => u.name}} '私は文字列であり記号ではないためにキーが必要だったからです。 – Breno

1

あなたがActiveRecord::QueryMethods#selectActiveRecord::Relation#as_jsonを使用することができます。

User.select(:login, '(first || last) as name').as_json(except: :id) 
+1

これは涼しいですが、レコードの作成には役に立たない1つの大きなハッシュを作成します。また、 'ActiveRecord_Relation'を返し、to_hashメソッドはerorrを発生させます。 –

+0

@Зелёный:ちょっとポイントだったのですか、何か不足していますか?レコード作成の前提と一緒に、私は推測します。 – potashin

+0

'User.select(:id、:name).map(&:attributes)'はここでは作品コードです。 –

0

何をしたいんActiveRecord::Result#to_hash不十分という名前と悪い文書化する方法を、私は思います。それは実際にはto_hashという名前のメソッドのためにかなり貧弱な形を思わハッシュの配列を、返さないため不十分という名前

User.select(:login, :name).to_hash 

+0

'to_hash'は、結果セットであり、未処理のクエリを実行するときに返されるもので、リレーションではありません。 –

+0

また、nameは属性ではなく、文字列を返すメソッドです。 – Breno

2

User.allにマップしようとすると、パフォーマンス上の問題が発生する可能性があります(後で説明します)。すべてのUserオブジェクトをインスタンス化しないようにするには、pluckを使用して直接DBからデータを取得し、マップします。

results = User.all.pluck(:login, :first, :last).map do |login, first, last| 
    { 'login' => login, 'name' => first << last } 
end 

すべてのユーザーをインスタンス化することは問題になります。 as_jsonの関係方法でさえもやっています。このメソッドを使用すると、そこにいるユーザーの数に応じて問題が発生することさえあります。

また、これはUser#nameが実際にはfirst + lastであることを前提としています。異なる場合は、ブロック内のロジックを変更することができます。

+0

はい、私は実際に 'User.all'を使用しません。特定のクエリの結果ですが、User.allを質問に入れるのは、ユーザモデルの戻り値:レコードが何であるかを問わず単純化するだけです。あなたの答えも正しいですが、@スピッカーマンが最初に答えました。 +1してありがとう! – Breno

+0

問題ありません。大きなクエリの場合は、パフォーマンスへの影響に注意してください。 –

+0

これはオートコンプリートのための特定のクエリです。最悪の場合、数十の結果が返されます。 – Breno

関連する問題