Rails 3: What happens after a form button is pressed? - ruby-on-rails

When I press the form button in edit.html.erb view, Rails goes to the "update" action.
Is this a convention ?
How can I control the target action when the form is submitted ?

Yes, the convention is for the update action to handle updating an object, hence its name. The conventions are that way for a reason: they're the best way of doing it, and shouldn't be changed unless you have a good reason.
I highly recommend you take a look at the Rails Forms Guide and possibly the API documentation for form_for and form_tag.

You can specify a url for the form. See here http://api.rubyonrails.org/classes/ActionView/Helpers/FormHelper.html#method-i-form_for
form_for :post, :url => { :action => "custom_action" } do |f|

Related

Rails Forms for custom actions

I'm trying to link the input of a form to a specific action in my rails app.
Currently if I go to www.myapp.com/check/:idNumber, I'll be able to trigger the action just fine (which means routes is setup properly?). This action is basically a function call to a ruby/rails script with the parameter "idNumber" being passed to it. If the function is successful, it would return a newly created "Person" object and nil otherwise. This is different than the standard new operation as it determines the the attributes based on some information that it obtained from a database somewhere else.
Rake routes does give me the following:
check /check/:idNumber(.:format) person#check {:id=>/\d+/}
What I'm having trouble implementing is the form itself.
<%= form_tag("/check", :method => "get") do %>
<%= text_field_tag(:idNumber) %>
<% end %>
Controller action:
def check
regCheck = RegCheck.new
#person = regCheck.check_id(params[:idNumber])
if #person.name == nil
redirect_to root_path
end
end
submitting the form above would bring me to myapp.com/check?utf8=✓&idNumber=1234 instead. Can someone tell me what am I doing wrong?
I believe that using the check_path helper that is generated from the routes file is your best bet.
The form should look like this then.
<%= form_tag(check_path) do %>
<%= text_field_tag(:idNumber) %>
<% end %>
Rails forms can be finicky, especially when trying to build really customized forms.
This line
= form_for [#object]
Determines where the form goes, as well as the object that is being implemented. If you want to route the form to a different place, you can user the :url option. This options determines the path of the form, however you must keep in mind that the method is determined by the #object. If it is a new object, the method will be POST, an existing object will use a PUT method.
Let's suppose you want to update an existing object, but you want to send in data for a new object belonging to the existing object. That would look like
= form_for [#object], :as => #child_object, :url => my_optional_custom_path do |f|
# etc...
This generates a form sending a PUT request to the custom url (or the update path for #object if no custom url is supplied. The PUT request is sent with the parameter params[:child_object].
Hopefully this helps!
Best,
-Brian
I don't think it's possible the way you're trying.. The URL for the form is created before the user inputs any data.. So you need to remove the :idNumber from your routing..
If you do you get the following route:
check /check(.:format) person#check
Because the regex is removed now, you need to do this in you're controller:
def check
# Make sure ID is digits only
idNumber = params[:idNumber].gsub(/[^\d]/, '')
regCheck = RegCheck.new
#person = regCheck.check_id(idNumber)
if #person.name == nil
redirect_to root_path
end
end
You're form is allright, but you may want to use check_path like TheBinaryhood suggests..
If you really want it to be check/:idNumber you may also be able to submit the form to another action and redirect it to the right path from there..

Passing id in form_for action

I have a form to update an attribute of a model - I don't want it to go to the standard update action I want it to go to a different action.
<% for car in #cars %>
<%= form_for car, :url => { :action => "custom_action/#{car.id}" } do |f| -%>
This is giving the following error -
No route matches {:action=>"custom_action/1", :controller=>"cars"}
However if I visit the url - custom_action/1 - I don't get the routing error.
Any idea why I can't do this?
In addition to what Frederick Cheung said about GET vs POST vs PUT, I think your code might be wrong in general.
To do exactly what you want, try:
form_for car, :url => {:action => "custom_action", :id => car, :controller => "cars"} do |f|
I don't think this is a good idea, and will probably cause you pain. I suggest taking a look at the Ruby on Rails Routing Guide, to understand how to do this properly. (Routing is a topic where I always have to consult the manual.)
With correct routes your code should look something like this:
form_for car, custom_action_car_path(car) do |f|
Which will be easier to change in the future if/when you refactor your app.
If you go to the url by typing it into the url bar, you're making a GET request, whereas forms emit POST requests by default, and in this case would probably emit a PUT request (since you're acting on an existing record).
It sounds like your route is only routing GET requests. Given that you say your custom action does update the record, it sounds like you should update your routes to accept PUT requests instead.

How call the "create" action in rails

I'm working in a rails app (rails 2.3.8), and I created a resource called articles. I need a form who call the create action in that controller. I used a form_remote_tag, but I can't call correctly the "create" action, the app always call de "new" action.
I used several different combinations, the last one is this
<%=form_remote_tag :html => { :action => url_for (:action => :create)} %>
How a could do this?.
I can't use the for_remote_for or the form_for because that form will feed more tan one table in my database.
Thanks in advance
You are over complicating it:
<%= form_remote_tag :action => :create %>
Also, be sure that this is what you truly need. You say you want to create multiple objects in the form, which is why I think you may be after form_remote_for coupled with fields_for rather than form_remote_tag, but from your question I don't fully understand.

Rails : How to create more than one form with a submit button, doing different functionality?

I want to create more than one form with a submit button, with each submit button having a different action/functionalities to perform.
How to achieve this? For now all the submit buttons takes the create controller method as its action function. How to override this ?. Can I give name to each submit button and redirect each button's action to different method in its controller file?
How to do it ? I'm using rail 3.0.1.
If you're using the form_for helper method, I believe it uses the new_record? method on whatever object you're passing it to determine the proper action it should point to. For example:
<%= form_for #page do |f| %>
If #page.new_record? evaluates to true, the form will POST to the create method on the PagesController. However, if it evaluates to false, it will POST to the update method on the PagesController.
You can override the URL the form POSTs to by doing something like:
<%= form_for #page, :url => { :action => "my_action" } do |f| %>
That will allow you to send the form data to a custom action. You don't have to change anything related to the submit buttons.
Hope that helps!

Ruby on Rails: form and radio button question

I have a form around a list of items. I would like to check a radio button on the list and then, after clicking 'Submit', go to the 'Edit' page of the selected item.
The problem is that if I am writing something like
<%= form_tag edit_item_path %>
but Rails complains that I didn't provided a proper id, which in turn is being set on my radio buttons as the following:
<%= radio_button 'item', 'id', item.id %>
So - how would I send a form with a selected id to a given action?
Doing it the way you describe would not work, since edit_item_path by default RESTful path definitions is a GET request. You are trying to make it a POST request. If you would like to stick to the RESTful way of doing things I would recommend simply looping through your items and provide links to edit, since you are planning to edit them one at a time anyways. Otherwise, you would have to define a new route if you would prefer doing things within the form with radio buttons. If you are, than you would add something like this to your config/routes.rb: (assuming you are using rails 2.3.x)
map.resources :items, :member =>{:edit_radio_form => :post}
Than your form would look like this:
<%= form_tag edit_radio_form_item_path do |form| %>
And it should work, but it not the right way of doing things for several reasons, the most anoying one of which is that you won't get a full URL on your edit page because you got there with a POST request, so if you refresh the page, your item id param will be gone and will produce an error.

Resources