2012-11-14 164 views
5

這是有史以來最紅的事情發生在我與紅寶石/鐵軌。對象沒有被加載

我有模特,店鋪,其中has_many 餘額。而且我有一種方法可以根據商店的貨幣爲我提供默認餘額。

商店模型。

class Store < ActiveRecord::Base 

    has_many :balances, as: :balanceable, dependent: :destroy 

    def default_balance 
    #puts self.inspect <- weird part. 
    balances.where(currency: self.currency)[0] 
    end 
    ... 
end 

平衡模型。

class Balance < ActiveRecord::Base 

    belongs_to :balanceable, :polymorphic => true 
    ... 
end 

好了,那麼在均衡控制器我有顯示行動,這會給我一個特定的餘額或默認的。

平衡控制器。

class Api::Stores::BalancesController < Api::Stores::BaseController 

    before_filter :load_store 

    # Returns a specific alert 
    # +URL+:: GET /api/stores/:store_id/balances/:id 
    def show 
    #puts @store.inspect <- weird part. 
    @balance = (params[:id] == "default") ? @store.default_balance : Balance.find(params[:id]) 
    respond_with @balance, :api_template => :default 
    end 
    ... 

    private 
    # Provides a shortcut to access the current store 
    def load_store 
     @store = Store.find(params[:store_id]) 
     authorize! :manage, @store 
    end 
end 

現在這裏是怪異的一部分來... ...

如果我做的演出行動的呼籲;例如:

GET/API /專賣店/ 148 /餘額/默認

它返回null(因爲貨幣被設置爲空,且有與空的貨幣無餘額),以及生成的SQL查詢是:

SELECT `balances`.* FROM `balances` WHERE `balances`.`balanceable_id` = 148 AND `balances`.`balanceable_type` = 'Store' AND `balances`.`currency` IS NULL 

,所以我不知道爲什麼...它是設置貨幣爲NULL。 如果在這個過程中的任何地方,我把

提出@ store.inspect

default_balance方法中:

提出self.inspect

它神奇的作品!

所以我不知道爲什麼會發生這種情況......看起來像商店對象沒有加載,直到我「檢查」它或類似的東西。

謝謝

+0

「貨幣」是表格專賣店的一列嗎? – Yanhao

+0

是的。 '貨幣:字符串(255)' – esbanarango

+0

嘗試在查詢之前調試對象 –

回答

0

好不容易經過很多調試,我找到了原因...

商店模型我有一個method_missing的方法,我有這樣的:

def method_missing method_name, *args 
    if method_name =~ /^(\w+)_togo$/ 
    send($1, *args).where(togo: true) 
    elsif method_name =~ /^(\w+)_tostay$/ 
    send($1, *args).where(tostay: true) 
    end 
end 

所以,當我打電話self.currency它首先去的method_missing方法,然後返回。我在這裏失蹤的是super電話。

def method_missing method_name, *args 
    if method_name =~ /^(\w+)_togo$/ 
    send($1, *args).where(togo: true) 
    elsif method_name =~ /^(\w+)_tostay$/ 
    send($1, *args).where(tostay: true) 
    else 
    super 
    end 
end 

但我仍然不知道我曾打電話puts @store.inspectputs self.inspect效果不錯後,爲什麼?我的意思是,爲什麼在那種情況下super電話不需要?

+1

大概是因爲'檢查'調用了表中所有列的方法。 –

+0

Adrien是正確的''檢查'是在'Object'中定義的,你的隱式下降。如果方法在類中或其祖先中找不到,則僅調用「method_missing」。 –

1

Sam和Adrien走在正確的道路上。

ActiveRecord重寫method_missing以添加一大堆動態方法,包括支持列的屬性(如Store#貨幣)的訪問器。雖然我在這方面做了很多工作,但足以說明,當調用邏輯時,動態類/實例方法將被添加到Store類/實例,以便後續調用不再需要method_missing掛鉤。

如果您在不調用super的情況下覆蓋method_missing,則會有效地禁用此功能。幸運的是,此功能可以通過其他方式調用,其中一種方式是在您調用store#inspect時觸發的其中一種方法。

通過添加對super的調用,您只需確保ActiveRecord的動態方法總是在需要時添加到類中。