Link_to parameters ignored

Hi,

I've faced a couple of times the next problem.

I have a link to like:

<%= link_to 'Add comment', :action => 'add_comment', :program_id => program.program_name, :user => @username %>

I have function in the right controller:

def add_comment   @program_id = params[:program_id]   @user = User.find(session[:uid]) end

And that fails with: Couldn't find Program with ID=add_comment

When I check the request sent to the server:

Processing ProgramsController#show (for 127.0.0.1 at 2008-02-27 13:37:19) [GET]   Session ID: BAh7.....   Parameters: {"user"=>"user1",                "program_id"=>"The program",                "action"=>"show",                "id"=>"add_comment",                "controller"=>"programs"}

←[4;36;1mProgram Columns (0.010000)←[0m ←[0;1mSHOW FIELDS FROM `programs`←[0m ←[4;35;1mProgram Load (0.010000)←[0m ←[0mSELECT * FROM `programs` WHERE (`programs`.`id` = 0) ←[0m

i guess you have added a RESTful route for this?

map.resource :programs

your link generates: /programs/add_comment?program_id=.... (and it's a GET request as with ever normal link)

and the RESTful url for the show action of this controller is: /programs/:id when it's a GET request, this routes to the show action. So the resource sees "add_comment" as :id

In a RESTful design, adding comments should be handled in the CommentsController, not the ProgramsController anyways.

Thorsten wrote:

i guess you have added a RESTful route for this?

map.resource :programs

Well no I haven't done anything like that. It is a basic rails app generated with scaffold. Should I post here some configuration file to help clarifying the issue?

To the main scaffold I have added a new add_comment.html.erb I try to open that one from the index.html.erb

This is my controller. I have some basic authentication also in place but that should be ok and is working.

class ProgramsController < ApplicationController

before_filter :check_auth, :except => :index

  def add_comment()     @program_id = params[:program_id]     @user = User.find(session[:uid])   end

def secret     puts session[:uid]     @user = User.find(session[:uid])     puts @user.username     redirect_to :action => 'list'   end

  def log_out     session[:uid] = nil     redirect_to :controller => 'main'   end

  # GET /programs   # GET /programs.xml   def index     @isLogged = false     if session[:uid]       @user = User.find(session[:uid])       @isLogged = true       @username = @user.username     end

    @programs = Program.find(:all)     @multiplier = -25

    respond_to do |format|       format.html # index.html.erb       format.xml { render :xml => @programs }     end   end

  # GET /programs/1   # GET /programs/1.xml   def show     @program = Program.find(params[:id])

    respond_to do |format|       format.html # show.html.erb       format.xml { render :xml => @program }     end   end

  # GET /programs/new   # GET /programs/new.xml   def new     @program = Program.new

    respond_to do |format|       format.html # new.html.erb       format.xml { render :xml => @program }     end   end

  # GET /programs/1/edit   def edit     @program = Program.find(params[:id])   end

  # POST /programs   # POST /programs.xml   def create     @program = Program.new(params[:program])

    respond_to do |format|       if @program.save         flash[:notice] = 'Program was successfully created.'         format.html { redirect_to(@program) }         format.xml { render :xml => @program, :status => :created, :location => @program }       else         format.html { render :action => "new" }         format.xml { render :xml => @program.errors, :status => :unprocessable_entity }       end     end   end

  # PUT /programs/1   # PUT /programs/1.xml   def update     @program = Program.find(params[:id])

    respond_to do |format|       if @program.update_attributes(params[:program])         flash[:notice] = 'Program was successfully updated.'         format.html { redirect_to(@program) }         format.xml { head :ok }       else         format.html { render :action => "edit" }         format.xml { render :xml => @program.errors, :status => :unprocessable_entity }       end     end   end

  # DELETE /programs/1   # DELETE /programs/1.xml   def destroy     @program = Program.find(params[:id])     @program.destroy

    respond_to do |format|       format.html { redirect_to(programs_url) }       format.xml { head :ok }     end   end

  private   def check_auth     unless session[:uid]       flash[:error] = 'You need to be logged in to access this panel'       redirect_to :controller => 'main'       #redirect_to :action => 'list'     end   end

end

Thanks.

in Rails 2.0 scaffold generates a RESTful controller and also adds the RESTful route to the routes.rb Have a look at the routes file and you will see it.

You can see what i described in my above reply in your own controller code genrated bx the scaffold:

# GET /programs/1 # GET /programs/1.xml   def show

a link like /programs/1 is routed to the show action. same for /programs/add_comments, as Rails doesn't restrict URLs to integer id values (we all love permalinks don't we?) thats why your error happens.

While I believe Thorsten is correct about the part that the scaffold is playing in the error, you'll need a couple more pieces to pull this together.

First, the RESTful ProgramsController is going to assume that you're dealing with the Program model, so it expects :id rather than :program_id. That will help with creating the correct route.

Second, to support 'add_comment' as a non-standard (ie., not a default Rails RESTful route) path you'll have to modify your /config/ routes.rb The scaffold should have added a line like the one Thorsten mentioned. You'll want to change it to something like this:

map.resources :programs, :member=>{:add_comment=>:post}

That tells the routing system that you want to find one member in the collection of Program routes (so expect an :id entry in the params hash), that the action/method handling it will be called add_comment, and it should only respond when accessed via http POST.

HTH, AndyV

comopasta Gr wrote:

Hi,

I've faced a couple of times the next problem.

I have a link to like:

<%= link_to 'Add comment', :action => 'add_comment', :program_id => program.program_name, :user => @username %>

Processing ProgramsController#show (for 127.0.0.1 at 2008-02-27 13:37:19) [GET]   Session ID: BAh7.....   Parameters: {"user"=>"user1",                "program_id"=>"The program",                "action"=>"show",                "id"=>"add_comment",                "controller"=>"programs"}

Plus the action received at the server is now "show". When I have specified "add_comment".

What is going on, any hints?

Thanks.

You might try adding the '{' and '}' around the action. Looking on the documentation all the examples have those braces. I have had link_to and link_to_remote do strange things when I leave those off. Good luck,

-Shandy

Hi again!

Thanks all for your great comments. I actually tried to play intially with the {...} and so but didn't help.

REST was one of my pending (one of many) areas and it looks like time has come. I just went through a perfect set of articles about the REST for me. I think I might have a basic knowledge of the main concepts.

Here's a link to the set of articles, started with Rails 1.2 and updated to 2.0: http://www.softiesonrails.com/search?q=rest+101

Best to modify the CommentsController.