views:

26

answers:

1

I have currently the following problem in my Rails application (Rails 2.3.5):

  • I want to sort books stored in the application by the author name, then the title of the book.

Book and Author are concrete models, the corresponding tables are Ressources and People. The relevant portion of the schema is (I have stripped down the model a bit):

  create_table "people", :force => true do |t|
      t.string   "sur_name"
      t.string   "pre_name"
      ...
      t.string   "type"
    end

  create_table "people_ressources", :id => false, :force => true do |t|
      t.integer  "ressource_id"
      t.integer  "person_id"
    end

  create_table "ressources", :force => true do |t|
      t.string   "type"
      t.string   "title"
    end

To show the list of books, I have used the following paginator:

@books = Book.paginate(
             :order => 'title', :per_page => 15, :page => params[:page])

My question now is: How should the paginator be constructed so that the books are ordered not by title, but first by author (== person) sur_name? And if that is not easily reachable, what construct would allow to store books and authors as separate entities, but would allow to get a paginator with the defined order?

+1  A: 

Given that you have multiple authors for a book you would need to decide how you determine which is the author whose name should be used to order the list of books.

You could add an association has_one :main_author, :class_name => 'Author' to your Book class defined however you wish (maybe there is a primary author field in people_ressources or maybe you just use the first author available:

has_one :main_author, :through => :author_books, :order => 'sur_name'

Having that has_one association means that you can include that in the pagination and order against the sur_name there:

@books = Book.paginate(:order => "#{Author.table_name}.sur_name", 
                       :per_page => 15, 
                       :page => params[:page])
Shadwell
That looks pretty nice. I will try that (when I have time). I have read a little bit about `has_one` relationship, and it tells that the foreign key goes to the other object (here: the author, which would be wrong). ON http://ar.rubyonrails.org/classes/ActiveRecord/Associations/ClassMethods.html I read that `belongs_to` gets the key. Or is the foreign key held in the relation `people_ressources`? Will check that definitively ...
mliebelt
You would need a `AuthorBook` class (with `belongs_to :author` and `belongs_to :book` on it) to do that. I wasn't sure which associations you had already defined.
Shadwell
I have built a complete new example to check the solution, but failed. I am pretty sure I did not make any errors, I could assign books to authors and vice versae. The error I get is: `SQLite3::SQLException: no such column: authors.sur_name: SELECT "books".* FROM "books" ORDER BY authors.sur_name LIMIT 15 OFFSET 0` when using the paginate call from above. My SQL knowledge is too basic to understand the real reason, but it looks for me that the joined table (authors) with its attributes is missing.
mliebelt