0
votes

currently I am adding a new feature for my application which is allowing the user to submit many forms of the same object with one submit button.

I've just added the 'add_inquery' button that when a user clicks on it, a new form will be rendered(in the same page). I don't limit the numbers of the forms that the users want to submit. Generally, they can submit from 10 to 20 forms if they want.

The error I get is:

undefined method `fields_for' for nil:NilClass

Here are all of my codes:

_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
2

2 Answers

0
votes

You are calling f.fields_for inside a form_tag defined form. To use the f.fields_for you need to have a defined model using form_for.

If you wish to use fields_for without using form_for, try removing the f. at the beginning and just use:

fields_for '' do |fd|
0
votes

fields_for creates a scope for a specific model object and will be available for form_for helper.

I have seen that, you are using form_tag, and you are expecting fields_for method for this form_tag. Hence it is giving error. Please check for more info for fields_for

Update:

Use the fields_for as given below. You need to loop through the pricing_histories objects that are initiated in new action in controller.

= 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