我知道这种问题已经多次回答了,但是我真的无法弄清楚这里导致问题的原因,我在解决这个问题时遇到了麻烦。我在尝试创建新注册时遇到同样的错误(http://localhost:3000/registrations/new?course_id=1):
NoMethodError at /registrations
undefined method `id' for nil:NilClass
这是我的RegistrationsController:
class RegistrationsController < ApplicationController
before_action :set_registration, only: [:show, :edit, :update, :destroy]
def index
@registrations = Registration.all
end
def show
end
def new
@registration = Registration.new
@course = Course.new
@course = Course.find_by id: params["course_id"]
end
def create
@registration = Registration.new registration_params.merge(email: stripe_params["stripeEmail"], card_token: stripe_params["stripeToken"])
raise "Please Check Registration Errors" unless @registration.valid?
@registration.process_payment
@registration.save
redirect_to @registration, notice: 'Registration was successfully created.'
rescue Exception => e
flash[:error] = e.message
render :new
end
protect_from_forgery except: :webhook
def webhook
event = Stripe::Event.retrieve(params["id"])
case event.type
when "invoice.payment_succeeded" #renew subscription
Registration.find_by_customer_id(event.data.object.customer).renew
end
render status: :ok, json: "success"
end
private
def stripe_params
params.permit :stripeEmail, :stripeToken
end
def set_registration
@registration = Registration.find(params[:id])
end
def registration_params
params.require(:registration).permit(:course_id, :full_name, :company, :telephone, :email, :card_token)
end
end
我的注册模式:
class Registration < ActiveRecord::Base
belongs_to :course
def process_payment
customer_data = {email: email, card: card_token}.merge((course.plan.blank?)? {}: {plan: course.plan})
customer = Stripe::Customer.create customer_data
Stripe::Charge.create customer: customer.id,
amount: course.price * 100,
description: course.name,
currency: 'usd'
#Annotate Customer Id when Registration is Created
cusotmer_id = customer.id
end
def renew
update_attibute :end_date, Date.today + 1.month
end
end
注册New.html.haml文件:
%section#course-content
%section#ruby
%section.detailed-syllabus
.wrapper-inside
= form_for @registration, html: { class: "basic-grey" } do |f|
- if @registration.errors.any?
#error_explanation
%h2
= pluralize(@registration.errors.count, "error")
prohibited this registration from being saved:
%ul
- @registration.errors.full_messages.each do |message|
%li= message
.field
= f.hidden_field :course_id, value: @course.id
.field
= f.label :full_name
= f.text_field :full_name
.field
= f.label :company
= f.text_field :company
.field
= f.label :email
= f.text_field :email
.field
= f.label :telephone
= f.text_field :telephone
//‘Stripe.js’ will recognize the card data because we have marked the inputs with ‘data-stripe’ attribute as: number, cvv, exp-month and exp-year.
= javascript_include_tag "https://js.stripe.com/v2/"
:javascript
Stripe.setPublishableKey('#{Rails.application.secrets.stripe_publishable_key}');
= label_tag "Card Number", nil, required: true
.control-group
.controls
= text_field_tag :card_number, nil, class: "input-block-level", "data-stripe" => "number"
= label_tag "Card Verification", nil, required: true
.control-group
.controls
= text_field_tag :card_verification, nil, class: "input-block-level", "data-stripe" => "cvv"
= label_tag "Card Expires", nil, required: true
= select_tag :exp_month, options_for_select(Date::MONTHNAMES.compact.each_with_index.map { |name,i| ["#{i+1} - #{name}", i+1] }), include_blank: false, "data-stripe" => "exp-month", class: "span2"
= select_tag :exp_year, options_for_select((Date.today.year..(Date.today.year+10)).to_a), include_blank: false, "data-stripe" => "exp-year", class: "span1"
.actions
= f.submit "Registration Payment", class: "btn", style: "color: white;background: rgb(242, 118, 73);"
有谁知道如何帮助我?非常感谢所有的帮助。 附加任何人都可以指导我如何在两个模型之间传递id,就像这个人在两个模型之间做的那样,因为他为一个模型创建了一个脚手架但是传递ID让他也可以为另一个模型创建值而无需为另一个模型创建动作https://github.com/gotealeaf/stripe-basics.git
编辑: 本代码的GitHub存储库 https://github.com/ChiragArya/Stripe_CheckOut_Demo
答案 0 :(得分:1)
根据您的评论,出现错误的原因是:
@course.id
为nil
解决此问题的方法是确保正确定义@course
。您需要执行以下操作:
def new
@registration = Registration.new
@course = Course.find_by id: params["course_id"]
end
您在此处遇到的另一个问题是,您的路由应该能够处理courses
而无需使用?course_id=1
附加它们:
#config/routes.rb
resources :registrations do
get :course_id, to: "registrations#new" #-> yoururl.com/registrations/:course_id
end
这仍然会在course_id
操作中为您提供new
参数;只是让它更多Rails。
-
<强>控制器强>
你的代码中也需要一些结构(你的目标是fat model, thin controller)。看起来你是以Ruby开发者的身份来到Rails;您需要了解Rails会为您处理大部分异常等。
具体来说,您需要了解如何从代码中删除代码:
def create
@registration = Registration.new registration_params
@registration.process_payment
if @registration.save
redirect_to @registration, notice: 'Registration was successfully created.'
else
# handle error here
end
end
private
def registration_params
params.require(:registration).permit(:course_id, :full_name, :company, :telephone, :email, :card_token).merge(email: stripe_params["stripeEmail"], card_token: stripe_params["stripeToken"])
end
-
`id'代表nil:NilClass
最后,你必须记住这个错误基本上意味着你试图调用一个动作的变量是nil
。
Ruby使用nil
对象填充NilClass
变量,因此很难确定错误实际是什么。所有这意味着你试图在上调用方法的变量没有上述方法,因为Ruby已经用NilClass
对象填充它。
答案 1 :(得分:0)
尝试将注册#新操作更改为
def new
@course = Course.find(params[:course_id])
@registration = @course.registrations.new
end
答案 2 :(得分:0)
在GROUP BY ?class
def create