2014-12-22 16 views
1

我試圖實現一項功能,用戶可以使用訂閱代碼註冊訂閱。這是我的代碼:在ActiveRecord方法中對數據庫進行非預期的第二次調用

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 

我得到一個無方法的錯誤,這是我的日誌。

處理由SubscriptionsController#創建爲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

你可以從SubscriptionsController添加'create'動作嗎? – tagCincy

+0

在 – DaneEH

+0

中添加了創建我會添加一些記錄器消息,以找出哪些代碼正在多次被擊中。 – tagCincy

回答

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,並且該錯誤將附加到訂閱。

末點,這是一個小點,但nil是Rails的假,所以不是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。驗證是爲了保持數據庫中的數據一致,而不是虛擬屬性。

+0

我得到一個SystemStackError:堆棧層太深。當我查看日誌時,它反覆更新訂閱。爲什麼現在調用遞歸? – DaneEH

相關問題