I want to have a Submit
button. It updates one field on the submission; submission.state = :submitted
Now, I could make 开发者_如何转开发a custom route and a custom action and just post to that. But that seems really heavy-handed. Especially since I'll also have a reject
button and possibly more. Needing a custom route & action for each of those seems downright silly to me.
It would be much nicer if I could do something like
button_to "Submit", submission_url(submission), :method => :put, :submission => { :state => :submitted }
Which would post to the submission's update
method and update only the desired field.
But that doesn't work. How can I make it work? Or do you have a better idea of how to do this?
The pull request mentioned by @AugustinRiedinger has been merged and is now available as of Rails 4.1.0. Now just add the params
option:
params: { state: :submitted }
It's not as concise, but without extending Rails, this will get me by:
= form_for submission, :html => { :class => "button_to" } do |f|
= f.hidden_field :state, :value => :submitted
= f.submit "Submit", :class => "link"
Add params:{} at the end, it will generate hidden_field
<%= button_to user.name, user, class:"btn btn-default", style:"", method: :patch, remote: true, params: { a_field: false, an_other_field:"a new value" } %>
I have something similar that works:
button_to "Submit", submission_url(submission, :submission => { :state => :submitted }), :method => :put
So, as from this rails pull request : https://github.com/rails/rails/pull/10471
Here is what you can do to have your custom button_to.
In application_helper.rb
, add these lines:
module ApplicationHelper
// Unfortunately these 2 methods need to be redefined. I don't know how I could access the original ones.
def token_tag(token=nil)
if token != false && protect_against_forgery?
token ||= form_authenticity_token
tag(:input, type: "hidden", name: request_forgery_protection_token.to_s, value: token)
else
''
end
end
def method_tag(method)
tag('input', type: 'hidden', name: '_method', value: method.to_s)
end
def button_to_with_params(name = nil, options = nil, html_options = nil, &block)
html_options, options = options, name if block_given?
options ||= {}
html_options ||= {}
html_options = html_options.stringify_keys
convert_boolean_attributes!(html_options, %w(disabled))
url = options.is_a?(String) ? options : url_for(options)
remote = html_options.delete('remote')
params = html_options.delete('params') { Hash.new }
method = html_options.delete('method').to_s
method_tag = %w{patch put delete}.include?(method) ? method_tag(method) : ''.html_safe
form_method = method == 'get' ? 'get' : 'post'
form_options = html_options.delete('form') || {}
form_options[:class] ||= html_options.delete('form_class') || 'button_to'
form_options.merge!(method: form_method, action: url)
form_options.merge!("data-remote" => "true") if remote
request_token_tag = form_method == 'post' ? token_tag : ''
html_options = convert_options_to_data_attributes(options, html_options)
html_options['type'] = 'submit'
button = if block_given?
content_tag('button', html_options, &block)
else
html_options['value'] = name || url
tag('input', html_options)
end
inner_tags = method_tag.safe_concat(button).safe_concat(request_token_tag)
params.each do |name, value|
inner_tags.safe_concat tag(:input, type: "hidden", name: name, value: value.to_param)
end
content_tag('form', content_tag('div', inner_tags), form_options)
end
end
And to use it:
= button_to_with_params 'Awesome button', awesome_action_path, method: :put, :params => {:my_param => 'my_value'}
Enjoy! Have fun Railing!
If I read things correctly what you are effectively wanting to do something specific when a standard rails form is submitted in the standard way.
Notice that when a form is submitted using e.g.
f.submit "Save Changes"
then
params[:commit] = "Save Changes"
The GOOD thing about this is that it can allow you to do some appropriate branching in the controllers update action.
The BAD thing is that it's brittle. If one day you or someone else decides to change the button text, things break.. which is bad.
K
As of Rails 3.2.1 you can add additional params to the :html_options hash using the :form key.
http://apidock.com/rails/v3.2.1/ActionView/Helpers/UrlHelper/button_to
This did not exist prior to 3.2.1 so the more verbose solution of declaring a form with hidden attributes was required.
精彩评论