Possible Missing Value with Parameters in Rails Application

I'm new to Rails and I have no idea what's going on here. The app I'm building is an online store. The current functionality works, but the change I'm trying to implement doesn't work. As a starting point, I'll show you the working version I currently have. Here is my /show.html.erb directory:

<p id="notice"><%= notice %></p>

<h2>My Cart</h2>
<table class="table table-responsive table-striped">
    <thead>
        <tr>
            <th>Item</th>
            <th>Quantity</th>
            <th>Total Price in Galleons</th>
            <th>Total Price in Muggle Currency</th>
        </tr>
        <tbody>
            <%= render(@cart.line_items) %>
            <tr>
                <td>Total</td>
                <td><%= number_to_currency(@cart.total_price * 7.35) %></td>
                <td></td>
                <td></td>
            </tr>
        </tbody>
    </thead>
</table>

<br>

<div class="row">
    <div class="col-md-3">
        <div class="row">
            <div class="col-md-4">
                <%= link_to 'Back', products_path, :class => 'btn btn-primary whiteText' %>
            </div>
            <div class="col-md-4">
                <%= link_to "Checkout", new_charge_path, :class => 'btn btn-success whiteText' %>
            </div>
            <div class="col-md-4">
                <%= link_to 'Empty Cart', @cart, method: :delete, data: {confirm: 'Are you sure you want to empty your cart?'}, :class => 'btn btn-danger whiteText' %>
            </div>
        </div>
    </div>
    <div class="col-md-9"></div>
</div>

      

However, I want to modify the workflow a bit so that it uses my Order thumbnail to redirect the user to the address confirmation page (orders / new.html.erb) after clicking Checkout on the Cart display page. Once the address is validated, it should then redirect the customer to the payment page, and this is what overrides the new_load_path in my current Checkout link.

So, first, I replace the Checkout link and rotate it out of this:

<%= link_to "Checkout", new_charge_path, :class => 'btn btn-success whiteText' %>

      

:

<%= link_to "Checkout", new_order_path, method: :get, :class => 'btn btn-success whiteText' %>

      

This redirect functions as expected and returns me to order / new.html.erb which contains the following:

<h1>Order Information</h1>

<br>

<%= render 'form', order: @order %>

<%= link_to 'Back', products_path %>

      

The form it provides contains the following code:

<%= form_for(order) do |f| %>
  <% if order.errors.any? %>
    <div id="error_explanation">
      <h2><%= pluralize(order.errors.count, "error") %> prohibited this order from being saved:</h2>

      <ul>
      <% order.errors.full_messages.each do |message| %>
        <li><%= message %></li>
      <% end %>
      </ul>
    </div>
  <% end %>


  <div class="row">

    <div class="col-md-6">

      <div class="field">
        <%= f.label :first_name %>
        <%= f.text_field :first_name, size: 20, :value => current_user.first_name, :class => "form-control" %>
      </div>

      <div class="field">
        <%= f.label :last_name %>
        <%= f.text_field :last_name, size: 20, :value => current_user.last_name, :class => "form-control" %>
      </div>

      <div class="field">
        <%= f.label :address %>
        <%= f.text_area :address, size: 40, :value => current_user.address, :class => "form-control" %>
      </div>

      <div class="field">
        <%= f.label :city %>
        <%= f.text_area :city, size: 20, :value => current_user.city, :class => "form-control" %>
      </div>  

      <div class="field">
        <%= f.label :state %>
        <%= f.text_area :state, size: 2, :value => current_user.state, :class => "form-control" %>
      </div>  

      <div class="field">
        <%= f.label :email %>
        <%= f.text_field :email, size: 40, :value => current_user.email, :class => "form-control" %>
      </div>

      <div class="field">
        <%= f.label :pay_type %>
        <%= f.select :pay_type, Order.pay_types.keys, prompt: 'Select a payment method', :class => "form-control" %>
      </div>

    </div>  



      <div class="col-md-6">

        <%= form_tag(payments_path, class: "form-inline") do %>
          <%= hidden_field_tag(:purchase_amount_cents, @cart.total_price) %>
          <div class="form_group">
            <%= label_tag(:credit_card_number, "Credit Card Number", class: "sr-only") %>
            <%= text_field_tag(:credit_card_number, "", class: "form-control", placeholder: "Credit Card #") %>
          </div>
          <br>
          <div class="form_group">
            <%= label_tag(:expiration_month, "Month", class: "sr-only") %>
            <%= text_field_tag(:expiration_month, "", class: "form-control", placeholder: "Month") %>
            <br>
            <%= label_tag(:expiration_year, "Year", class: "sr-only") %>
            <%= text_field_tag(:expiration_year, "", class: "form-control", placeholder: "Year") %>
            <br>
            <%= label_tag(:cvc, "Year", class: "sr-only") %>
            <%= text_field_tag(:cvc, "", class: "form-control", placeholder: "CVC #") %>
          </div>
          <br>
          <div class="form_group">
            <%= submit_tag("Purchase Cart", class: "btn btn-default", id: "purchase") %>
          </div>
        <% end %>

      </div>



  </div>


  <hr>

  <div class="actions">
    <%= f.submit 'Proceed to Payment' %>
  </div>
<% end %>

      

The payment options are Credit Card (Stripe) or Paypal. I will eventually add the Paypal feature, but the Stripe API is all I have.

Here is my order controller:

class OrdersController < ApplicationController
  include CurrentCart
  before_action :set_cart, only: [:new, :create]
  before_action :ensure_cart_isnt_empty, only: :new
  before_action :set_order, only: [:show, :edit, :update, :destroy]

  # GET /orders
  # GET /orders.json
  def index
    @orders = Order.all
  end

  # GET /orders/1
  # GET /orders/1.json
  def show
  end

  # GET /orders/new
  def new
    @order = Order.new
  end

  # GET /orders/1/edit
  def edit
  end

  # POST /orders
  # POST /orders.json
  def create
    @order = Order.new(order_params)
    @order.add_line_items_from_cart(@cart)
    respond_to do |format|
      if @order.save
        format.html { redirect_to new_charge_path}
      else
        format.html { render :new }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

  # PATCH/PUT /orders/1
  # PATCH/PUT /orders/1.json
  def update
    respond_to do |format|
      if @order.update(order_params)
        format.html { redirect_to @order, notice: 'Order was successfully updated.' }
        format.json { render :show, status: :ok, location: @order }
      else
        format.html { render :edit }
        format.json { render json: @order.errors, status: :unprocessable_entity }
      end
    end
  end

  # DELETE /orders/1
  # DELETE /orders/1.json
  def destroy
    @order.destroy
    respond_to do |format|
      format.html { redirect_to orders_url, notice: 'Order was successfully destroyed.' }
      format.json { head :no_content }
    end
  end

  private
    # Use callbacks to share common setup or constraints between actions.
    def set_order
      @order = Order.find(params[:id])
    end

    # Never trust parameters from the scary internet, only allow the white list through.
    def order_params
      params.require(:order).permit(:first_name, :last_name, :address, :city, :state, :email, :pay_type)
    end

    def ensure_cart_isnt_empty
      if @cart.line_items.empty?
        redirect_to products_path, notice: 'Your cart is empty!'
      end
    end

end

      

Here is my charge controller:

class ChargesController < ApplicationController
    include CurrentCart
    before_action :set_cart, only: [:new, :create]

    def new
    end

    def create #METHOD IS CALLED AFTER PAYMENT IS MADE
     # Amount in cents
     @amount = @cart.total_price

     customer = Stripe::Customer.create(
       :email => params[:stripeEmail],
       :source  => params[:stripeToken]
     )

     charge = Stripe::Charge.create(
       :customer    => customer.id,
       :amount      => @amount,
       :description => 'Customer',
       :currency    => 'usd'
     )

     Cart.destroy(session[:cart_id]) 

    rescue Stripe::CardError => e
      flash[:error] = e.message
      redirect_to new_charge_path
    end 

end

      

Here's the problem. While the redirects work as expected, @amount in the Charge controller is set to $ 0.00 if the order controller is used. If, however, the Cart link is directly linked to the Charge controller, then the correct dollar amount is used. So my guess is that somehow the cart object is lost or reset.

Here is my set_cart method:

def set_cart
      @cart = Cart.find(params[:id])
end

      

And here is my CurrentCart module:

module CurrentCart
  private
    def set_cart 
      @cart = Cart.find(session[:cart_id])
    rescue ActiveRecord::RecordNotFound
      @cart = Cart.create
      session[:cart_id] = @cart.id
    end
end

      

+3


source to share


1 answer


My idea is that you need to pass @ cart.total_price value from cart form to order controller here, some steps to follow

inside your link (you pass the value as parameters)

<%= link_to "Checkout", new_order_path(total_price: @cart.total_price), method: :get, :class => 'btn btn-success whiteText' %>

      

inside order_controller (you get the parameters and put in the instance variabel)

  # GET /orders/new
  def new
    @order = Order.new
    @temp_total_price = params[:total_price]
  end

      



inside the insert order_form between your form_for tag, we have to put this in the form as a hidden value, so it can go to create the method for payment

<%= hidden_field_tag 'total_price', @temp_total_price  %>

      

inside your class ChargesController create method you can get total_price

@total_price = params[:total_price]

      

I know this a bit, but maybe it can help

0


source







All Articles