2011-07-06 4 views
0

リストを取得しようとしていますが、私は例として本を使用します。Rails HABTMが別の条件で結合する

class Book < ActiveRecord::Base 
    belongs_to :type 
    has_and_belongs_to_many :genres 
end 

class Genre < ActiveRecord::Base 
    has_and_belongs_to_many :books 
end 

この例では、すべてのジャンルのリストを表示したいが、最初の列はタイプでなければならない。そう言うジャンルが「スペース」であれば、種類は「ノンフィクション」と「フィクション」可能性があり、それが表示されるでしょう:

Type   Genre  
Fiction  Space 
Non-fiction Space 

ジャンルテーブルのみ「ID」、「名前」があり、 "description"の場合、genres_booksの結合テーブルは "genre_id"と "book_id"を持ち、Bookテーブルは "type_id"と "id"を持っています。私はこれを動作させるのに問題があります。

私がされるであろう必要がありますSQLコードを知っている:

SELECT distinct genres.name, books.type_id FROM `genres` INNER JOIN genres_books ON genres.id = genres_books.genre_id INNER JOIN books ON genres_books.book_id = books.id order by genres.name 

と私は

@genre = Genre.all 
@genre.each do |genre| 
    @type = genre.book.find(:all, :select => 'type_id', :group => 'type_id') 
    @type.each do |type| 

を行うことができ、これは私が各ジャンルやプリントと一緒に種類を見てみましょうだろう見つかりましたそれらを出すことはできましたが、私はそれらを一度にすべて処理することはできませんでした。私は、Genre.allステートメントで何らかの形でグループ化することができれば、ジャンル/タイプの組み合わせを一緒に保ち、さらにそれらを道に沿って使うことができれば理想的だろうと思います。

しかし、この時点で私は周りを走り回っていてどこにもいない。 has_many:throughを使用する必要がありますか?

答えて

1

次の例では、上記で定義したモデルを使用しています。スコープを使用して、関連付けをモデルに戻す必要があります(代わりに、モデル上にクラスメソッドを定義するだけで済みます)。これにより、レコードの取得呼び出しをチェックするのに役立ち、Demeterの法則を守るのに役立ちます。

条件なしに、熱心に各書籍の種類やジャンルをロードし、ブックのリストを取得します。

def Book < ActiveRecord::Base 
    scope :with_types_and_genres, include(:type, :genres) 
end 

@books = Book.with_types_and_genres #=> [ * a bunch of book objects * ] 

をあなたは私があなたの目標を理解していれば、あなただけでは、Rubyの一部を囲いするグループ化を行うことができることをしたらあなたの本は、あなたの視点に渡す必要がある構造に挿入します。

@books_by_type = @books.group_by { |book| book.type } 

# or the same line, more concisely 
@books_by_type = @books.group_by &:type 

@books_by_type.each_pair do |type, book| 
    puts "#{book.genre.name} by #{book.author} (#{type.name})" 
end 
関連する問題