Another noob question

Hi!

I’m very new to rails and try to set up a simple app with artists and
their songs, for learning.

I have nested routes for some actions to get urls like example.com/
ackord/artistname/songname
And I also have some non-nested routes. It looks like this:

resources :artists, :path => “ackord” do
resources :songs, :path => “”, :only =>
[:index, :edit, :show, :update]
end

resources :songs, :only => [:new, :create, :destroy]

match “skicka-in-analys” => “songs#new”, :as => :new_song

So far so good!

Now I want to create a list of, say, the 30 latest songs added to my
site. I’m trying to be restful and not add new actions, so how do I
achieve this? It is a index action but with some extra filters
like …limit(30) and order(“created_at DESC”) and so on.

This action won’t depend on the artist though and therefor shouldn’t
be nested inside the artists. Since my regular index action IS nested
with artists I have all these @artist variables in my view which gives
me errors, of course.

So, how do I achieve what I want? Special action or not?

A kick in the right direction would be awesome. I want to learn “the
right way” from the beginning.

Best Regards
Linus

On Mar 24, 3:23pm, Linus P. [email protected]
wrote:

Now I want to create a list of, say, the 30 latest songs added to my
site. I’m trying to be restful and not add new actions, so how do I
achieve this? It is a index action but with some extra filters
like …limit(30) and order(“created_at DESC”) and so on.

Yes, you’ll pass in a param (i.e. “/songs/?limit=30”) and then use
params[:limit] when doing your query. Note that if you plan on using
some type of UI front end (say jQuery dataTables) they’ll usually have
some API for param names they’ll send, so if you have no better names
to choose from you can just set them to your UI front end so you don’t
need to translate.

This action won’t depend on the artist though and therefor shouldn’t
be nested inside the artists. Since my regular index action IS nested
with artists I have all these @artist variables in my view which gives
me errors, of course.

So, how do I achieve what I want? Special action or not?

You should definitely use the index action and not a special action
since you’re still doing a GET for the collection of songs, which
doesn’t get more RESTfully pointing to the index action.

The basic premise of what you want to do is wherever you look for
songs you need to predicate on params[:artist_id]; if its present you
should get and store @artist and then do @artist.songs.all(:condtions
=> …), etc.; if its not present then you should do
Song.all(:conditions => …). For rendering it really depends on
whether you can have one view that renders a collection of songs (and
in the case of artists/5/songs they all happen to be by one artist) or
if there is a truely different view you want to render. If its the
later, you just predicate your respond_to block on params[:artist_id]
as well and render either index_with_artist or index (names up to you
of course). If those share a lot of things you can move the common
items to partials and then those templates will be calls out to the
partials, where the with_artist one renders the artist partial whereas
the regular index doesn’t.

If you go at all this haphazardly the bookkeeping here can be a bit
daunting for all the predication and whatnot, so I’d recommend taking
a look at make_resourceful or InheritedResource gems. You can choose
to use them or not (they would help you with this problem as well as
others), but they both handle optional parents so you can look at
their code and what they do to see some good patterns for keeping your
code DRY. For example make_resourceful defines something like (in lib/
resourceful/default/accessors.rb):

def current_model
if !parent?
current_model_name.constantize
else
parent_object.send(instance_variable_name)
end
end

You should trace down all those function calls, but basically now
everywhere you were going to do if params[:artist_id] then
@artists.songs.find(…) else Song.find(…), you can now just do
current_model.find(…). I’m not as familiar with InheritedResource
but both do this similarily in my understanding and both have chosen a
good set of utility functions you’d want any controller handling the
problem you describe to have.

HTH,
\Peter