如何将 user.id 从一个控制器传递到另一个 "undefined method `id' for nil:NilClass"

How to pass user.id from one controller to another "undefined method `id' for nil:NilClass"

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

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

商品和价格拉取成功,可惜@user.id没有拉入记录。我收到以下错误: "undefined method `id' for nil: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

** 显示我呈现部分付款的页面(通过 Stripe)**

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

** 我的订单控制器 **

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 终止了我的会话。我在我的 paymentsController 中添加了 skip_before_filter :verify_authenticity_token ,现在一切都很好。

但我仍然想知道如何fix/why发生这种情况,如果有人有任何信息

更新 2

现在我更好地理解了这个问题,我找到了一个更老的 post 处理这个问题,可能对其他人有帮助。

Rails simple form gives InvalidAuthenticityToken error

基本上 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 令牌的主要原因与人员片段缓存有关,因为当从缓存中提取表单时,后续请求的真实性令牌将是错误的。