trying_hal9000
trying_hal9000

Reputation: 4403

Rail 3 routing: trouble understanding routes w/ multiple associations

I have a User model, a Book model, an Author model, and an Authorship model. A User has_many Books, and a Book belongs_to a User. The Book has_many :authors through :authorships.

The important thing to remember is that Authors DONT create Books. Users create Books, and assign 1 or more authors to the book. (The author model just has a name column)

Now I'd like routes like this:

/authors   # all authors index
/authors/1/books  # all books with this author
/users/3/authors  # all authors used by user's books
                  # should this be /users/3/books/authors ???
/users/3/author/1/books # all books with author id=1 made by user with ID=3

here's what I came up with, can someone explain where I'm going wrong and how to correct it? Thanks a lot.

routes.rb

    resources :authors do
      member do
        get :books
      end
    end

   resources :users do
     resources :authors do
       member do
         get :books
       end
     end
   end

Upvotes: 1

Views: 44

Answers (1)

sled
sled

Reputation: 14625

turn the books into a resource:

resources :authors do
  resources :books
end

resources :users do
  resources :authors do
    resources :books
  end
end

The tricky thing is the index action in your books/authors controller:

You have to check whether a user_id is supplied or not and join accordingly:

The Authors Controller:

class AuthorsController < ApplicationController

  def index

    if params[:user_id]
      # authors used by this user's books
      @authors  = Author.joins(:authorships).joins('INNER JOIN books ON books.id = authorships.book_id').where(['books.user_id = ?', params[:user_id]]).group('authors.id')
    else
      # all authors
      @authors  = Author.all
    end
  end

end

The BooksController:

class BooksController < ApplicationController

  def index

    if params[:user_id] && params[:author_id]
      # all books with :author_id made by :user_id
      @books  = Book.joins(:authorships).where(['authorships.author_id = ?', params[:author_id]], ['books.user_id = ?', params[:user_id]])
    elsif params[:author_id]
      # all books with :author_id
      @books  = Book.joins(:authorships).where(['authorships.author_id = ?', params[:author_id]])
    else
      # all books
      @books  = Book.all
    end
  end
end

Upvotes: 1

Related Questions