josh
August 15, 2008, 4:07pm
1
Hi all
I’m quite new to RESTful Rails and tried a bit with a new app, but it
seems I don’t comprehend something yet.
I have the following two models:
class CompactDisc < ActiveRecord::Base
belongs_to :genre
validates_presence_of :genre
end
class Genre < ActiveRecord::Base
has_many :compact_discs
end
In routes.rb I have the following route:
ActionController::Routing::Routes.draw do |map|
map.resources :compact_discs
map.resources :genres do |genre|
genre.resources :compact_discs, :name_prefix => ‘genre_’
end
…
end
When opening localhost:3000/compact_discs it shows me all CD’s. When
opening localhost:3000/genres/1/compact_discs it still shows me all
CD’s! Shouldn’t it only display the ones that are associated to genre 1
now? Or did I miss something?
I also played with
map.resources :genres, :has_many => :compact_discs
but this didn’t help me neither…
Thanks for help
Josh
josh
August 15, 2008, 6:02pm
2
On Aug 15, 9:07 am, Joshua M. [email protected]
wrote:
end
map.resources :genres do |genre|
genre.resources :compact_discs, :name_prefix => ‘genre_’
end
…
end
Those routes look good…
Thanks for help
Josh
Posted viahttp://www.ruby-forum.com/.
When you have nested routes, Rails handles almost everything for
you, but you need to adjust your index action to be aware of the
“parent” resource:
def index
if params[:genre]
@genre = Genre.find(params[:genre])
@compact_discs = @genre.compact_discs
else
@compact_discs = CompactDisc.find(:all)
end
continue code here
end
In other words, you want to detect if you’re nested inside a genre,
and in that case, only show the discs for that genre.
There are more elegant ways to do this, too (many people use a
before_filter, etc.)
Does this help at all?
Jeff
REST with Rails: Oct 4, 2008, Austin, TX
http://www.purpleworkshops.com/workshops/rest-and-web-services
josh
August 15, 2008, 7:34pm
3
Does this help at all?
Jeff
Thanks a lot, Jeff. Can you point me into some “best practices” on how
to make this work? before_filter etc…?
josh
August 15, 2008, 7:43pm
4
Joshua M. wrote:
Does this help at all?
Jeff
Thanks a lot, Jeff. Can you point me into some “best practices” on how
to make this work? before_filter etc…?
Well, created one myself. You think this is safe and clean/DRY?
private
def prepare_compact_discs
genre = (params[:genre_id] ? Genre.find(params[:genre_id]) : nil)
@compact_discs = (genre ? genre.compact_discs :
CompactDisc.find(:all))
end
Btw, in your example before you should have used params[:genre_id], not
only params[:genre]. Thanks anyway.
josh
August 15, 2008, 11:56pm
5
Again, I don’t think there’s a right or wrong necessarily - whatever
you think keeps the code the clearest.
Thanks, interesting ways! Let’s me feel like a complete newbie again
and again
josh
August 15, 2008, 8:45pm
6
On Aug 15, 12:43 pm, Joshua M. [email protected]
wrote:
private
def prepare_compact_discs
genre = (params[:genre_id] ? Genre.find(params[:genre_id]) : nil)
@compact_discs = (genre ? genre.compact_discs :
CompactDisc.find(:all))
end
It’s probably a matter of taste, but I tend to recommend something
like this:
before_filter :find_genre
def index
@compact_discs = @genre ? @genre.compact_discs ||
CompactDisc.find(:all)
…
end
def find_genre
@genre = Genre.find_by_id(params[:genre_id]) # returns nil if not
foun
end
Some people prefer this:
before_filter :load_for_genre
def index
Find all discs only if we don’t have any yet
@compact_discs ||= CompactDisc.find(:all)
end
def load_for_genre
@compact_discs = Genre.find(params[:genre_id]).compact_discs if
params[:genre_id]
end
Again, I don’t think there’s a right or wrong necessarily - whatever
you think keeps the code the clearest.
Btw, in your example before you should have used params[:genre_id], not
only params[:genre]. Thanks anyway.
Good catch.
Jeff
REST with Rails: Oct 4, 2008, Austin, TX
http://www.purpleworkshops.com/workshops/rest-and-web-services