6 votes

"TypeError : no implicit conversion of nil into String" lors du chargement rapide des résultats

J'utilise ruby '2.3.0' y 'rails', '3.2.22.2' .

J'ai besoin d'un peu d'aide et d'explications sur une requête que j'ai faite. Voici mes modèles :

class AssessmentRaw < ActiveRecord::Base
  belongs_to :session
  has_many :schedulers, :class_name => 'MailingScheduler', :as => :owner, :dependent => :destroy
end

class MailingScheduler < ActiveRecord::Base
  belongs_to :owner, :polymorphic => true
end

class Session < ActiveRecord::Base
  has_many :assessment_raws, :dependent => :destroy
end

Je veux récupérer tous les assessment_raws, et charger les sessions et les mailing_schedulers associés.

1. sessions à chargement rapide uniquement

ars = AssessmentRaw.includes(:session).where("sessions.start_at >= ?", 1.year.ago).limit(10)

ars.map { |ar| ar.session.id } => [2877, 2878, 2879, 2880, 2881, 2882, 2883, 2884, 2902, 2903]

`ars.map { |ar| ar.schedulers.try(:size) }`
   MailingScheduler Load (0.6ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 622 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
   MailingScheduler Load (0.6ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 725 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
   MailingScheduler Load (0.3ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 771 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
   MailingScheduler Load (0.3ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 782 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
   MailingScheduler Load (0.3ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 881 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
   MailingScheduler Load (0.2ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 996 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
   MailingScheduler Load (0.3ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 1087 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
   MailingScheduler Load (0.3ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 1155 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
   MailingScheduler Load (0.2ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 653 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
   MailingScheduler Load (0.2ms)  SELECT "mailing_schedulers".* FROM "mailing_schedulers" WHERE "mailing_schedulers"."owner_id" = 940 AND "mailing_schedulers"."owner_type" = 'AssessmentRaw'
 => [0, 0, 0, 0, 0, 0, 0, 0, 0, 0]

Bien sûr pour obtenir le nombre de mailing_schedulers, les rails doivent interroger (problème N+1)

2. sessions de chargement rapide et mailing_schedulers

ars = AssessmentRaw.includes(:schedulers,:session).where("sessions.start_at >= ?", 1.year.ago).limit(10)

TypeError: no implicit conversion of nil into String
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/arel-3.0.3/lib/arel.rb:40:in `initialize'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/arel-3.0.3/lib/arel.rb:40:in `new'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/arel-3.0.3/lib/arel.rb:40:in `sql'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/associations/join_helper.rb:47:in `block in sanitize'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/associations/join_helper.rb:45:in `map'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/associations/join_helper.rb:45:in `sanitize'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/associations/join_dependency/join_association.rb:104:in `block in join_to'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/associations/join_dependency/join_association.rb:74:in `each'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/associations/join_dependency/join_association.rb:74:in `each_with_index'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/associations/join_dependency/join_association.rb:74:in `join_to'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation/query_methods.rb:370:in `block in build_joins'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation/query_methods.rb:369:in `each'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation/query_methods.rb:369:in `build_joins'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation/query_methods.rb:266:in `build_arel'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation/query_methods.rb:260:in `arel'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation/finder_methods.rb:259:in `construct_limited_ids_condition'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation/finder_methods.rb:243:in `apply_join_dependency'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation/finder_methods.rb:232:in `construct_relation_for_association_find'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation/finder_methods.rb:211:in `find_with_associations'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation.rb:171:in `exec_queries'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation.rb:160:in `block in to_a'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/explain.rb:41:in `logging_query_plan'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation.rb:159:in `to_a'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/activerecord-3.2.22.2/lib/active_record/relation.rb:498:in `inspect'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/railties-3.2.22.2/lib/rails/commands/console.rb:47:in `start'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/railties-3.2.22.2/lib/rails/commands/console.rb:8:in `start'
  from /Users/oim/.rbenv/versions/2.3.0/gemsets/project-gems/gems/railties-3.2.22.2/lib/rails/commands.rb:41:in `<top (required)>'
  from script/rails:6:in `require'
  from script/rails:6:in `<main>'irb(main):064:0>

ouch. Je pense que j'ai besoin d'un LEFT OUTER JOIN ici parce que tous les assessment_raws n'ont pas de mailing_schedulers, non ?

Toute aide est appréciée.

4voto

neuronaut Points 2326

Ce problème est dû à une modification apportée dans Ruby 2.3 où Hash répond maintenant à to_proc qui confond le interpolate méthode. Voir ce rapport de bogue pour plus de détails : https://github.com/rails/rails/issues/25010 . Notez également qu'il y a une solution de contournement mentionnée qui a résolu le problème pour moi, mais à moins que vous ne soyez sûr de ne pas utiliser la nouvelle version de l to_proc ça peut être potentiellement dangereux.

Ce qui a marché pour moi : J'ai ajouté le patch suggéré pour le singe (comme indiqué ci-dessous) en haut de ma page d'accueil. config/application.rb

class Hash
  undef_method :to_proc if self.method_defined?(:to_proc)
end

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X