Forum: Ruby on Rails form post not working

Announcement (2017-05-07): www.ruby-forum.com is now read-only since I unfortunately do not have the time to support and maintain the forum any more. Please see rubyonrails.org/community and ruby-lang.org/en/community for other Rails- und Ruby-related community platforms.
Abhinav (Guest)
on 2006-05-04 13:24
Hi there,

I have this form code in a view:

<%= start_form_tag :action => "listByArtist", :id => artist.id %>
  <p><b>List by Artist:</b>
  <select id="artist_id" name="artists[id]">
    <%= options_from_collection_for_select(@artists, "id", "name") %>
  </select>
<%= submit_tag "List" %>
<%= end_form_tag %>

When I hard code the ":id" in line 1 everything works fine - in that the
listByArtist controller and view render exactly what I want.

When I use the above code with ":id => artist.id" I get this error:

undefined local variable or method `artist'

This is really frustrating, I am simply trying to pass the id of an
artist which is selected by the user, such as to list all songs by this
artist.

How can I successfully pass this artist.id?

Thanks,
A
Alex Y. (Guest)
on 2006-05-04 13:32
(Received via mailing list)
Abhinav wrote:
> <%= end_form_tag %>
> artist.
>
> How can I successfully pass this artist.id?
It needs to be passed from the controller as an instance variable.  Your
controller code should look something like this:

def lookup
   @artist = Artist.find(params[:id])
   @artists = Artist.find(:all)
end

and then you can use

<%= start_form_tag :action => "listByArtist", :id => @artist.id %>

in your view.
Abhinav (Guest)
on 2006-05-04 16:20
Alex Y. wrote:
> It needs to be passed from the controller as an instance variable.  Your
> controller code should look something like this:
>
> def lookup
>    @artist = Artist.find(params[:id])
>    @artists = Artist.find(:all)
> end
>
> and then you can use
>
> <%= start_form_tag :action => "listByArtist", :id => @artist.id %>
>
> in your view.

Thanks Alex - I believe I am doing this already...so I guess I should
run through exactly what I have set up so far.

I have the following setup.  Essentially from "list" I can call
"listByArtist" to show songs grouped by the artist selected.

What I am trying to do is pass the artist.id from the list view to the
listByArtist controller, which in turn builds an array of songs that
have the artist.id associated to them (marked below with >>>).

I placed your suggested code into the listByArtist controller, but
really all I am passing to the controller is an integer that represents
an artist...the code below works fine for the listByArtist controller
and view.

I just cant seem to pass the artist.id from the list view as I keep
getting the aforementioned error.

-- Controller code --

def list
 @songs = Song.find(:all, :order => "(select name from artists where
artists.id = songs.artist_id)")
 @artists = Artist.find_all
end

def listByArtist
>>> @song = Song.find(:all, :conditions => [ "artist_id = ?", @params["id"] ])
 @artist = Artist.find(params[:id])
end

-- End Controller code --

-- List View Code --

<h1>All Songs</h1>
<center>
<table border="0">
 <tr>
  <td width="50%"><p align="center"><i><b>Song</b></i></td>
  <td width="50%"><p align="center"><i><b>Artist</b></i></td>
 </tr>
 <% @songs.each do |song| %>
  <tr>
   <td><p align="center"><%= link_to song.name, :action => "show", :id
=> song.id %></td>
   <td><p align="center"><%= song.artist.name %></td>
  </tr>
 <% end %>
</table>

<%= start_form_tag :action => "listByArtist", :id => @artist.id %>
  <p><b>List by Artist:</b>
  <select id="artist_id" name="artists[id]">
    <%= options_from_collection_for_select(@artists, "id", "name") %>
  </select>
<%= submit_tag "List" %>
<%= end_form_tag %>
</center>

-- End List View Code --

-- ListByArtist View Code --

<h1>Songs by Artist</h1>
<center>
<table border="0">
 <tr>
  <td width="50%"><p align="center"><i><b>Song</b></i></td>
 </tr>
 <% @song.each do |song| %>
  <tr>
   <td><p align="center"><%= link_to song.name, :action => "show", :id
=> song.id %></td>
  </tr>
 <% end %>
</table>
</center>

-- End ListByArtist View Code --
Alex Y. (Guest)
on 2006-05-04 16:41
(Received via mailing list)
Abhinav wrote:
>>and then you can use
> "listByArtist" to show songs grouped by the artist selected.
>
> What I am trying to do is pass the artist.id from the list view to the
> listByArtist controller, which in turn builds an array of songs that
> have the artist.id associated to them (marked below with >>>).
First, some terminology, just so we're singing from the same hymn sheet.

list and listByArtist are actions, not controllers.  The controller is
the class that holds those actions.  At least, I assume that's how
you've set this up.  It would be the most sensible way, I think.

list's view only has access to those instance variables define in the
list action.  In your case, that is @songs and @artists.

>
> I placed your suggested code into the listByArtist controller,
It should go in the list action, so that the list view has access to
@artist.


<snip>
> <%= start_form_tag :action => "listByArtist", :id => @artist.id %>
>   <p><b>List by Artist:</b>
>   <select id="artist_id" name="artists[id]">
>     <%= options_from_collection_for_select(@artists, "id", "name") %>
>   </select>
> <%= submit_tag "List" %>
> <%= end_form_tag %>
> </center>
<snip>
I don't know if this is something you might be assuming, but defining
'listByArtist' as an action for the start_form_tag call doesn't call the
listByArtist action.  It sets it up to be called on form submission.
That's why the list action needs to define @artist for itself.

At least, that's what's wrong in theory.  Looking at it, I don't
actually see why you need :id => @artist.id in the start_form_tag call
at all...  the ID is going to be provided by the select box anyway.
You'll need to change the call in the listByArtist from params[:id] to
params[:artists][:id], but that's where the value should be coming
from...
Guest (Guest)
on 2006-05-05 04:54
Alex Y. wrote:
> list and listByArtist are actions, not controllers.  The controller is
> the class that holds those actions.  At least, I assume that's how
> you've set this up.  It would be the most sensible way, I think.

Yes that is how I have set it up...my terminology is not up to
scratch...if it isnt obvious I am very new to ruby/rails/html. :)

>> I placed your suggested code into the listByArtist controller,
> It should go in the list action, so that the list view has access to
> @artist.

Um...I actually got it to work without adding anything into the list
action.

> At least, that's what's wrong in theory.  Looking at it, I don't
> actually see why you need :id => @artist.id in the start_form_tag call
> at all...  the ID is going to be provided by the select box anyway.

Yes you are right here - I have not explicityly stated the :id in other
forms and they are working fine.  I was just trying to explicitly pass
this id as a brute force attempt to send the id to the listByArtist
action.

> You'll need to change the call in the listByArtist from params[:id] to
> params[:artists][:id], but that's where the value should be coming
> from...

So - I now understand where I was going wrong.  Thanks for your help
Alex - it has put me straight...

I removed the :id from the start_form_tag in the listByArtist view:

<%= start_form_tag :action => "listByArtist" %>

...and called the variable artist instead of artists (just cleaning up):

  <select id="artist_id" name="artist[id]">

...and I added this to the listByArtist action:

        def listByArtist

                @song = Song.find(:all, :conditions => [ "artist_id =
?", params[:artist][:id] ])
                @artist = Artist.find(params[:artist][:id])

        end

I did not change the list action as you have suggested.  This did not
seem necessary to me as the only two arrays of data being used by the
list action were song and artists.  So I left this alone.

I really need to learn about using a debugger to be able to quickly
establish what is going wrong.

Anyway - thank you for your help!
A
This topic is locked and can not be replied to.