Rails 3 ActiveRecord:: Отношение случайных ассоциаций поведения
В настоящее время у меня странная проблема с приложением, перенесенным с рельсов 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) rails (3.0.3) ruby 1.9.2p0 (2010-08-18 revision 29036)
2 ответа
После более глубокого изучения кода 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 и надеемся, что они будут исправлены в будущих выпусках.
Вот наши файлы инициализатора на случай, если кто-то еще столкнется с этой проблемой: own_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
Надеюсь, что это полезно для кого-то
Спасибо, что поделились этим. Проблема с ассоциациями ушла. Но у меня все еще была эта проблема даже с прямым методом "найти".
@post = Post.find(params[:id)
@post.update_attributes...
потерпит неудачу с ошибкой ActiveRecord::Relation. тем не мение
@post = Post.find_by_id(params[:id])
@post.update_attributes...
буду работать
Похоже на странное ленивое поведение при загрузке