对象没有被加载(Object does not get loaded)

编程入门 行业动态 更新时间:2024-10-25 09:36:30
对象没有被加载(Object does not get loaded)

这是使用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控制器中我有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
 

现在这里是奇怪的部分来...

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

GET / api / stores / 148 / balances / default

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

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

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

puts @ store.inspect

或者在default_balance方法中:

提出自己的看法

它神奇地工作!!!。

所以我不知道为什么会发生这种情况?......看起来商店对象没有被加载,除非我“ 检查 ”它或类似的东西。

谢谢

This is the weirdest thing ever happened to me with ruby/rails.

I have a model, Store, which has_many Balances. And I have a method that gives me the default balance based on the store's currency.

Store model.

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
 

Balance model.

class Balance < ActiveRecord::Base

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

Ok, so then in the Balance controller I have the show action, that will give me a specific balance or the default one.

Balance 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
 

Now here is where the weird part comes...

If I make a call to the show action; for example:

GET /api/stores/148/balances/default

It returns null (because the currency was set as null, and there is no Balance with null currency), and the SQL query generated is:

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

So I DON'T know why... it is setting the currency as NULL. BUT if in any where in that process I put

puts @store.inspect

or inside the default_balance method:

puts self.inspect

it magically works!!!.

So I don't know why is that happening?... It seems like the store object is not getting loaded until I "inspect" it or something like that.

Thanks

最满意答案

萨姆和阿德里安走在正确的道路上。

ActiveRecord覆盖method_missing以添加一大堆动态方法,包括支持列的属性(如Store#货币)的访问器。 虽然我在这方面做了很多工作,但足以说明,当调用逻辑时,动态类/实例方法将被添加到Store类/实例,以便后续调用不再需要method_missing挂钩。

如果您在不调用super的情况下覆盖method_missing,则会有效地禁用此功能。 幸运的是,此功能可以通过其他方式调用,其中一种方式是在您调用store#inspect时触发的其中一种方法。

通过添加对super的调用,您只需确保ActiveRecord的动态方法总是在需要时添加到类中。

OK finally after a lot of debugging, I found the reason...

In the Store model I have a method_missing method and I had it like this:

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
 

So when I was calling self.currency it went first to the method_missing and then returned null. What I was missing here was the super call.

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
 

But I continue wondering why after I had called puts @store.inspect or puts self.inspect it worked well?. I mean, why in that case that super call wasn't needed?

更多推荐

本文发布于:2023-07-30 01:29:00,感谢您对本站的认可!
本文链接:https://www.elefans.com/category/jswz/34/1321389.html
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系,我们将在24小时内删除。
本文标签:加载   对象   loaded   Object

发布评论

评论列表 (有 0 条评论)
草根站长

>www.elefans.com

编程频道|电子爱好者 - 技术资讯及电子产品介绍!