How to call a method and send new parameters in RoR?
Let's say I have methodA
def methodA
note = Note.find(params[:id])
note.link = params[:link]
note.linktype = params[:linktype]
note.save
redirect_to(notes_url)
end
When I call this method from a view like this, it works fine
<%= link_to image_tag(w.link, :border =>0), methodA_path(:linktype => w.linktype, :link => w.link, :id => @note.id) %>
But, if I call the method from another method in the same controller 开发者_开发百科like this:
def methodB
...
methodA(:id => params[:id], :link => link, :linktype => "image")
end
I get this error:
wrong number of arguments (1 for 0)
The parameters that methodA is getting are still the same parameters that methodB got, not the ones that I'm sending from methodB. How do I get around this problem? Thank for reading.
Several things:
- The Ruby, and therefore Ruby on Rails, naming convention is to use underscore notation rather than camelcase. So it should be
method_a
rather thanmethodA
. - It looks like
methodA
is a controller action. If you look at your method signature, you're not actually defining any method parameters. That's a good thing: actions don't take any. - The
params
call in themethodA
action is not accessing method parameters, but is access the Rails requestparams
hash. - In your view, you're not actually calling the method. Rather, you're linking to the action, which, when clicked, initiate a request that is routed to that action. The actual method you're calling is
methodA_path
, which is generating the URL. This is a shortcut tourl_for
that automatically fills in some parameters for you (the other ones are in the hash you're passing). This method was automatically generated for you from your routes. Do arake routes
from the root of your app for a little more information. - If you wanted to call the action method from
methodB
, which is probably unwise, you don't need to pass it the parameters. SincemethodB
is also an action being called in its own request cycle, theparams
hash is still available tomethodA
, and it will find all of those things just fine. I'd suggest, however, extracting any common functionality into a third helper method and calling that from each action; calling actions from other actions feels like a code smell to me.
A bit of a summary: methodA
and methodA_path
are different methods. The former takes no parameters but accesses the Rails request parameters hash, while the latter takes parameters to pass to url_for
.
This is all pretty basic, so I strongly suggest you read Agile Web Development with Rails (3rd edition for Rails 2, 4th for Rails 3).
A call to method_a_path
and method_a
are not the same.
The
method_a
does not take parameters. It accesses the parameters from theparams
hash set to the controller instance during action invocation.The
method_a_path
does not invokemethod_a
, it just generates the URL for invoking the method. Actual invocation happens when the user clicks on the link and the rails server processes the request.
If you want to reuse the method in a diffrent context extract the code of the action to a new method as shown below:
class PostsController < ApplicationController
def add_media
add_media_with_para(params)
end
def action2
add_media_with_para(:id => params[:id], :link => link, :linktype => "image")
end
private
def add_media_with_para p = {}
note = Note.find(p[:id])
note.link = p[:link]
note.linktype = p[:linktype]
note.save
redirect_to(notes_url)
end
end
Now in your view you can obtain the path to add_media action as follows:
posts_add_media_path(:linktype => w.linktype, :link => w.link, :id => @note.id)
I assume by addMedia you mean methodA
Note, method methodA_path
is not the same as methodA
. First one is automatically generated because you have a route named methodA
and returns url necessary to access that route. Thus, it returns string. While methodA
usually renders html template.
If you want to delegate rendering to another action, you can do something like this: redirect_to :action => :methodA, :id => 1, :otherParam => 2
精彩评论