With_scope issue

I have the following code:

class User < ActiveRecord::Base
has_many :requests do
def find_active(options = {})
with_scope :find => { :conditions => [“requests.active = ?”,
true] } do
find(:all, options)
end
end
end
end

Executing user.requests.find_active results in the following SQL:
SELECT * FROM requests WHERE (( requests.user_id = 10 ) AND
( requests.active = 1 )) AND (requests.user_id = 10) ORDER BY
requests.name

Note the extra (requests.user_id = 10).

Is this as expected? I can use with_exclusive_scope and that makes it
go away, but the doc makes me wonder if I may not get what I expect
since has_many is probably doing some kind of with_scope under the
covers.

I’m using Rails 1.2.5 and Ruby 1.8.6.

On 19 Oct 2007, at 00:21, gobigdave wrote:

end
end
end

Executing user.requests.find_active results in the following SQL:
SELECT * FROM requests WHERE (( requests.user_id = 10 ) AND
( requests.active = 1 )) AND (requests.user_id = 10) ORDER BY
requests.name

Would the find_active method not be better defined on the Request
class ?

Fred

I don’t think so because I’m looking for active requests of the user.
Sure, I could have a Request.find_active(user) method, but I decided
to make use of my has_many association. While it does bring a little
Request knowledge into User, I think user.requests.find_active is
cleaner and makes more sense than Request.find_active(user). To me,
that’s one of the beauties of has_many, has_one, etc.

Besides, that is not the original question. :slight_smile:

On Oct 19, 4:14 am, Frederick C. [email protected]

On 19 Oct 2007, at 12:44, gobigdave wrote:

I don’t think so because I’m looking for active requests of the user.
Sure, I could have a Request.find_active(user) method, but I decided
to make use of my has_many association. While it does bring a little
Request knowledge into User, I think user.requests.find_active is
cleaner and makes more sense than Request.find_active(user). To me,
that’s one of the beauties of has_many, has_one, etc.

you can make use of the has_many, since this sort of stuff works:

class Request < ActiveRecord::Base
def self.find_active
find :all, :condition => [“active = ?”, true]
end
end

And then user.requests.find_active finds active requests for that user.

Fred

Umm…looks like a bug to my eyes…does it happen in latest edge rails
as well ?

On 10/19/07, gobigdave [email protected] wrote:

end
Is this as expected? I can use with_exclusive_scope and that makes it
go away, but the doc makes me wonder if I may not get what I expect
since has_many is probably doing some kind of with_scope under the
covers.

I’m using Rails 1.2.5 and Ruby 1.8.6.


Cheers!

Haven’t tried edge rails yet, but I found another one that scares me.
I have a class that uses an after_create callback to build up several
associations. I’m finding that a simple Request.find call is
inheriting scope depending on how I create the object. It’s hard to
explain without see all the code, but here goes.

User has_many Requests. Requests will build up associations amongst
themselves by after_create calling search(). The search method in
Request is basically like:

def search
Request.find(…)
end

If I create a Request like this:

user.requests.create!()

Then calls in the Request.find() calls in Request get a (user_id = n)
added to their where clause. That should not happen.

If I call Request.search() directly or do user.requests <<
Request.new(), then the (user_id = n) is not added to the where
clause.

Sure feels like a nasty, subtle bug to me.

Is this the best place to let it be known?

I’m going back to 1.2.4.

Then calls in the Request.find() calls in Request get a (user_id = n)
added to their where clause. That should not happen.

This scoping is intentional although the consequences can be subtle.
It’s what makes user.requests.find_active work when you’ve only
defined Request.find_active

This is intentional? That surprises me because of all the subtle side-
effects. I mean how would I know what to do in Request.after_create
because the behavior is different based on how I was created
(user.requests.create() vs. user.requests << Request.new())? I’m of
the opinion that code (like a state machine) should not be dependent
on where you’re called from. It should only be dependent on the
arguments passed. I guess I need to go through all my code and make
sure I don’t have any other issues like this.

There still is the issue of doubling up of (user_id = 10) when using
with_scope.

On Oct 19, 10:50 am, Frederick C. [email protected]

I played with this some more, and I get the power of this for finders,
but create can cause some troubles. Knowing this, I moved all my
association extensions from User to Request, and that got rid of the
double (user_id = 10) and (user_id = 10). Although, I still think the
previous is a minor issue with with_scope.

I fixed my Request.find issue by adding with_exclusive_scope anywhere
where I really did want to search the entire requests table and not
inherit any scope.

If I create a Request like this:

user.requests.create!()

Then calls in the Request.find() calls in Request get a (user_id = n)
added to their where clause. That should not happen.

This scoping is intentional although the consequences can be subtle.
It’s what makes user.requests.find_active work when you’ve only
defined Request.find_active

If I call Request.search() directly or do user.requests <<
Request.new(), then the (user_id = n) is not added to the where
clause.

Sure feels like a nasty, subtle bug to me.

Is this the best place to let it be known?

dev.rubyonrails.org, the rails-core mailing lists or the rails-
contrib irc channgels are more suitable for discussing the
development of rails itself.

Fred

Yes, it does work, but in your example user.requests.find_active will
not cache. That was the main reason for me putting it in User. I
ended up with the best of both worlds using the scope_out plugin. Now
I have:

class Request
belongs_to :user
scope_out :active, :conditions => [“requests.active = ?”, true]
end
class User
has_many :requests, :extend => Request::AssociationMethods
end

Now, find_active, with_active, and calculate_active are available from
Request and user.requests, I get the caching I want, and it’s a whole
lot less code.

On Oct 19, 8:10 am, Frederick C. [email protected]