Rails 3 ActiveRecord :: Relation随机关联行为 [英] Rails 3 ActiveRecord::Relation random associations behavior

查看:128
本文介绍了Rails 3 ActiveRecord :: Relation随机关联行为的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前有一个奇怪的问题,那就是从Rails 2.3.8迁移到Rails 3(3.0.1、3.0.2、3.0.3)的应用程序. 在随机时刻,联想行为异常.在某些情况下,关联的对象将返回Relation对象,而不是相应的模型.这似乎主要发生在多态关联上.例如:

I am currently having a strange issue with an application migrated from rails 2.3.8 to rails 3 (3.0.1, 3.0.2, 3.0.3). At random moments associations behave strangely. In some cases, an associated object will return the Relation object, instead of the corresponding model. This seems to happen mostly on polymorphic associations. For example:

class A
  belongs_to :b, :polymorphic => true
end

class B
  has_many :a, :as => :source
end

当调用"a.b"时,它将有时"返回Relation对象(引起未定义的方法……导致ActiveRecord :: Relation"错误),而在其他时候,它将返回正确的B对象. 返回关系对象后,可能会有时通过重新启动服务器临时修复",但最终会再次出现.

When invoking "a.b" this will "sometimes" return the Relation object (causing a "undefined method ... for ActiveRecord::Relation" error to raise) and some other times it will return the correct B object. When the relation object is returned, it may sometimes be "fixed" temporarily by restarting the server, but it will eventually show up again.

我得到的另一个问题是,当获取"关联对象时,有时并不会自动应用所需的过滤器(其中元素id = ...).这将导致查询返回表中的第一个对象,而不是正确的关联对象.

Another issue i get is that when "getting" associated objects, sometimes the required filters are not automatically applied (where element id = ...). this causes the query to return the first object in the table and not the correct associated object.

这正成为一个令人沮丧的问题,特别是因为我似乎找不到其他人遇到此问题或类似问题.

This is becoming a very frustrating issue, specially since i don't seem to find anyone else with this or similar issues.

应用程序中的所有finder方法都已迁移到新的rails表单,但是这种奇怪的行为仍然存在.

All finder methods in the application have been migrated to the new rails form, but this strange behavior remains.

当前使用的配置是: 的Ubuntu 10 Nginx服务器 乘客(3.0.2) 导轨(3.0.3) 红宝石1.9.2p0(2010-08-18修订版29036)

The current configuration being used is: Ubuntu 10 nginx server passenger (3.0.2) rails (3.0.3) ruby 1.9.2p0 (2010-08-18 revision 29036)

推荐答案

在深入研究Active Record代码之后,我和我的同事发现,belongs_to_association.rb和belongs_to_polymorphic_association.rb仍在使用旧的查找程序. "find_target"方法中的方法.

After digging a bit deeper into the Active Record code, my co-worker and I found that the belongs_to_association.rb and belongs_to_polymorphic_association.rb were still using the old finder methods in the "find_target" method.

我们通过记录来自不同查询的该方法的结果对象进行了几次测试,发现旧的查找器在随机时刻返回ActiveRecord :: Relation(加载相同的对象有时会返回该对象,而其他时候返回Relation对象).

We ran a couple tests by logging the resulting objects of this method from different queries and discovered the old finders were returning the ActiveRecord::Relation at random moments (loading the same object it would sometimes return the object and other times the Relation object).

我们在初始化器文件中覆盖了这两个类的find_target方法,将其中使用的查找器更改为新的rails3格式(klass.select(...).where(...)等).这似乎已经解决了问题.

We overrode the find_target method for these 2 classes in initializer files, changing the finders used there to the new rails3 format (klass.select(...).where(...), etc). This seems to have solved the issue.

"has_many"关联文件已经在使用新格式,因此它们没有引起任何问题.

The "has_many" association files are already using the new format, so these haven't caused any issues.

我们将这些修补程序"应用到了rails 3.0.3,希望它们在将来的版本中得到解决.

We applied these "fixes" to the rails 3.0.3 and hope that they will be resolved in future releases.

这是我们的初始化文件,以防其他人遇到此问题: belongs_to_polymorphic_association.rb:

Here are our initializer files in case someone else bumps into this problem: belongs_to_polymorphic_association.rb:

#initializers/belongs_to_polymorphic_association.rb
module ActiveRecord
  # = Active Record Belongs To Polymorphic Association
  module Associations
    class BelongsToPolymorphicAssociation < AssociationProxy #:nodoc:
      private
        def find_target
          return nil if association_class.nil?

          target =
            if @reflection.options[:conditions]
              association_class.select(@reflection.options[:select]).where(conditions).where(:id => @owner[@reflection.primary_key_name]).includes(@reflection.options[:include]).first
            else
              association_class.select(@reflection.options[:select]).where(:id => @owner[@reflection.primary_key_name]).includes(@reflection.options[:include]).first
            end
          set_inverse_instance(target, @owner)

          target
        end      
    end
  end
end

belongs_to_association.rb:

#initializers/belongs_to_association.rb
module ActiveRecord
  # = Active Record Belongs To Associations
  module Associations
    class BelongsToAssociation < AssociationProxy #:nodoc:

      private
        def find_target
          key_column = (@reflection.options[:primary_key]) ? @reflection.options[:primary_key].to_sym : :id

          options = @reflection.options.dup
          (options.keys - [:select, :include, :readonly]).each do |key|
            options.delete key
          end
          options[:conditions] = conditions

          the_target= @reflection.klass.select(options[:select]).where(key_column => @owner[@reflection.primary_key_name]).where(options[:conditions]).includes(options[:include]).readonly(options[:readonly]).order(options[:order]).first if @owner[@reflection.primary_key_name]
          set_inverse_instance(the_target, @owner)
          the_target
        end

    end
  end
end

希望这对某些人很有用

这篇关于Rails 3 ActiveRecord :: Relation随机关联行为的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆