【问题标题】:Submit multiple forms in rails在 Rails 中提交多个表单
【发布时间】:2016-07-12 06:49:58
【问题描述】:

目前我正在为我的应用程序添加一项新功能,该功能允许用户使用一个提交按钮提交同一对象的多个表单。

我刚刚添加了“add_inquery”按钮,当用户单击它时,将呈现一个新表单(在同一页面中)。我不限制用户想要提交的表单的数量。一般来说,他们可以根据需要提交 10 到 20 个表格。

我得到的错误是:

nil:NilClass 的未定义方法 `fields_for'

这是我所有的代码:

_form.html.haml

.col-md-3
  = link_to "Add Inquery", pricing_histories_add_inquery_path, remote: true, class: 'btn btn-default', data: {disable_with: "Please wait..."}

= form_tag pricing_histories_path , html: {class: 'form-horizontal'} do |f|
  %div.alert.alert-danger.display-hide
    %button.close{'data-close' => 'alert'}
    You have some form errors. Please check below.
  %div.alert.alert-success.display-hide
    %button.close{'data-close' => 'alert'}
    Your form validation is successful!
  %div.row
    %div.col-xs-12.form-body
      = f.fields_for '' do |fd|
        = render 'form_body', f: fd, object: f.object
  %div.form-actions
    %div.row
      %div.col-md-offset-9.col-md-3
        %button.btn.green{:type => 'submit'} Submit

_form_body.html.haml

%div.form-group.form-md-line-input
  %label.control-label.col-md-3
    = I18n.t('columns.customer_name')
    %span.required *
  %div.col-md-6
    = f.text_field_tag :customer_name, placeholder: 'Customer Name', class: 'form-control'
    %div.form-control-focus
    %span.help-block Enter Customer Name
%div.form-group.form-md-line-input
  %label.control-label.col-md-3
    = I18n.t('columns.actual_customer')
    %span.required *
  %div.col-md-6
    = f.text_field_tag :actual_customer, placeholder: 'Actual Customer', class: 'form-control actual_customer'
    %div.form-control-focus
    %span.help-block Enter Actual Customer
%div.form-group.form-md-line-input
  %label.control-label.col-md-3
    = I18n.t('columns.bco')
    %span.required *
  .col-md-6
    .mt-radio-inline
      %label.mt-radio
        = f.radio_button :bco, true, :checked => true, class: 'bco'
        = I18n.t('columns.bco_splited')
        %span
      %label.mt-radio
        = f.radio_button :bco, false, class: 'non_bco'
        = I18n.t('columns.non_bco_splited')
        %span
%div.form-group.form-md-line-input
  = f.label :trade_id, class: 'col-md-3 control-label' do
    = I18n.t('columns.trade')
    %span.required *
  %div.col-md-6
    = f.select :trade_id, options_for_select(Trade.all.map{|l| [l.name + '(' + l.code + ')', l.id]}, object.trade_id), {}, {class: 'form-control'}
    %div.form-control-focus
    %span.help-block Enter Trade
%div.form-group.form-md-line-input
  = f.label :trade_id, class: 'col-md-3 control-label' do
    = I18n.t('columns.sub_trade')
    %span.required *
  %div.col-md-6
    = f.select :sub_trade_id, options_for_select(SubTrade.all.map{|l| [l.name + '(' + l.code + ')', l.id]}, object.trade_id), {}, {class: 'form-control'}
    %div.form-control-focus
    %span.help-block Enter Sub Trade
%div.form-group.form-md-line-input
  = f.label :bound, class: 'col-md-3 control-label' do
    = I18n.t('columns.bound')
    %span.required *
  .col-md-6
    = f.select :bound, PricingHistory.get_bound_array,
      {}, {class: 'form-control select2_category'}
    %div.form-control-focus
    %span.help-block Enter Bound
%div.form-group.form-md-line-input
  = f.label :sales_week_id, class: 'col-md-3 control-label' do
    Sales Week
    %span.required *
  %div.col-md-6
    = f.select :sales_week_id, options_for_select(SalesWeek.all.map{|sw| [sw.display, sw.id]}, object.sales_week_id), {}, {class: 'form-control'}
    %div.form-control-focus
    %span.help-block Enter Sales Week
%div.form-group.form-md-line-input
  = f.label :origin_location_id, class: 'col-md-3 control-label' do
    Origin Location
    %span.required *
  %div.col-md-6
    = f.select :origin_location_id, options_for_select(Location.all.map{|l| [l.name + '(' + l.code + ')', l.id]}, object.origin_location_id), {}, {class: 'form-control'}
    %div.form-control-focus
    %span.help-block Enter Origin Location
%div.form-group.form-md-line-input
  = f.label :destination_location_id, class: 'col-md-3 control-label' do
    Destination Location
    %span.required *
  %div.col-md-6
    = f.select :destination_location_id, options_for_select(Location.all.map{|l| [l.name + '(' + l.code + ')', l.id]}, object.destination_location_id), {}, {class: 'form-control'}
    %div.form-control-focus
    %span.help-block Enter Destination Location
%div.form-group.form-md-line-input
  = f.label :surcharge_group_id, class: 'col-md-3 control-label' do
    Surcharge Group
    %span.required *
  %div.col-md-6
    = f.select :surcharge_group_id, options_for_select(SurchargeGroup.all.map{|s| [s.code, s.id]}, object.surcharge_group_id), {}, {class: 'form-control'}
    %div.form-control-focus
    %span.help-block Enter Surcharge Group Code
%div.form-group.form-md-line-input
  = f.label :commodity_group_id, class: 'col-md-3 control-label' do
    Commodity Group
    %span.required *
  %div.col-md-6
    = f.select :commodity_group_id, options_for_select(CommodityGroup.all.map{|s| [s.name + '(' + s.code + ')', s.id]}, object.surcharge_group_id), {}, {class: 'form-control'}
    %div.form-control-focus
    %span.help-block Enter Commodity Group
%div.form-group.form-md-line-input
  = f.label :tier_id, class: 'col-md-3 control-label' do
    Tier
    %span.required *
  %div.col-md-6
    = f.select :tier_id, options_for_select(Tier.all.map{|s| [s.tier, s.id]}, object.tier_id), {}, {class: 'form-control'}
    %div.form-control-focus
    %span.help-block Enter Tier
%div.form-group.form-md-line-input
  = f.label :d2_volume, class: 'col-md-3 control-label' do
    D2 Volume
    %span.required *
  %div.col-md-6
    = f.number_field :d2_volume, class: 'form-control', 'aria-required' => true, 'aria-describedby' => 'number-error'
    %div.form-control-focus
    %span.help-block Enter D2 Volume
%div.form-group.form-md-line-input
  = f.label :d4_volume, class: 'col-md-3 control-label' do
    D4 Volume
    %span.required *
  %div.col-md-6
    = f.number_field :d4_volume, class: 'form-control', 'aria-required' => true, 'aria-describedby' => 'number-error'
    %div.form-control-focus
    %span.help-block Enter D4 Volume
%div.form-group.form-md-line-input
  = f.label :d5_volume, class: 'col-md-3 control-label' do
    D5 Volume
    %span.required *
  %div.col-md-6
    = f.number_field :d5_volume, class: 'form-control', 'aria-required' => true, 'aria-describedby' => 'number-error'
    %div.form-control-focus
    %span.help-block Enter D5 Volume
%div.form-group.form-md-line-input
  = f.label :d7_volume, class: 'col-md-3 control-label' do
    D7 Volume
    %span.required *
  %div.col-md-6
    = f.number_field :d7_volume, class: 'form-control', 'aria-required' => true, 'aria-describedby' => 'number-error'
    %div.form-control-focus
    %span.help-block Enter D7 Volume
%div.form-group.form-md-line-input
  = f.label :r2_volume, class: 'col-md-3 control-label' do
    R2 Volume
    %span.required *
  %div.col-md-6
    = f.number_field :r2_volume, class: 'form-control', 'aria-required' => true, 'aria-describedby' => 'number-error'
    %div.form-control-focus
    %span.help-block Enter R2 Volume
%div.form-group.form-md-line-input
  = f.label :r5_volume, class: 'col-md-3 control-label' do
    R5 Volume
    %span.required *
  %div.col-md-6
    = f.text_field_tag :r5_volume, class: 'form-control', 'aria-required' => true, 'aria-describedby' => 'number-error'
    %div.form-control-focus
    %span.help-block Enter R5 Volume

pricing_history_controller.rb

class PricingHistoriesController < ApplicationController
  before_action :set_pricing_history, only: [:show, :edit, :update, :destroy]

  def add_inquery

  end

  def index
    @pricing_histories = current_user.pricing_histories.all.order(updated_at: :desc)
  end

  def show
  end

  def new
    @pricing_history = current_user.pricing_histories.build
    @pricing_histories = []
    6.times do
      @pricing_histories << @pricing_history
    end
  end

  def edit
  end

  def create
    params["pricing_history"].each do |pricing_history|
      pricing_history = current_user.pricing_histories.build(pricing_history_params(pricing_history))
      pricing_history.tier_id = 3
      customer_name =  pricing_history.customer_name

      if pricing_history.bco == false && Scra.exists?(actual_customer: pricing_history.actual_customer)
        return redirect_to new_pricing_history_path, notice: init_message(:error, t('scras.record_exist'))
      end

      if (scra = Scra.find_by_customer_name(customer_name)).present?
        pricing_history.tier_id = Tier.find_by_scra_id(scra.id).id
      end

      if pricing_history.save
        # pricing_history.calculate!
        # redirect_to pricing_histories_path, notice: init_message(:success, t('message.new_success', page_name: t('page_name.pricing_history')))
      else
        render :new
      end
    end
    # @pricing_history = current_user.pricing_histories.build(pricing_history_params)
    # @pricing_history.tier_id = 3
    # customer_name =  @pricing_history.customer_name
    #
    # if @pricing_history.bco == false && Scra.exists?(actual_customer: @pricing_history.actual_customer)
    #   return redirect_to new_pricing_history_path, notice: init_message(:error, t('scras.record_exist'))
    # end
    #
    # if (scra = Scra.find_by_customer_name(customer_name)).present?
    #   @pricing_history.tier_id = Tier.find_by_scra_id(scra.id).id
    # end
    #
    # if @pricing_history.save
    #   @pricing_history.calculate!
    #   redirect_to @pricing_history, notice: init_message(:success, t('message.new_success', page_name: t('page_name.pricing_history')))
    # else
    #   render :new
    # end
  end

  def update
    if @pricing_history.update(pricing_history_params)
      if Scra.exists?(customer_name: @pricing_history.customer_name)
        @pricing_history.update_columns(tier_id: 3)
      end
      redirect_to @pricing_history, notice: init_message(:success, t('message.update_success', page_name: t('page_name.price_history')))
    else
      render :edit
    end
  end

  def destroy
    @pricing_history.destroy
    redirect_to pricing_histories_url, notice: init_message(:success, t('message.delete_success', page_name: t('page_name.price_history')))
  end

  private
    def set_pricing_history
      @pricing_history = PricingHistory.find(params[:id])
    end

    def pricing_history_params(element_params)
      element_params.permit(
        :sales_week_id,
        :trade_id,
        :sub_trade_id,
        :bound,
        :origin_location_id,
        :destination_location_id,
        :surcharge_group_id,
        :commodity_group_id,
        :tier_id,
        :customer_name,
        :actual_customer,
        :bco,
        :d2_volume,
        :d4_volume,
        :d5_volume,
        :d7_volume,
        :r2_volume,
        :r5_volume
      )
    end
end

【问题讨论】:

    标签: ruby-on-rails ruby


    【解决方案1】:

    您在 form_tag 定义的表单中调用 f.fields_for。 要使用f.fields_for,您需要使用form_for 定义模型。

    如果您想使用fields_for 而不使用form_for,请尝试删除开头的f.,然后使用:

    fields_for '' do |fd|
    

    【讨论】:

    • 非常感谢。实际上,在我在这里看到您的解决方案之前,我已经修复了它,现在我又遇到了另一个问题。我会将其作为另一个问题发布。祝你有美好的一天。 :))
    【解决方案2】:

    fields_for 为特定模型对象创建一个范围,并可用于form_for 助手。

    我已经看到了,您正在使用 form_tag,并且您期望该 form_tag 使用 fields_for 方法。因此它给出了错误。请查看fields_for的更多信息

    更新:

    使用下面给出的fields_for。您需要遍历控制器中new 操作中启动的pricing_histories 对象。

    = form_tag pricing_histories_path, **** do ||
      - @pricing_histories.each do |pricing_history|
        = fields_for 'pricing_history[]', pricing_history do |p|
          = render 'form_body', f: pricing_history, object: @pricing_history
    

    【讨论】:

    • 我正在关注本教程,他确实将 fields_for 与 form_tag 一起使用。但是,如果我把它改回 form_for,我会得到另一个错误。有什么建议吗?
    • @ĐỗTiến - 更新了我的答案以在您的场景中使用 fields_for 辅助方法。一旦尝试这种方式,如果有任何问题,请告诉我。
    • 实际上,我决定退回到 form_for。但无论如何,谢谢你的帮助。祝你有美好的一天。
    猜你喜欢
    • 2022-11-22
    • 1970-01-01
    • 2016-04-06
    • 1970-01-01
    • 2011-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多