Is ActiveResource buggy or am I ?

Hi, I'm currently working with ActiveResource and I have some troubles with it. I have two models on the server side, Artist and Song

Songs: belong_to :artist and Artist: has_many :songs

I also have two controllers methods : A method songs in the ArtistsController that return his songs and a list_by_artist in the SongsController that return all the songs for an artist.

All of this is Restful.   map.resources :artists, :member => {:songs => :get}   map.resources :songs, :collection => {:list_by_artist => :get}

I know that these two methods does the same thing and I will keep only one of them at the end but :

I wan't to be able to retrieve all the songs of an artist in the client side (with ActiveResource) as Songs objects

I can do : Artist.find(1).get(:songs) to retrieve an Array but Artist.find(1).find(:songs) gives me a NoMethodError for the find method

I can also do

Song.get(:list_by_artist, :id => 1) #again an Array... but Song.find(:list_by_artist, :id => 1) gives me :

ArgumentError: expected an attributes Hash, got         from /var/lib/gems/1.8/gems/activeresource-2.1.0/lib/ active_resource/base.rb:883:in `load'         from /var/lib/gems/1.8/gems/activeresource-2.1.0/lib/ active_resource/base.rb:639:in `initialize'         ...

Looks like Rails try to instanciate a record where it should instantiate a collection.

Is there any way to solve this ? Is my method buggy, or is it Rails ?

if you want to get the songs from a artist you can do like i said before or:

@songs = Song.find_by_artist_id(1) # guess you have a artist_id on songs

if I'm not mistaken this is the right way...

Sorry, to retrieve all the songs from an artist you call

@songs = Song.find_all_by_artist_id(1) # guess you have a artist_id on songs

if you use the find_by_artist_id, you would get just one song instead of all of them

Will this work even though the two models are ActiveResource based? I
didn't think it provided you with the finder methods on ActiveResource
models.

Yes all this find_by_*** stuff and even @artist = Artist.find(1) @songs = @artist.songs doesn't work just cause it should not wok, I don't want to be able to do anything on my "server" models, just the stuff that the RESTFUL webservice "describe" (that means that I have to call URL, not server models methods).

The right way to do this is the

Artist.find(1).get(:songs) or Song.get(:list_by_artist, :id => 1)

but as I say previously, this return an Array.

I'm not sure that Artist.find(1).find(:songs) should work (find is not defined for an ActiveResource object) but Song.find(:list_by_artist, :id => 1) should work according to the doc, but it just doesn't work according to my test :slight_smile:

Any other idea ?

Ryan Bigg wrote:

Will this work even though the two models are ActiveResource based? I didn't think it provided you with the finder methods on ActiveResource models.

Ops.. that's right it won't work... my mistake...

I'm a bit confused. Why not just say:

artist.songs (that'll return all the songs for a given artist object) or Song.find_by_artist_id(1) which will return all the songs where artist ID is one

If you're not able to do that in script/console then your models are not defined correctly.

Artist < ActiveRecord::Base should have "has_many :songs" and Song < ActiveRecord::Base should have "belongs_to :artist"

I think ActiveRecord is pretty tight - I haven't experienced any bugs (well just one but it was some really far out funky thing). The stuff you are doing is run-of-the-mill every day AcitveRecord.

If you're wanting to do it REST style then you need to define some nested routes. That'll give you something like /artists/1/songs/4 for song with ID of 4, which belongs to artist 1. That has more to do with ActiveResource than ActiveRecord.

Nicholas

You obviously didn't quite read the first email, or the title of this
thread.

He's using Active*Resource* models, not ActiveRecord. The dynamic
finders you so trumpet are not available to him!

Please read thoroughly next time!

So nobody has any idea ?

Should I submit a bug in Lighthouse ?

Ok so I'll answer my own question :slight_smile:

In fact, the Person.find(:managers) example written by Ryan daigle and DHH doen't work (anymore?) http://ryandaigle.com/articles/2007/4/26/what-s-new-in-edge-rails-activeresource-gets-custom-methods

You have to write Person.find(:all, :from => :managers) and if you wants some params : Person.find(:all, :from => :managers, :params => {:office => "Chicago"}) this will make a call to http://webservice_site/persons/managers.xml?office=Chicago and returns the result as real ActiveResource objects !

Hope that can help anyone :slight_smile:

This is very helpful, I was getting the same error about a month ago
and just gave up. Thanks for giving me a renewed interest and idea to
tackle the problem :slight_smile: