我试图实现一个功能,用户可以使用订阅代码注册订阅。这是我的代码:
class SubscriptionsController < ApplicationController
def create
@subscription = current_user.subscriptions.build(subscription_params)
respond_to do |format|
if @subscription.save
format.html { redirect_to @subscription, notice: 'Subscription was successfully created.' }
format.json { render :show, status: :created, location: @subscription }
else
format.html { render :new }
format.json { render json: @subscription.errors, status: :unprocessable_entity }
end
end
end
end
class Subscription < ActiveRecord::Base
belongs_to :user
belongs_to :topic
has_one :subscription_code
before_validation :register_subscription
after_save :register_expiry_date
validates_presence_of :submitted_code, :topic_id, :subscription_code_id
attr_accessor :submitted_code
private
def register_subscription
registered_code_id = SubscriptionCode.register_subscription_code(self.submitted_code)
unless registered_code_id == nil
self.subscription_code_id = registered_code_id
else
errors.add(:submitted_code, "Invalid Code")
return false
end
end
def register_expiry_date
self.expiry_date ||= self.created_at + 1.year
self.save
end
end
class SubscriptionCode < ActiveRecord::Base
belongs_to :subscription
attr_accessor :number_of_codes
def self.register_subscription_code(submitted_code)
matched_code = find_by(code: submitted_code, used: false)
matched_code.update(used: true, date_used: DateTime.now)
return matched_code.id
end
end
我得到一个no方法错误,这是我的日志。
SubscriptionsController处理#create as HTML 参数:
{"utf8"=>"✓", "authenticity_token"=>"iV5cOOi+IgyVUuq0rR5yIdCwYDCrRHGf4Hvw25kGso0=", "subscription"=>{"topic_id"=>"1", "submitted_code"=>"89aaa22e40958b40092f"}, "commit"=>"Create Subscription"}
User Load (0.3ms) SELECT "users".* FROM "users" WHERE "users"."id" = $1 LIMIT 1 [["id", 3]]
(0.2ms) BEGIN
SubscriptionCode Load (0.7ms) SELECT "subscription_codes".* FROM "subscription_codes" WHERE "subscription_codes"."code" = '89aaa22e40958b40092f' AND "subscription_codes"."used" = 'f' LIMIT 1
SQL (35.8ms) UPDATE "subscription_codes" SET "date_used" = $1, "updated_at" = $2, "used" = $3 WHERE "subscription_codes"."id" = 7 [["date_used", "2014-12-22 15:31:45.258082"], ["updated_at", "2014-12-22 15:31:45.280165"], ["used", "t"]]
SQL (1.4ms) INSERT INTO "subscriptions" ("created_at", "subscription_code_id", "topic_id", "updated_at", "user_id") VALUES ($1, $2, $3, $4, $5) RETURNING "id" [["created_at", "2014-12-22 15:31:45.318757"], ["subscription_code_id", 7], ["topic_id", 1], ["updated_at", "2014-12-22 15:31:45.318757"], ["user_id", 3]]
SubscriptionCode Load (0.6ms) SELECT "subscription_codes".* FROM "subscription_codes" WHERE "subscription_codes"."code" = '89aaa22e40958b40092f' AND "subscription_codes"."used" = 'f' LIMIT 1
(0.3ms) ROLLBACK
Completed 500 Internal Server Error in 129ms
NoMethodError - undefined method `update' for nil:NilClass:
app/models/subscription_code.rb:17:in `register_subscription_code'
答案 0 :(得分:0)
一些观察结果:
您将在每次保存时调用:register_subscription
,无论是创建还是更新。
尝试:
before_validation :register_subscription, on: :create
此外,如果:register_subscription_code
无法找到代码,则会抛出undefined method update
错误。尝试:
def self.register_subscription_code(submitted_code)
matched_code = find_by(code: submitted_code, used: false)
return nil unless matched_code
matched_code.update(used: true, date_used: DateTime.now)
matched_code.id # returns are implied at the ends of methods
end
此方法将返回nil,错误将附加到Subscription。
最后一点,这是一个小问题,但在Rails中nil
是假的,因此unless registered_code_id == nil
代替if registered_code_id
更容易阅读submitted_code
最后一点,您已经在:register_subscription
上进行了验证,因此您无需在def register_subscription
self.subscription_code_id = SubscriptionCode.register_subscription_code(self.submitted_code)
end
中对其进行预验证。它只需要看起来像这样:
submitted_code
好的,最后一点,您不需要在attr_accessor
上验证,这是{{1}}。验证用于保持数据库中的数据一致,而不是虚拟属性。