This project is archived and is in readonly mode.
has_many :through associations may not respect default_scope :conditions
Reported by Khurram Virani | December 23rd, 2009 @ 07:28 PM
class Book < ActiveRecord::Base
has_many :chapters, :as => :content, :dependent => :destroy
has_many :paragraphs, :through => :chapters
end
class Chapter < ActiveRecord::Base
belongs_to :content, :polymorphic => true
has_many :paragraphs
end
class Paragraph < ActiveRecord::Base
default_scope :conditions => { :deleted_at => nil } # changing this to :conditions => ["paragraphs.deleted_at IS NULL"]
belongs_to :chapter
end
Book.paragraphs.all # => ignores conditions and returns records with that have deleted_at set (not null)!
I kept the polymorphism in here because my production code has it. Not sure if it is related to the bug at all...I think it's happening because of using the conditions hash - the table name is being inferred incorrectly ... or something... going to investigate more shortly.
Looks like is_paranoid is resolving this by hacking the has_many method (but in a tightly coupled way that isn't really correct): http://github.com/semanticart/is_paranoid/commit/fae6f0d3b056f7ba29...
Comments and changes to this ticket
-
Khurram Virani December 23rd, 2009 @ 07:29 PM
comment should read:
changing this to :conditions => ["paragraphs.deleted_at IS NULL"] may fix the issue
-
Mateo Murphy August 3rd, 2010 @ 03:57 AM
Just ran into this issue using while using the "paranoid" gem. I don't think it's related to the conditions hash, since the paranoid gem uses the string syntax and still has the issue.
I'll look into it some more later this week...
-
Neeraj Singh August 3rd, 2010 @ 10:06 AM
- Importance changed from to Low
I am not able to reproduce this with rails edge.
ActiveRecord::Schema.define(:version => 20100803085555) do create_table "brakes", :force => true do |t| t.string "name" t.integer "car_id" end create_table "cars", :force => true do |t| t.string "name" end end class Brake < ActiveRecord::Base default_scope :conditions => { :name => 'hello' } belongs_to :car end class Car < ActiveRecord::Base has_many :brakes end
> Car.first.brakes Car Load (0.2ms) SELECT "cars".* FROM "cars" LIMIT 1 Brake Load (0.2ms) SELECT "brakes"."id", "brakes"."name", "brakes"."car_id" FROM "brakes" WHERE ("brakes"."name" = 'hello') AND ("brakes".car_id = 1)
-
Mateo Murphy August 3rd, 2010 @ 03:52 PM
Note that the issue is with has_many :through, not regular has many. However I haven't been able to reproduce the problem in a simple test, so there may be something else in my app (another gem maybe) that's causing it.
-
Neeraj Singh August 3rd, 2010 @ 04:01 PM
- State changed from new to invalid
This is with has many through.
ree-1.8.7-2010.01 > Person.first.posts Person Load (0.3ms) SELECT "people".* FROM "people" LIMIT 1 Post Load (0.2ms) SELECT "posts".* FROM "posts" INNER JOIN "readers" ON "posts".id = "readers".post_id WHERE ("posts"."name" = 'rails3') AND (("readers".person_id = 1)) class Post < ActiveRecord::Base has_many :readers has_many :people, :through => :readers default_scope :conditions => {:name => 'rails3'} end class Person < ActiveRecord::Base has_many :readers has_many :posts, :through => :readers end
Closing this ticket. If you are able to reproduce this case then please update this thread and the ticket will be alive again. Thanks.
-
Mateo Murphy August 3rd, 2010 @ 04:50 PM
The problem I was having was that I was expecting the
default_scope
of the join model to be applied, which does not happen: i.e.class Blog < ActiveRecord::Base has_many :posts has_many :users, :through => :posts end class Post < ActiveRecord::Base default_scope :conditions => 'published_at IS NOT NULL' belongs_to :blog belongs_to :user end class User < ActiveRecord::Base belongs_to :post end
> Blog.first.posts Blog Load (0.3ms) SELECT "blogs".* FROM "blogs" LIMIT 1 Post Load (0.2ms) SELECT "posts"."id", "posts"."name", "posts"."blog_id", "posts"."user_id", "posts"."published_at", "posts"."created_at", "posts"."updated_at" FROM "posts" WHERE (published_at IS NOT NULL) AND ("posts".blog_id = 1)
> Blog.first.users Blog Load (0.3ms) SELECT "blogs".* FROM "blogs" LIMIT 1 User Load (0.2ms) SELECT "users".* FROM "users" INNER JOIN "posts" ON "users".id = "posts".user_id WHERE (("posts".blog_id = 1))
In this case, I would have expected the default scope of posts to be respected, and only the users of published posts to be returned. I'm not certain if this should be considered a bug or not, though... thoughts?
-
Neeraj Singh August 3rd, 2010 @ 05:08 PM
Blog.first.users will not have the default_scope declared for Post. So technically this is not a bug :-)
-
Mateo Murphy August 3rd, 2010 @ 05:27 PM
No, technically it's not a bug. But intuitively it feels like one :) it may be a feature worth exploring
-
Jan Xie November 19th, 2010 @ 05:43 AM
What is a technically bug?
In my understand, "default" means all my arel queries respect the default_scope I set. But has_many through create a special case of default_scope now.
-
releod March 29th, 2011 @ 03:26 PM
I am also experiencing this issue. I feel it is a valid bug, as the results are not expected - clearly by the creation of this ticket.
-
jack dempsey (jackdempsey) March 30th, 2011 @ 08:18 PM
Just got surprised by this as well. Other threads around net have others agreeing. Anyone want to reopen this and solicit patches or a better reason to not do this?
-
Brian Underwood April 4th, 2011 @ 03:34 PM
I'm also having this issue. If you're defining as association with "through", the through model should be considered. Seems like a bug to me, or at least the way that it should work which may not have been previously considered. One of the things that I love about Ruby and Rails is that they work the way that you would expect them to ;)
Create your profile
Help contribute to this project by taking a few moments to create your personal profile. Create your profile »
<h2 style="font-size: 14px">Tickets have moved to Github</h2>
The new ticket tracker is available at <a href="https://github.com/rails/rails/issues">https://github.com/rails/rails/issues</a>