Rails 3 ActiveRecord :: Отношение случайных ассоциаций поведения - PullRequest
0 голосов
/ 23 декабря 2010

У меня странная проблема с приложением, перенесенным с рельсов 2.3.8 на рельсы 3 (3.0.1, 3.0.2, 3.0.3).В случайные моменты ассоциации ведут себя странно.В некоторых случаях связанный объект будет возвращать объект Relation вместо соответствующей модели.Похоже, это происходит в основном при полиморфных ассоциациях.Например:

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

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

Когда вы вызываете «ab», это «иногда» возвращает объект Relation (вызывая «неопределенный метод ... для вызова ошибки ActiveRecord :: Relation») и некоторые другие моменты временивернет правильный объект B.Когда объект отношения возвращается, он может иногда быть временно "исправлен" путем перезапуска сервера, но в конечном итоге он снова появится.

Другая проблема, которую я получаю, заключается в том, что при "получении"связанные объекты, иногда необходимые фильтры не применяются автоматически (где элемент id = ...).это приводит к тому, что запрос возвращает первый объект в таблице, а не правильный связанный объект.

Это становится очень неприятной проблемой, тем более что я, похоже, не нахожу никого другого с этой или подобными проблемами.

Все методы поиска в приложении были перенесены в новую форму rails, но это странное поведение сохраняется.

Используемая текущая конфигурация: Ubuntu 10 nginx server passenger (3.0.2)рельсы (3.0.3) ruby ​​1.9.2p0 (редакция 2010-08-18 29036)

Ответы [ 2 ]

0 голосов
/ 26 декабря 2010

Спасибо, что поделились этим.Проблема с ассоциациями ушла.Но у меня все еще была эта проблема даже при прямом методе "find".

@post = Post.find(params[:id)
@post.update_attributes...

завершится с ошибкой ActiveRecord :: RelationОднако

@post = Post.find_by_id(params[:id])
@post.update_attributes...

будет работать

Похоже на странное ленивое поведение при загрузке

0 голосов
/ 24 декабря 2010

После более глубокого изучения кода Active Record мой коллега и я обнаружили, что own_to_association.rb и assign_to_polymorphic_association.rb все еще использовали старые методы поиска в методе "find_target".

Мы запустили пару тестов, зарегистрировав получившиеся объекты этого метода из разных запросов и обнаружили, что старые искатели возвращали ActiveRecord :: Relation в случайные моменты (при загрузке того же объекта иногда возвращался объект, а иногда - Relation объект).

Мы переопределили метод find_target для этих двух классов в файлах инициализатора, изменив используемые там искатели на новый формат rails3 (klass.select (...). Where (...) и т. Д.). Это, кажется, решило проблему.

Файлы ассоциации has_many уже используют новый формат, поэтому они не вызвали никаких проблем.

Мы применили эти «исправления» к рельсам 3.0.3 и надеемся, что они будут исправлены в будущих выпусках.

Вот наши файлы инициализатора на случай, если кто-то столкнется с этой проблемой: 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

Надеюсь, это кому-нибудь пригодится

...