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? --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
uhm your code is a bit confusing ... 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 Artist<->song<->song_appearance<->album ********************* Now, the controller. I shortened the code for better readability, you might add an error check here and there: def create #find or create the Artist: @artist = Artist.find_or_create_by_name(params[:artist][:name]) #we have the artist, now find the song by this artist if it exists, if not, create a new one, associated to the artist: song = @artist.songs.find_by_name(params[:songs][:name]) if @song = nil @song = @artist.songs.create(params[:song]) end #Now we got the song, associated to the artist. #So we find or create the Album, and add the song to the has_many :through relationship @album = Album.find_or_create_by_name(params[:albums][:name]) @album.songs << @song #creates an association in the join table "song_appearances" #Redirect to the Show page for the album: redirect_to action => ''show'', :id => @album.id end Hope that helps --~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
That does help. I didn''t know about the :through and I didn''t think to use an association table. Thanks for the help. On Jun 14, 4:38 pm, Thorsten <duple...-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote:> 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 > > Artist<->song<->song_appearance<->album > > ********************* > Now, the controller. I shortened the code for better readability, you > might add an error check here and there: > > def create > #find or create the Artist: > @artist = Artist.find_or_create_by_name(params[:artist][:name]) > > #we have the artist, now find the song by this artist if it exists, > if not, create a new one, associated to the artist: > song = @artist.songs.find_by_name(params[:songs][:name]) > if @song = nil > @song = @artist.songs.create(params[:song]) > end > > #Now we got the song, associated to the artist. > #So we find or create the Album, and add the song to the > has_many :through relationship > @album = Album.find_or_create_by_name(params[:albums][:name]) > @album.songs << @song #creates an association in the join table > "song_appearances" > > #Redirect to the Show page for the album: > redirect_to action => ''show'', :id => @album.id > end > > Hope that helps--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---
Glad i could help. One more thing: the "has many :albums" in the Artist class won''t work i guess, it slipped in there accidentally. ;) The rest should be fine though. On 15 Jun., 00:13, tayknight <taykni...-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org> wrote:> That does help. I didn''t know about the :through and I didn''t think to > use an association table. Thanks for the help. > > On Jun 14, 4:38 pm, Thorsten <duple...-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> wrote: > > > 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 > > > Artist<->song<->song_appearance<->album > > > ********************* > > Now, the controller. I shortened the code for better readability, you > > might add an error check here and there: > > > def create > > #find or create the Artist: > > @artist = Artist.find_or_create_by_name(params[:artist][:name]) > > > #we have the artist, now find the song by this artist if it exists, > > if not, create a new one, associated to the artist: > > song = @artist.songs.find_by_name(params[:songs][:name]) > > if @song = nil > > @song = @artist.songs.create(params[:song]) > > end > > > #Now we got the song, associated to the artist. > > #So we find or create the Album, and add the song to the > > has_many :through relationship > > @album = Album.find_or_create_by_name(params[:albums][:name]) > > @album.songs << @song #creates an association in the join table > > "song_appearances" > > > #Redirect to the Show page for the album: > > redirect_to action => ''show'', :id => @album.id > > end > > > Hope that helps--~--~---------~--~----~------------~-------~--~----~ You received this message because you are subscribed to the Google Groups "Ruby on Rails: Talk" group. To post to this group, send email to rubyonrails-talk-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org To unsubscribe from this group, send email to rubyonrails-talk-unsubscribe-/JYPxA39Uh5TLH3MbocFFw@public.gmane.org For more options, visit this group at http://groups.google.com/group/rubyonrails-talk?hl=en -~----------~----~----~----~------~----~------~--~---