Skip to content

Where(Hash) followed by Scoped Where(Hash) in ActiveRecord #3052

Closed
christianblais opened this Issue Sep 16, 2011 · 10 comments

6 participants

@christianblais

Quoted from Stackoverflow : http://goo.gl/o4y3w

class Project < ActiveRecord::Base
  scope :with_status, where(:status => 'test1')
  scope :with_status, where('status = ?', 'test2')
end

[ok]
Project.where(:status => 'test1').where(:status => 'test2')
  Project Load (0.4ms)  SELECT "projects".* FROM "projects" WHERE "projects"."status" = 'test1' AND "projects"."status" = 'test2'

[ok]
Project.where(:status => 'test1').with_status_2
  Project Load (0.5ms)  SELECT "projects".* FROM "projects" WHERE "projects"."status" = 'test1' AND "projects"."status" = 'test2'

[ok]
Project.with_status_1.where(:status => 'test2')
  Project Load (0.4ms)  SELECT "projects".* FROM "projects" WHERE "projects"."status" = 'test1' AND "projects"."status" = 'test2'

[not ok]
Project.where(:status => 'test2').with_status_1
  Project Load (0.5ms)  SELECT "projects".* FROM "projects" WHERE "projects"."status" = 'test1'

All results should be the same, but the last one is not. The scope erases the preceding condition when the where clause is a Hash, but works fine with a String.

@isaacsanders

@christianblais Is this still an issue?

@frodsan
frodsan commented Apr 30, 2012

@isaacsanders Running with master:

> Project.where(:status => 'test1').where(:status => 'test2')
  SELECT "projects".* FROM "projects" WHERE "projects"."status" = 'test1' AND "projects"."status" = 'test2'

> Project.where(:status => 'test1').with_status_2
  SELECT "projects".* FROM "projects" WHERE "projects"."status" = 'test1' AND (status = 'test2')

> Project.with_status_1.where(:status => 'test2')
  SELECT "projects".* FROM "projects" WHERE "projects"."status" = 'test1' AND "projects"."status" = 'test2'

> Project.where(:status => 'test2').with_status_1
  SELECT "projects".* FROM "projects" WHERE "projects"."status" = 'test1'

Apparently is still

@isaacsanders

That is odd. cc/ @tenderlove @josevalim

@the8472
the8472 commented Jul 2, 2012

I have run into this issue too, but it might actually be caused by activerecord-hackery/squeel#146 in my case.

@the8472 the8472 referenced this issue in activerecord-hackery/squeel Jul 2, 2012
Closed

relation.merge removes conditions in 1.0.6 #146

@the8472
the8472 commented Jul 2, 2012

Ok, now i have tried this without squeel and it's still happening, this seems to be intentional behavior according to https://github.com/rails/rails/blob/64872d1e34d929ee30041b37900591aade2a5eaf/activerecord/lib/active_record/relation/merger.rb#L101

Silently throwing away conditions on .merge but ANDing them when chaining the wheres directly seems to be a violation of the principle of least astonishment to me.

What's the reasoning behind this?

@the8472
the8472 commented Jul 2, 2012

In fact, this seems to be a direct violation of a scope's contract

According to the docs:

A scope represents a narrowing of a database query

Discarding where-conditions means that the resulting data set is not a strict subset of the set that the scope is applied to.

@the8472
the8472 commented Jul 2, 2012

related issue: #6596

@senny
Ruby on Rails member
senny commented Oct 12, 2012

I think the problem is the ActiveRecord::Relation::Merger#merged_wheres. It is applied when using scopes and it won't be applied when using where calls. The merger will filter duplicated == conditions on the same field.

The code in question originates from this PR #7392 there is also a discussion why the scope functionality behaves the way it does.

@rafaelfranca @steveklabnik thoughts? I think this is the exact same issue as #7365

@senny
Ruby on Rails member
senny commented Mar 12, 2013

@neerajdotname @jonleighton did #9553 fix this issue as well?

@neerajdotname
Ruby on Rails member

@senny Yes this is duplicate of #9553 .

Please refer to http://edgeguides.rubyonrails.org/active_record_querying.html#merging-of-scopes to see the new behavior in Rails 4.

Please note that Rails 3-stable would continue to work the old way.

@senny senny closed this Mar 12, 2013
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.