Liz
Liz

Reputation: 1437

Call a Model Method with simple_form Submit in rails

I have a page on my app where the user selects a shipping option. I need to have their choice added to the order.total in the database. I have the following custom method in the order.rb model:

def update_order_from_shipping_page(shipping)
  new_total = self.total + self.shipping
  self.update_attributes(total: new_total)
end

And the following form in my view:

  %= simple_form_for @order, url: charges_update_order_path(:shipping), method: :post do |f| %>
    <div class="row">
      <div class="form-inputs text-left">
        <div class="form-group col-sm-6">
          <%= f.collection_radio_buttons :shipping, shipping_choices, :first, :last, item_wrapper_class: :block_radio_button_collection %>
        </div>
      </div> <!-- form inputs -->
    </div> <!-- choices row -->
    <div class="row">
    <%= f.button :submit, "Calculate Shipping" %>
  </div>
  <% end %>

And I have created the following route:

post 'charges/update_order'

I have this in my charges_controller:

  def update_order
    @order = current_order
    if @order.update_order_from_shipping_page(shipping)
      redirect_to new_charge_path and return
    else
      redirect_to :back
      flash[:notice] = "Something is amuck."
    end
  end

The radio buttons populate correctly and no console or server errors show up, but the total shown on the charges#new page does not reflect the updates that would have been triggered by the model method. Can anyone see where I'm going wrong?

Upvotes: 0

Views: 699

Answers (1)

Gerry
Gerry

Reputation: 10497

Your method receives a parameter (shipping) but it is not using it:

def update_order_from_shipping_page(shipping)
  new_total = self.total + self.shipping
  self.update_attributes(total: new_total)
end

new_total is adding self.shipping to self.total, instead of adding shipping. So, unless self.shipping already contains any data, it will not add anything.

As a result, when you call that method with:

@order.update_order_from_shipping_page(shipping)

it is not taking into account shipping and no update to total is done.

To fix it, change update_order_from_shipping_page method so it adds shipping instead of self.shipping:

def update_order_from_shipping_page(shipping)
  new_total = self.total + shipping
  self.update_attributes(total: new_total)
end

UPDATE

To avoid Array can't be coerced into BigDecimal, you need to get the correct value from the options Array and convert it to Integer/Float. To accomplish that update your controller's update_order method:

def update_order
  @order = current_order
  shipping = params[:order][:shipping].gsub(/[$,]/,""​).to_f  # new line added

  if @order.update_order_from_shipping_page(shipping)
    redirect_to new_charge_path and return
  else
    redirect_to :back
    flash[:notice] = "Something is amuck."
  end
end
  • gsub(/[$,]/,""​) is to remove currency characters ($ and ,)

  • to_f to convert String to Float.

Upvotes: 1

Related Questions