【问题标题】:How to add additional params to a button_to form?如何向 button_to 表单添加额外的参数?
【发布时间】:2011-02-03 13:54:05
【问题描述】:

我想要一个Submit 按钮。它更新提交的一个字段; submission.state = :submitted

现在,我可以创建一个自定义路由和一个自定义操作,然后发布到其中。但这似乎真的很严厉。特别是因为我还会有一个reject 按钮,可能还有更多。需要为每一个自定义路线和操作对我来说似乎非常愚蠢。

如果我能做类似的事情会更好

button_to "Submit", submission_url(submission), :method => :put, :submission => { :state => :submitted }

这将发布到提交的update 方法并仅更新所需的字段。

但这不起作用。我怎样才能让它工作?或者您对如何执行此操作有更好的想法?

【问题讨论】:

    标签: ruby-on-rails forms


    【解决方案1】:

    @AugustinRiedinger 提到的 pull request 已被合并,现在可从 Rails 4.1.0 开始使用。现在只需添加params 选项:

    params: { state: :submitted }
    

    【讨论】:

    • 请注意,params 选项目前不允许嵌套哈希。示例:params: {user: {active: false}} 不允许。您可以使用丑陋的params: {:"user[active]" => true} 绕过它
    • 我在 Rails 5.2.1 上,现在支持嵌套哈希。
    【解决方案2】:

    它不是那么简洁,但是如果不扩展 Rails,这会让我明白:

    = form_for submission, :html => { :class => "button_to" } do |f|
        = f.hidden_field :state, :value => :submitted
        = f.submit "Submit", :class => "link"
    

    【讨论】:

    • 那么没有别的解决办法了吗?喜欢button_to "Submit", submission_url(submission), :method => :put, :params => {:submission => { :state => :submitted }}
    • 显然这种演变已经发展,但仍需要整合:github.com/rails/rails/pull/10471
    【解决方案3】:

    最后加上params:{},会生成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" } %>
    

    【讨论】:

      【解决方案4】:

      我有类似的方法:

      button_to "Submit", submission_url(submission, :submission =&gt; { :state =&gt; :submitted }), :method =&gt; :put

      【讨论】:

      • 这可行,但是它将参数附加到查询字符串中,这看起来有点难看。
      【解决方案5】:

      所以,从这个 rails pull request 开始:https://github.com/rails/rails/pull/10471

      您可以执行以下操作来自定义 button_to。

      application_helper.rb 中,添加以下行:

      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
      

      并使用它:

      = button_to_with_params 'Awesome button', awesome_action_path, method: :put, :params => {:my_param => 'my_value'}
      

      享受吧!玩得开心!

      【讨论】:

      • 我是那个 PR 的作者。它已被 Rails 接受,因此自 Rails 4.1 起,params 选项现在可用。
      【解决方案6】:

      如果我没看错,当以标准方式提交标准 Rails 表单时,您实际上想要做的具体事情是什么。

      请注意,当使用例如提交表单时

      f.submit "Save Changes"

      然后

      params[:commit] = "Save Changes"

      这样做的好处是它可以让您在控制器更新操作中进行一些适当的分支。

      不好的是它很脆。如果有一天您或其他人决定更改按钮文本,事情就会中断......这很糟糕。

      K

      【讨论】:

        【解决方案7】:

        从 Rails 3.2.1 开始,您可以使用 :form 键向 :html_options 哈希添加额外的参数。

        http://apidock.com/rails/v3.2.1/ActionView/Helpers/UrlHelper/button_to

        这在 3.2.1 之前不存在,因此需要更详细的解决方案,即声明具有隐藏属性的表单。

        【讨论】:

        • :html_options 不允许您将隐藏的输入元素添加到 button_to 创建的表单中。它将向输入标签的 html 添加选项。但是,您可以将一个选项传递给 html_options,它将在表单中生成一个隐藏字段,这就是方法选项。有关示例,请参阅文档:api.rubyonrails.org/classes/ActionView/Helpers/…
        猜你喜欢
        • 1970-01-01
        • 2013-07-20
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2015-08-27
        相关资源
        最近更新 更多