I have a situation where I have three models, Album, Artists and
Songs:
class Album < ActiveRecord::Base
belongs_to :song
end
class Artist < ActiveRecord::Base
belongs_to :song
end
class Song < ActiveRecord::Base
belongs_to :artist
end
So, an album can have songs that have artists.
The problem is that on the Album create form, the user is allowed to
enter all three values. So, the user may enter an existing album that
has a new song by a new artist. Or they have enter a new album that
has an existing song by an existing artist.
I can't figure out how to manage this create in the controller. So,
far I have:
def create
@artist = Artist.find_or_create_by_name(params[:artists][:name])
@song = Song.find_by_name(params[:songs][:name])
if @song.nil?
@song = Song.new(:name => params[:songs][:name], :artist_id
=> @artist.id)
if !@song.save
flash[:error] = "Couldn't create song"
redirect_to :action => 'new'
end
end
@album = Album.new()
@album.item_id = @item.id@album.song_id = @song.id
if @album.save
flash[:notice] = 'Album was successfully created.'
redirect_to :action => 'show', :id => @album.id
else
render :action => 'new'
end
end
This seems to work, but it feels kludgy and I'm not sure if there is
another, more Rails appropriate way to do it. Any suggestions?
1) where does @item come from? it's not created in the "create"
action... some before filter? what is it?
2) you say users can enter an existing album, but you always create a
new one ? and doesn't it get a name or something?
3) how are your associations set up?
while because of the above, i'm not sure what you exactly want or
need, i was in the mood to type some stuff out as i like associations
problems. If it doesn't suit your needs exactly maybe you can get some
hints out of it:
First the associations, i guess how you have (or should have) set them
up, due to above unclarities:
lass Artist < ActiveRecord::Base
has_many :songs
has_many :albums, :through => :songs
end
class Song < ActiveRecord::Base
belongs_to :artist
has_many :album_appearances
has_many :albums, :through => :album_appearances
end
class AlbumAppearances < ActiveRecord::Base
belongs_to :album
belongs_to :song
end
class Album < ActiveRecord::Base
has_many :songs
has_many :artists, :through => :songs
end
so the association works like this