这是我使用 ruby/rails 遇到的最奇怪的事情。
我有一个模型,商店,它有很多余额。我有一种方法可以根据商店的货币为我提供默认余额。
商店模型。
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
好的,那么在 Balance Controller 中我有 show 操作,它会给我一个特定的余额或默认余额。
平衡 Controller 。
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
现在奇怪的部分来了......
如果我调用 show Action ;例如:
GET /api/stores/148/balances/default
返回null(因为币种设置为null,不存在币种为null的Balance),生成的SQL查询为:
SELECT `balances`.* FROM `balances` WHERE `balances`.`balanceable_id` = 148 AND `balances`.`balanceable_type` = 'Store' AND `balances`.`currency` IS NULL
所以我不知道为什么...它将 currency 设置为 NULL。 但是如果我在那个过程中的任何地方放置
puts @store.inspect
或者在 default_balance
方法中:
puts self.inspect
它神奇地起作用了!!!
所以我不知道为什么会这样?...似乎直到我“检查”或类似的东西才加载商店对象。
谢谢
最佳答案
山姆和阿德里安走在正确的道路上。
ActiveRecord 重写 method_missing 以添加一大堆动态方法,包括用于列支持属性(如 Store#currency)的访问器。虽然我掩饰了很多,但我只想说当调用逻辑时,动态类/实例方法被添加到 Store 类/实例,以便后续调用不再需要 method_missing Hook 。
当您在不调用 super 的情况下覆盖 method_missing 时,您实际上禁用了此功能。幸运的是,可以通过其他方式调用此功能,其中一种方式是您在调用 store#inspect 时遇到的。
通过添加对 super 的调用,您只需确保 ActiveRecord 的动态方法总是在需要时添加到类中。
关于ruby-on-rails - 对象未加载,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/13378349/