开发者

How to add additional params to a button_to form?

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜