Hi all. A simple app. Albums have songs. Songs have artists. Models look like: class Album < ActiveRecord::Base has_many :albumappearances has_many :songs, :through => :albumappearances validates_length_of :description, :minimum => 4 end class Albumappearance < ActiveRecord::Base belongs_to :album belongs_to :song end class Song < ActiveRecord::Base has_many :albumappearances has_many :albums, :through => :albumappearances belongs_to :artist validates_length_of :name, :minimum => 4 end class Artist < ActiveRecord::Base has_many :songs validates_length_of :name, :minimum => 6 end # -------------- At album create or update, a user can enter a totally new artist/song combination. If the artist or song don't exist, they need to get created. So, for example, in my controller, i know I can have something like: def update # figure out which album we're talking about. @album = Album.find(params[:id]) # set the album description the user entered @album.description = params[:album][:description] # we'll need an artist.id later to associate with the song. # so start with artist. @artist = Artist.find(params[:artist][:name]) rescue nil # if no artist was found, we need to create one. if @artist == nil @artist = Artist.new(:name => params[:artist][:name]) # try to save the artist. errors will be captured. @artist.save end @song = Song.find(params[:song][:name]) rescue nil # if we couldn't find a song, we need to create one. if @song == nil @song = Song.new(:name => params[:song][:name]) # see if there are any validation errors with the song @song.valid? # if there isn't an artist and there are errors associated with the artist... if @artist.errors && @artist.id = nil # don't try to save the song since it won't have an ID to use for artist # but do try to validate the song so we can tell the user about the problem @song.valid? else # try to save the song @artist.songs << @song end end # now, work on the album. if @song.errors || @artist.errors # if there were errorsdon't try to save the album, but validate to show the user errors @album.valid? render :action => 'edit' # exit else # otherwise save the album. if @album.save flash[:notice] = 'album was successfully updated.' redirect_to :action => 'show', :id => @album else render :action => 'edit' end end end # ----------------- Now, this seems to work, but it seems awfully verbose and un rails- like. Should some of this get moved to the models? Am I missing something obvious?
on 2007-06-20 00:13