I'm using ruby '2.3.0'
and 'rails', '3.2.22.2'
.
I need a little help & explanations about a query I've made. Here's my models:
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
I want to retrieve all the assessment_raws, and eager load the associated sessions and mailing_schedulers.
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]
Of course to get the count of the mailing_schedulers, rails must query (N+1 problem)
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. I think I need a LEFT OUTER JOIN here because all assessment_raws doesn't have mailing_schedulers, right?
Any help appreciated.
This issue occurs due to a change made in Ruby 2.3 where Hash
now responds to to_proc
which confuses the interpolate
method. See this bug report for more details: https://github.com/rails/rails/issues/25010. Also note there is a workaround mentioned which resolved the issue for me, but unless you're sure you don't use the new to_proc
it could potentially be dangerous.
What worked for me: I added the suggested monkey patch (as shown below) to the top of my config/application.rb
class Hash
undef_method :to_proc if self.method_defined?(:to_proc)
end
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With