【问题标题】:Possible missing value with parameters in Rails appRails 应用程序中的参数可能缺少值
【发布时间】:2017-12-19 18:44:17
【问题描述】:

我是 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 重定向到的页面。

首先,我将替换结帐链接并将其转为:

<%= 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 是我现在所拥有的。

这是我的订单控制器:

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

这是我的充电控制器:

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

这就是问题所在。虽然重定向按预期工作,但如果使用订单控制器,则 Charge 控制器中的 @amount 设置为 $0.00。但是,如果 Cart 直接链接到 Charge 控制器,则使用正确的美元金额。因此,我假设购物车对象以某种方式丢失或重置其值。

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

【问题讨论】:

  • 收费后,Stripe 是否会回拨到ChargesController#create(在 webhook 中)?
  • 我不这么认为。
  • 显示set_cart 方法以及CurrentCart 中的内容
  • 好的,我更新了我的问题以包含 set_cart 方法和 CurrentCart 模块。

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


【解决方案1】:

我的想法是,您需要将值 @cart.total_price 从购物车展示表单传递给订单控制器,这里需要执行一些步骤

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

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

在你的form_for标签之间插入order_form,我们需要把它作为隐藏值放在表单中,所以它可以传递给创建收费方法

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

在您的类 ChargesController 创建方法中,您可以获得总价格

@total_price = params[:total_price]

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

【讨论】:

  • 不幸的是,当我尝试这样做时,我在充电控制器中收到一个错误,表明未设置金额。
  • 尝试在视图和控制器之间进行跟踪,您可以使用 puts 命令进行跟踪,例如在 order_controller 中跟踪新命令后您可以跟踪 puts params[:total_price] 检查它是否为 nil / 0 / 其他值跨度>
  • 我尝试使用“at”cart.total_price 在订单创建方法中显示通知。它显示正确的金额,因此订单控制器肯定能够访问“at”cart.total_price 的金额。但由于某种原因,充电控制器不能。我在此评论中使用“at”,因为 Stack Overflow 不允许使用该符号。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-11-12
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多