Lighthouse has a new layout. Prefer the old one? Return to the old layout, and switch back any time from the link at the top of each page.

This project is archived and is in readonly mode.

has_many through belongs_to association bug

#4887

I am finding the bug in has_many through belongs_to association:

class Post < AR::Base
  belongs_to :author
  has_many :favorites, :through => :author
end

Let's say that our app allows anonymous posts. In this case author_favorites association should return empty array for anonymous posts:

post = Post.create!(:title => 'title', :body => 'body')
assert_equal post.favorites.size, 0

Second line throws an exception:

ActiveRecord::StatementInvalid: PGError: ERROR:  syntax error at or near ")"
LINE 1: ...ites".author_id = "authors".id WHERE     (("authors".id = ))
                                                                     ^
: SELECT     COUNT(*) AS count_id FROM       "author_favorites" INNER JOIN "authors" ON "author_favorites".author_id = "authors".id WHERE     (("authors".id = ))
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/connection_adapters/abstract_adapter.rb:210:in `log'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:464:in `execute_without_query_record'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/test/cases/helper.rb:40:in `execute'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:954:in `select_raw'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/connection_adapters/postgresql_adapter.rb:941:in `select'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:7:in `select_all'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/connection_adapters/abstract/query_cache.rb:56:in `select_all'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:13:in `select_one'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/connection_adapters/abstract/database_statements.rb:19:in `select_value'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/relation/calculations.rb:174:in `execute_simple_calculation'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/relation/calculations.rb:161:in `perform_calculation'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/relation/calculations.rb:128:in `calculate'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/relation/calculations.rb:45:in `count'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/base.rb:406:in `__send__'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/base.rb:406:in `count'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/associations/association_collection.rb:195:in `count'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/base.rb:1167:in `with_scope'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/associations/association_collection.rb:195:in `send'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/associations/association_collection.rb:195:in `count'
    /home/bogdan/makabu/opensource/ruby/rails/activerecord/lib/active_record/associations/has_many_through_association.rb:32:in `size'
    ./test/cases/associations/has_many_through_associations_test.rb:368:in `test_has_many_association_through_a_belongs_to_association_if_belongs_to_is_nil'
    /home/bogdan/makabu/opensource/ruby/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb:67:in `__send__'
    /home/bogdan/makabu/opensource/ruby/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb:67:in `run'
    /home/bogdan/makabu/opensource/ruby/rails/activesupport/lib/active_support/callbacks.rb:417:in `_run_setup_callbacks'
    /home/bogdan/makabu/opensource/ruby/rails/activesupport/lib/active_support/testing/setup_and_teardown.rb:65:in `run'

It tries to build a join through unexisted relation.

Thanks,
Bogdan.

Reported by Bogdan Gusiev · June 17th, 2010 @ 11:36 AM

State: resolved
Milestone: 2.3.10
Assigned to: Ryan Bigg Ryan Bigg
Importance: Low

Activity

  1. Bogdan Gusiev
    Bogdan Gusiev
    • Tag changed from activerecord associations, activerecord to activerecord associations, activerecord, patch

    Here is my patch. Hopefully won't cause any side effects.

    June 17th, 2010 @ 11:42 AM

  2. DHH
    DHH
    • Assigned user set to Pratik

    June 17th, 2010 @ 03:42 PM

  3. Andrew White
    Andrew White
    • Assigned user changed from Pratik to Andrew White
    • State changed from new to open
    • Milestone cleared.
    • Importance changed from to High

    Someone else has reported this on #4977 Calling 'size' on an 'has_many :through' association errors. Definitely need to fix this before final release. Should return an empty array if the belongs_to association is nil.

    June 26th, 2010 @ 01:47 PM

  4. Bogdan Gusiev
    Bogdan Gusiev

    Hey Andrew,

    Thanks for taking care about this.

    I have fixed the bug by redefining costruct_scope method and return "empty" scope in case of nil association.
    {:find => {:conditions => "1!=1"}} seems the only one way of creating an always empty scope that works on MySQL, sqlite and postgres.

    Here is my updated patch where tests are in the right place.

    Thanks,
    Bogdan.

    June 26th, 2010 @ 07:29 PM

  5. Andrew White
    Andrew White
    • State changed from open to needs-more-info
    • Importance changed from High to Low

    I can't reproduce this - can you post a sample application where this fails? I added the test case from your first patch and it passed. Funny thing is there seems to be a test already there for it anyway:

    http://github.com/rails/rails/commit/95e1cf4812d4b964d7ab0fdf4bfa31...

    August 23rd, 2010 @ 01:21 PM

  6. Jeremy Kemper
  7. Bogdan Gusiev
    Bogdan Gusiev

    Hi Andrew,

    That bug is truly fixed.
    Seems there was more general change that fixed this bug in recent patches.

    I can´t reproduce it in Rails 3.0 but it is in 2.3.5.
    So, you may close it at least for v3.0.

    Thanks,
    Bogdan.

    August 31st, 2010 @ 07:14 PM

  8. Andrew White
    Andrew White
    • Milestone set to 2.3.10
    • State changed from needs-more-info to open

    August 31st, 2010 @ 10:21 PM

  9. Rohit Arondekar
    Rohit Arondekar
    • Tag changed from activerecord associations, activerecord, patch to activerecord, associations, patch

    October 7th, 2010 @ 05:21 AM

  10. Jon Leighton
    Jon Leighton
    • Assigned user changed from Andrew White to Ryan Bigg

    Reporter has indicated that this is no longer an issue in Rails 3, which is the current stable, so can this be closed please?

    December 12th, 2010 @ 11:26 AM

  11. Jon Leighton
    Jon Leighton
    • State changed from open to resolved

    December 20th, 2010 @ 08:13 PM