1

Given User and Book models, I've created a join model, ViewedBook, that contains additional attributes. Below is the essence of what I've come up with:

create_table "users" 
    t.string   "username"
end

create_table "books" 
    t.string   "title"
    t.integer "user_id"
    t.date "authored_date"
end

create_table "books_viewings"
    t.integer  "book_id"
    t.integer  "user_id"
    t.boolean "finished"
    t.date "last_viewed_date"
end

class User 
    belongs_to :book_viewing

    has_many    :authored_books,
                :class_name => "Book",
                :source => :book

    has_many :book_viewings

    has_many    :viewed_books :through => :book_viewings
                :order => "book_viewings.last_viewed_date DESC"

    has_many    :finished_books :through => :book_viewings
                :conditions => "book_viewings.finished = TRUE",
                :order => "book_viewings.last_viewed_date DESC"
end

class Book
    belongs_to :user
    has_one :author, :class_name => "User"
end

class BookViewing
    belongs_to :book
    belongs_to :user
end

I think this works for most of the queries I need to create. However, I want each of the Book objects returned by user.viewed_books to include the finished attribute as well. Further, I will have additional queries like Book.best_sellers that I would also like to scope to a given user so that they also include the finished attribute.

From my limited exposure to ActiveRecord, it appears there's probably an elegant way to manage this and generate efficient queries, but I have yet to find an example that clarifies this scenario.

EDIT: to clarify, the other queries I'm looking for will not themselves be restricted to books that have been finished, but I need to have the finished attribute appended to each book if it exists for the given book and scoped user in book_viewings.

Ken Cooper
  • 851
  • 1
  • 9
  • 17

1 Answers1

2

See my answer here https://stackoverflow.com/a/8874831/365865

Pretty much, no there isn't a specific way to do this, but you can pass a select option to your has_many association. In your case I'd do this:

has_many :books, :through => :book_viewings, :select => 'books.*, book_viewings.finished as finished'
Community
  • 1
  • 1
Bradley Priest
  • 7,438
  • 1
  • 29
  • 33
  • Thanks, Bradley! I think that just might do exactly what I need. I'll verify this later today. – Ken Cooper Feb 15 '12 at 16:27
  • This approach is sadly generating an inner join, so restricts the results to those books that have an associated book_viewing. I clarified the original question to include the fact that I need a left join for most of my queries. – Ken Cooper Feb 16 '12 at 01:02