nil:NilClass 的 NoMethodError 未定义方法“id”:
NoMethodError undefined method `id' for nil:NilClass:
我知道这类问题已经回答了多次,但我真的无法弄清楚是什么导致了这里的问题,我在解决这个问题时遇到了麻烦。当我尝试创建新注册 ( 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);"
有人知道如何帮助我吗?非常感谢所有帮助。
任何人都可以指导我如何在 2 个模型之间传递 id,就像这个人在 2 个模型之间所做的那样,因为他正在为一个模型创建脚手架,但传递 ID 也可以让他为另一个模型创建值,而无需为另一个控制器创建操作 https://github.com/gotealeaf/stripe-basics.git
已编辑:
GitHub 此代码的存储库
https://github.com/ChiragArya/Stripe_CheckOut_Demo
尝试将注册#new 操作更改为
def new
@course = Course.find(params[:course_id])
@registration = @course.registrations.new
end
将此添加到您的 def create
def create
@course = Course.find_by id: params["registration"]["course_id"]
@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
@course = Course.find_by id: params["registration"]["course_id"]
render :new
end
根据您的评论,错误似乎是由以下原因引起的:
@course.id
being 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
这仍然会在 new
操作中为您提供 course_id
参数;只是让它更 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' for nil:NilClass
最后,你必须记住这个错误基本上意味着你试图为其调用操作的变量是 nil
。
Ruby 用 NilClass
对象填充 nil
变量,因此很难确定错误到底是什么。这意味着您尝试在 上调用方法的变量没有 具有上述方法,因为 Ruby 已经用 NilClass
填充了它对象。
我知道这类问题已经回答了多次,但我真的无法弄清楚是什么导致了这里的问题,我在解决这个问题时遇到了麻烦。当我尝试创建新注册 ( 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);"
有人知道如何帮助我吗?非常感谢所有帮助。 任何人都可以指导我如何在 2 个模型之间传递 id,就像这个人在 2 个模型之间所做的那样,因为他正在为一个模型创建脚手架,但传递 ID 也可以让他为另一个模型创建值,而无需为另一个控制器创建操作 https://github.com/gotealeaf/stripe-basics.git
已编辑: GitHub 此代码的存储库 https://github.com/ChiragArya/Stripe_CheckOut_Demo
尝试将注册#new 操作更改为
def new
@course = Course.find(params[:course_id])
@registration = @course.registrations.new
end
将此添加到您的 def create
def create
@course = Course.find_by id: params["registration"]["course_id"]
@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
@course = Course.find_by id: params["registration"]["course_id"]
render :new
end
根据您的评论,错误似乎是由以下原因引起的:
@course.id
beingnil
解决此问题的方法是确保正确定义 @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
这仍然会在 new
操作中为您提供 course_id
参数;只是让它更 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' for nil:NilClass
最后,你必须记住这个错误基本上意味着你试图为其调用操作的变量是 nil
。
Ruby 用 NilClass
对象填充 nil
变量,因此很难确定错误到底是什么。这意味着您尝试在 上调用方法的变量没有 具有上述方法,因为 Ruby 已经用 NilClass
填充了它对象。