Reputation: 4403
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
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