2017-04-25 16 views
0

の関連するモデルにネストされた属性を追加します。私の見解では私はActive Recordの関連付けを使用して3機種持っRailsの

Book Model 
has_many :checkouts 

User Model 
has_many :checkouts 

Checkout Model 
belongs_to :book 
belongs_to :user 

を、私はチェックアウトから書籍、チェックアウト、およびユーザー名を必要とします。

#<ActiveRecord::AssociationRelation 
    [#<Checkout id: 30, 
    checkout_date: "2017-04-13", 
    return_date: nil, 
    book_id: 118, 
    user_id: 1, 
    created_at: "2017-04-13 17:43:07", 
    updated_at: "2017-04-13 17:43:07" 
    >,#<Checkout id: 50, 
    checkout_date: "2017-04-13", 
    return_date: nil, 
    book_id: 118, 
    user_id: 1, 
    created_at: "2017-04-14 00:33:34", 
    updated_at: "2017-04-14 00:33:34"> 
    ]> 

をしかし、私は、ユーザー名だけでなく、IDに希望:

Book.first.checkoutsを使用することにより、私が得ます。私はBook.first.checkouts.map { |c| c.user.name }を試しましたが、それは名前だけを返すので、残りのチェックアウト情報が必要です。

{ 
    name: "Book Name", 
    checkouts: [ 
    checkout_data: "Today", 
    user_name: "Mary" 
    ] 
} 

がどのように私は私のチェックアウトデータにユーザー名を追加することができます。理想的には、(JSONに変換)私のデータは、何かのように見えますか?

+0

チェックアウトを個別に表示していますか?つまり、「.each」ループですか? 'checkout.user.name' – Okomikeruko

+0

@Okomikeruko yesを各ループを通して個別に表示できるはずです。 'checkout.user.name'は動作しますが、ユーザー名だけが返されます。チェックアウトとユーザー名の両方が必要です。私はそれを仮想属性に追加することができるかどうか、それと同じように思っています。 – BHOLT

+0

私は2つのオブジェクトのデータを結合しようとしていると思います: 'checkouts'と' user' – BHOLT

答えて

1

あなたのコントローラでこれを試すことができます。

render json: @books, include: { checkout: { only: :checkout_date, include: { user: { only: :name } } }}

+0

この!それは本当にいいです – BHOLT

0

あなたは(N + 1)を防止するためにデータをプリロードする必要があり、クエリの問題、特定の書籍の表示可能なチェックアウトの場合 :

book_id = <given book id> 
book = Book.find(book_id) 
checkouts = book.checkouts.includes(:user) 
return_hash = {name: book.name, checkouts: []} 
checkouts.each do |checkout| 
    return_hash[:checkouts] << { checkout_data: checkout.checkout_date, 
           user_name: checkout.user.name 
           } 
end 
+0

これは私が試していたもののようなものですが、より単純な方法があるかどうか疑問に思いました。 N + 1クエリの問題は何ですか? – BHOLT

+1

checkout.userは、チェックアウトごとに1つのクエリをデータベースに送信します。includes:usersを使用すると、すべての対応するユーザーが1つのINクエリでプリフェッチされます。 – aqfaridi

0

他のソリューションを含めると、これはかなりうまくいくことがわかりました:

checkouts = book.checkouts.unreturned.map do |checkout| 
    checkout.attributes.merge({ user_name: checkout.user.name }) 
end 

{ checkouts: checkouts, available: book.available?, book_id: book.id } 

attributes.mergeトリックしました。

+0

使用しません。私はアプリケーションで同じパフォーマンスの問題に直面した、あなたのコードのボトルネックを見るためにruby-profを使用してください – aqfaridi

関連する問題