Question

In Rails 2.3, I have the following model:

class Foo
  named_scope :first_scope, lambda {
    record_ids = SomeModel.find(some_conditions).map(&:foreign_ids)

    { :conditions => {:field => record_ids} }
  }

  named_scope :second_scope, lambda {
    record_ids = SomeOtherModel.find(some_conditions).map(&:foreign_ids)

    { :conditions => {:field => record_ids } }
  }
end

I'd like to be able to call something like:

Foo.first_scope.second_scope.all

and have it execute SQL statement that looks like

SELECT *
FROM foo
WHERE
  field in (1, 2, 3) AND
  field in (2, 3, 4)

or even better, I'd want it to do the intersection and execute

SELECT *
FROM foo
WHERE
  field in (2, 3)

Instead, what actually executes is the SQL for whatever scope is last in the chain. In my example, it's

SELECT *
FROM foo
WHERE
  field in (2, 3, 4)

The first scope is simply never applied. I believe that's because the condition in the second scope is over-writing the condition in the first.

I can't just use :include or :join because Foo is backed by one database and SomeModel and SomeOtherModel are backed by a different database, so joins are impossible. I also want to use named_scopes (as opposed to executing one query and then selectively deleting or something like that) because of performance considerations.

Was it helpful?

Solution

I haven't done any Rails2 for a long time but I'd guess that something inside ActiveRecord is merging your Hash conditions so it ends up doing something like this:

h1 = {:field => [1,2,3]}
h2 = {:field => [2,3,4]}
conditions = h1.merge(h2)

and the result is that the first :field entry is overwritten by the second. If you use array conditions instead of Hashes:

{ :conditions => [ 'field in (?)', record_ids ] }

then I think the conditions will stack the way you expect them to. As I said, my Rails2 is rusty so I might not have the right syntax for the array condition.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top