Handling a select_tag nil value

A relationship exists between “artist” and “album”.

Artist.rb
    has_many :albums

Album.rb
    belongs_to :artist

The edit form for “album” creates/updates this relationship in a
database using the “select_tag”.

<%= select_tag('artist_id',
    options_for_select([['choose one', '']] +
    @artists.collect {|art| [art.name, art.id]},
    @album.artist_id)) -%>

resulting in this HTML

<select id="design_id" name="design_id">
    <option value="">choose one</option>
    <option value="1">Artist #1</option>
    <option value="2">Artist #2</option>
    <option value="3">Artist #3</option>

The “album” controller is successfully creating/updating the database
as long as an option other than “choose one” is selected.

If “choose one” is selected when submitting the form this error is
generated:

ActiveRecord::RecordNotFound in AlbumsController#update
    Couldn't find Artist with ID=

Parameters: {"commit"=>"Edit", "id"=>"1",
    "album"=>{"title"=>"Rock", "Rating"=>"1"},
    "artist_id"=>""}

Question: How can my controller receive the nil value for “choose one”
and successfully process the form?

I think I need a logic statement in my controller, but I am not sure
how to acquire and handle the nil value.

AlbumsController currently reads as follows:

def create
@album = Album.find(params[:id])

artist = Artist.find(params[:artist_id])
@album.artist = artist

if @album.update_attributes(params[:album])
  flash[:notice] = 'Album was successfully updated.'
  redirect_to(:action => 'show', :id => @album)
else
  @artists = Artist.find(:all)
  render(:action => 'edit')
end

end

Thanks for read this far, I know that is probably too much detail.
Your advice is appreciated.

Success!

Thank you George.

On 2/10/07, SelectNothing [email protected] wrote:

database using the “select_tag”.

<%= select_tag('artist_id',
    options_for_select([['choose one', '']] +
    @artists.collect {|art| [art.name, art.id]},
    @album.artist_id)) -%>

Try this instead:

select ‘album’, ‘artist_id’, @artists.map{|a| [a.name, a.id]},
:prompt => ‘Choose one…’

This will pass the artist id (possibly “”) as the value of the
album[artist_id] parameter, which lets you update it with the call to
Album.create or Album update in your controller. That is, there’s no
need to update this field separately.

AlbumsController currently reads as follows:

def create
@album = Album.find(params[:id])

artist = Artist.find(params[:artist_id])
@album.artist = artist

if @album.update_attributes(params[:album])

So the above 4 lines become something like:

@album = Album.new(params[:album])  # sets album_id too now
if @album.save
  flash[:notice] = 'Album was successfully updated.'
  redirect_to(:action => 'show', :id => @album)
else
  @artists = Artist.find(:all)
  render(:action => 'edit')
end

end

Thanks for read this far, I know that is probably too much detail.

Not at all; I found your question/problem very clear and easy to follow.

Your advice is appreciated.

You’re welcome!
George.