特異クラスの使い方
前の記事の最後に出したコードで特異クラスを使ってます。
def build_book books = Book.joins('LEFT JOIN reviews ON books.id = reviews.book_id'). select('books.id bid, reviews.id rid, reviews.book_id, reviews.body') res = {} books.each { |rec| book = res[rec.bid] if book == nil book = Book.new class << book attr_accessor :reviews end res[rec.bid] = book book.id = rec.bid book.reviews = Array.new end 〜略〜 } res.values end
通常のO-Rマッピングの操作(findなど)でActive Recordが返してくるモデルには、関連先テーブルのデータもフィールドとして含めて返してくれます。
例えば、Bookモデルだったら、BOOKSテーブルと関連するREVIEWSテーブルのデータは、Book.reviews としてモデルを返してくれます。
しかし、今回はBookモデルを自分でnewして、Book.reviewsを持つモデルをつくろうとしてます。
ところが、Bookモデルのクラス定義は以下。
class Book < ActiveRecord::Base has_many :reviews end
自分で普通にnewしたBookモデルでは、reviewsフィールドに値をセットできません。
だからといて、わざわざそのためにクラス定義するのも面倒だし。
そこで特異クラスを使ってみました。 attr_Accessor :reviews を追加定義することで、モデルを再現しています。
本当にこういう使い方でいいのかな?