对象未加载

esb*_*ngo 5 ruby ruby-on-rails

这是我用ruby/rails发生的最奇怪的事情.

我有一个模型,Store,has_many Balances.我有一个方法,根据商店的货币给我默认余额.

商店模型.

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
Run Code Online (Sandbox Code Playgroud)

平衡模型.

class Balance < ActiveRecord::Base

  belongs_to :balanceable, :polymorphic => true
  ...
end
Run Code Online (Sandbox Code Playgroud)

好的,那么在Balance控制器中我有show动作,它会给我一个特定的余额或默认值.

平衡控制器.

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
Run Code Online (Sandbox Code Playgroud)

现在这里有奇怪的部分......

如果我打电话给节目动作; 例如:

GET/api/stores/148 /余额/默认

它返回null(因为货币设置为null,并且没有使用null货币的Balance),并且生成的SQL查询是:

SELECT `balances`.* FROM `balances` WHERE `balances`.`balanceable_id` = 148 AND `balances`.`balanceable_type` = 'Store' AND `balances`.`currency` IS NULL
Run Code Online (Sandbox Code Playgroud)

所以我不知道为什么......它将货币设置为NULL.但是如果我在那个过程中的任何地方放了

把@ store.inspect放进去

或在default_balance方法内:

把self.inspect

它神奇地工作!!!

所以我不知道为什么会发生这种情况?...看起来商店对象在我" 检查 "它或类似的东西之前没有被加载.

谢谢

esb*_*ngo 0

好吧,经过一番调试,终于找到原因了……

Store模型中,我有一个 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
Run Code Online (Sandbox Code Playgroud)

因此,当我调用时,self.currency它首先转到 method_missing ,然后返回null。我在这里缺少的是电话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
Run Code Online (Sandbox Code Playgroud)

但我仍然想知道为什么在我打电话之后puts @store.inspect还是puts self.inspect效果很好?我的意思是,为什么在这种情况下super不需要那个电话?