Hakanai
Hakanai

Reputation: 12670

Does find(:all) on a has_many :through simply not work?

I have some model classes like this:

class Organisation < ActiveRecord::Base
  has_many :dongles
  has_many :licences_on_owned_dongles, :through => :dongles, :source => :licences,
           :include => [:organisation, :user, :owner_organisation, :profile, :dongle,
                        {:nested_licences => [:profile]} ]
end

class Dongle < ActiveRecord::Base
  has_many :licences
  belongs_to :organisation
end

class Licence < ActiveRecord::Base
  belongs_to :dongle

  # tree-like structure. I don't remember why this had to be done but the comment says
  # "find a way to make the simpler way work again" and I tried using the simpler way
  # but tests still fail. So obviously the SQL awfulness is necessary...
  default_scope :conditions => { :parent_licence_id, nil }
  has_many :nested_licences, :class_name => 'Licence', :dependent => :destroy,
           :autosave => true,
           :foreign_key => :parent_licence_id,
           :finder_sql => proc {
             "SELECT l.* FROM licences l WHERE l.parent_licence_id = #{id}" },
          :counter_sql => proc {
             "SELECT COUNT(*) FROM licences l WHERE l.parent_licence_id = #{id}" }
end

Now I can do this:

test "getting licences on owned dongles" do
  org = organisations(:some_other_corp)
  assert_equal [licences(:licence_4)], org.licences_on_owned_dongles
end

That happily passes. Since it's an association, you might thing you can find() on it:

test "getting licences on owned dongles and then filtering further" do
  org = organisations(:some_other_corp)
  conditions = { :owner_organisation_id => nil }
  assert_equal [licences(:licence_4)],
    org.licences_on_owned_dongles.find(:all, :conditions => conditions)
end

But this gives:

ActiveRecord::StatementInvalid: SQLite3::SQLException: no such column: dongles.organisation_id: SELECT "licences".* FROM "licences" WHERE "licences"."parent_licence_id" IS NULL AND (("dongles".organisation_id = 72179513)) AND ("licences".parent_licence_id = 747059259)
test/unit/organisation_test.rb:123:in `test_getting_licences_on_owned_dongles_and_then_filtering_further'

In fact, this even occurs when all you call is find(:all). It isn't just SQLite either, because I noticed this in production (oops) on MySQL.

So I don't know. It's really too mysterious to investigate further. I might shelve it as a "Rails just can't do find() on an association", use a block to filter it and leave it at that. But I wanted to put it out, just in case there is a better option.

(Actually if you look at the query Rails is generating, it is complete nonsense. Somehow it has ended up generating a query where something has to be NULL and equal to a value at the same time. Even if the query worked, this will return 0 rows.)

Upvotes: 0

Views: 140

Answers (2)

Zach Kemp
Zach Kemp

Reputation: 11904

I think you're looking for .where:

org.licenses_on_owned_dongles.where(conditions)

Upvotes: 0

charredUtensil
charredUtensil

Reputation: 152

Don't use find in a Rails 3 app.

org.licences_on_owned_dongles.find(:all, :conditions => conditions)

should be

org.licences_on_owned_dongles.where(conditions)

Edit: Read up on it here.

Upvotes: 1

Related Questions