2012-11-14 166 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的动态方法总是在需要时添加到类中。