ruby-on-rails - Rails 应用程序中的参数可能缺少值

标签 ruby-on-rails e-commerce stripe-payments

我是 Rails 的新手,我不知道这里发生了什么。我正在构建的应用程序是一个在线商店。当前功能有效,但我尝试实现的更改无效。作为起点,我将展示我现在拥有的工作版本。这是我的 carts/show.html.erb 文件:

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

但是,我想稍微更改一下工作流程,以便在单击购物车显示页面上的“结帐”后,它使用我的订单脚手架将用户重定向到地址确认页面 (orders/new.html.erb)。确认地址后,它应该将客户引导至付款页面,这是我当前结帐链接中的 new_charge_path 已经重定向到的页面。

所以首先,我要替换 Checkout 链接并将其转换为:

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

为此:

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

此重定向按预期运行,并将我带到 orders/new.html.erb,其中包含以下内容:

<h1>Order Information</h1>

<br>

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

<%= link_to 'Back', products_path %>

它呈现的表单包含以下代码:

<%= 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 %>

付款选项为信用卡 (Stripe) 或 Paypal。我最终会添加 Paypal 功能,但 Stripe API 是我现在所拥有的。

这是我的订单 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

这是我的充电 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

问题来了。虽然重定向按预期工作,但如果使用订单 Controller ,收费 Controller 中的@amount 将设置为 $0.00。但是,如果 Cart 直接链接到 Charge Controller ,则会使用正确的金额。因此,我假设购物车对象以某种方式丢失或重置其值。

这是我的 set_cart 方法:

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

这是我的 CurrentCart 模块:

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

最佳答案

我的想法是您需要将值@cart.total_price 从购物车显示表单传递给订单 Controller ,这里有一些步骤要做

在您的链接中(您将值作为参数传递)

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

在 order_controller 内部(你得到参数并放入实例变量)

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

在 order_form 中插入你的 form_for 标签,我们需要把它作为隐藏值放在表单中,这样它就可以传递给 create 方法进行收费

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

在你的类 ChargesController create 方法中你可以获得 total_price

@total_price = params[:total_price]

我知道这有点日志,但这可能会有所帮助

关于ruby-on-rails - Rails 应用程序中的参数可能缺少值,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/45106794/

相关文章:

javascript - Stripe 元素基于什么?他们如何保护它?

ruby-on-rails - 使用 nginx 映射 Rails 应用程序

jquery - 使用 jQuery 和 AJAX 将参数从 Controller 传递到 javascript,以在 Ruby on Rails 中渲染 View

ruby-on-rails - Rails 基于位置的搜索不适用于 Heroku

java - 如何从命令提示符或管理控制台停止 Hybris 服务器

&lt;script&gt; 标签中的 Javascript 变量

javascript - 如何将 Stripe 支付库与 HTML/JS 中单选按钮选择的多个按钮结合起来

ruby-on-rails - 具有 join_table 和 has_many 的模型的路由错误 :through in RailsAdmin

mysql - 设计电子商务数据库 - MySQL

php - Magento 四舍五入货币转换