has_many :through and foo.bars.include?

hallo everybody,

i already googled the following problem, but there are so many
questions regarding "has_many :through", that i just couldn't find
what i was looking for. so, i'm really sorry if this has been asked
before. if so, just drop me the link.

i have a has_many :through relationship similar to the following
example:

class Group < ActiveRecord::Base
  has_many :group_memberships,
    :dependent => :destroy

  has_many :admins,
    :through => :group_memberships,
    :source => :user,
    :conditions => 'is_admin = true AND pending = false'
end

class GroupMembership < ActiveRecord::Base
  belongs_to :group
  belongs_to :user
end

class User < ActiveRecord::Base
  has_many :group_memberships

  has_many :administrations,
    :through => :group_memberships,
    :source => :group,
    :conditions => "is_admin = true AND pending = false "
end

this is working fine. i even started a new rails-project and tried it
there. no problem.

now in an existing project of mine i sometimes get the following:
g = Group.first
=> #<Group id: 1, created_at: "2009-10-28 11:42:36", updated_at:
"2009-10-28 11:42:36">

g.admins.include? User.first

ArgumentError: wrong number of arguments (1 for 0)
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/connection_adapters/mysql_adapter.rb:226:in `kind_of?'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/connection_adapters/mysql_adapter.rb:226:in `quote'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/base.rb:2392:in `quote_bound_value'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/base.rb:2352:in `replace_bind_variables'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/base.rb:2352:in `gsub'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/base.rb:2352:in `replace_bind_variables'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/base.rb:2320:in `sanitize_sql_hash_for_conditions'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/base.rb:2231:in `sanitize_sql'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/base.rb:2006:in `expand_id_conditions'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/base.rb:692:in `exists?'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/associations/association_collection.rb:380:in `send'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/associations/association_collection.rb:380:in
`method_missing_without_paginate'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/base.rb:2143:in `with_scope'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/associations/association_proxy.rb:206:in `send'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/associations/association_proxy.rb:206:in `with_scope'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/associations/association_collection.rb:376:in
`method_missing_without_paginate'
        from /home/n0ne/_files/work/beagile/code/comuungo/vendor/
plugins/will_paginate/lib/will_paginate/finder.rb:170:in
`method_missing'
        from /usr/lib64/ruby/gems/1.8/gems/activerecord-2.3.4/lib/
active_record/associations/association_collection.rb:336:in `include?'
        from (irb):3>>

however, when i reload that association before asking for admins it is
working:

g.admins

=> []

g.admins.include? User.last

=> false

same thing:
Group.first.admins.include? User.last
=> Exception (see above)
Group.first.admin_ids.include? User.last
=> false

I already checked will_paginate as it is mentioned in the trace. But
in my test-project i set up it is working perfectly with the above
code and will_paginate installed.

Has anyone ever seen a behaviuor like this? Any clues, hints or tipps?

hallo everybody,

has_many :admins,
:through => :group_memberships,
:source => :user,
:conditions => 'is_admin = true AND pending = false'

Try changing that to :conditions => ['is_admin = true AND pending =
false']

Fred

There's clearly some sort of collision going on between an attribute
method and the built-in definition of kind_of? - every Ruby object
defines the one-argument form, so the fact that it's finding a 0-
argument version is a sign.

Somewhat unrelated, but you may want to declare these kind of flag
associations using bind variables; it's not strictly necessary, but
it's good practice to ensure cross-DB compatibility. In other words,
use this:

:conditions => ["is_admin = ? AND pending = ?", true, false]

Otherwise, you may get weird errors when you switch your DB (to, for
example, an in-memory SQLite3 for test speed) and the new DB doesn't
escape booleans the same way.

--Matt Jones

thanks a lot for your replies!

i already changed my :conditions. but i have an additional question
about that: should i change :order-statements accordingly (to also
include the brackets)?

as for my original problem:
thanks matt! your post put me into a new direction. i really found an
old (obsolete) 'type_of'-attribute inside my user-model. your
explanation seems to have a point. i did not try it yet, but i'm
pretty sure that it would solve my problem.

thanks again.

thanks a lot for your replies!

i already changed my :conditions. but i have an additional question
about that: should i change :order-statements accordingly (to also
include the brackets)?

No. (and changing conditions isn't necessary - I just had a (probably
wrong) hunch about what might be wrong)). A dangerously named
attribute/method is far more likely

Fred

just tried it. removing the kind_of-attribute did the trick! THANKS!
that bug was really getting annoying.