如何将user.id从一个控制器传递到另一个控制器"未定义的方法`id'为零:NilClass"

时间:2016-06-22 01:40:16

标签: ruby-on-rails devise stripe-payments

因此,我正在构建一个通过Stripe处理付款的电子商务平台。成功处理完成后,我想为页面管理员创建一个订单条目,以便在订单页面上查看。

Stripe成功处理付款,然后通过添加捕获的条目来创建订单:

  • @ product.id
  • @ user.id
  • @ product.price

产品和价格正在成功拉动,但遗憾的是@ user.id并没有被拉入记录中。我收到以下错误: "未定义的方法`id'为零:NilClass"。

**付款管理员**

class PaymentsController < ApplicationController
  def create
    token = params[:stripeToken]
    @product = Product.find(params[:product_id])
    @user = current_user
    # Create the charge on Stripe's servers - this will charge the user's card
    begin
      charge = Stripe::Charge.create(
        :amount => (@product.price*100).to_i, # amount in cents, again
        :currency => "usd",
        :source => token,
        :description => params[:stripeEmail]
      )

      if charge.paid
        Order.create!(          
          product_id: @product.id, 
          user_id: @user_id, 
          total: @product.price)
      end

      flash[:success] = "Payment processed successfully"
    rescue Stripe::CardError => e 
      #Card was declined
      body = e.json_body
      err = body[:error]
      flash[:error] = "Unfortunately, there was an error processing your payment: #{err[:message]}"
    end
    redirect_to product_path(@product)
  end
end

**命令控制器**

class OrdersController < ApplicationController
  protect_from_forgery with: :null_session

  def index
  end

  def show 
  end

  def create
  end

  def destroy
  end
end

**显示我正在呈现付款部分的页面(通过条纹)**

<div class="col-md-6 center text-center">
  <div class="container">
    <div class="header-spacing">
      <%= image_tag(@product.image_url, class:" img-responsive center") %>
    </div>

    <h2>
      <%= @product.name %>
    </h2>

    <h4>
      <%= @product.desc %>
      <%= @product.style %>
      <strong>$<%= '%.2f' % @product.price %></strong>
    </h4>

    <%= form_tag("/payments/create", remote: true) do %>
      <%= render partial: "shared/stripe_checkout_button" %>
      <%= hidden_field_tag(:product_id, @product.id) %>
    <% end %>
  </div>
</div>

**我的OrdersController **

class OrdersController < ApplicationController
  # before_filter :authenticate_user!
  protect_from_forgery with: :null_session

  def index
  end

  def show 
  end

  def create
    @order = Order.create(order_params)
    respond_with @order
  end

  def destroy
  end

  private

  def order_params
    params.require(:order).permit(:product_id, :user_id, :total)
  end
end

现在我已经考虑过添加:

<%= hidden_field_tag(:user_id, @user.id) %>

但我得到完全相同的错误。

非常感谢任何帮助。

更新

结果发现我正在制作的AJAX请求没有携带CSRF令牌。出于这个原因,Rails杀了我的会话。我在paymentController中添加了skip_before_filter:verify_authenticity_token,现在一切都很顺利。

但我仍然想知道如何修复/为什么会发生这种情况,如果有人有任何信息

更新2

既然我已经更好地理解了这个问题,我发现一个较旧的帖子处理这个问题,可能会对其他人有所帮助。

Rails simple form gives InvalidAuthenticityToken error

1 个答案:

答案 0 :(得分:4)

基本上,form_tag不会自动生成CSRF令牌,除非明确告知这样做,但是form_for标签也没有,因为它们在Rails 4中切断了它。

我只是通过在表单中​​添加隐藏输入来解决问题:

<%= form_tag("/payments/create", remote: true) do %>
   <%= render partial: "shared/stripe_checkout_button" %>
   <%= hidden_field_tag(:product_id, @product.id) %>
   <input type="hidden" value="<%= form_authenticity_token() %>"name="authenticity_token"/>
<% end %>

他们切断自动生成CSRF令牌的主要原因与人员碎片缓存有关,因为当从缓存中提取表单时,后续请求中的真实性令牌会出错。