Skip to content
This repository

#exists? no longer takes default_scope into consideration #8795

Closed
dhh opened this Issue January 07, 2013 · 3 comments

2 participants

David Heinemeier Hansson Jon Leighton
David Heinemeier Hansson
Owner
dhh commented January 07, 2013

Models:

class Todolist < ActiveRecord::Base
  has_many :todos
end


class Todo < ActiveRecord::Base
  default_scope -> { where trashed: false }
  belongs_to :todolist
end

Queries:

irb(main):007:0> l.todos.exists?(completed: true)
  Todo Exists (0.1ms)  SELECT 1 AS one FROM "todos" WHERE "todos"."todolist_id" = ? AND "todos"."completed" = 't' LIMIT 1  [["todolist_id", 1]]
=> 1
irb(main):008:0> l.todos.where(completed: true).exists?
  Todo Exists (0.1ms)  SELECT 1 AS one FROM "todos" WHERE "todos"."trashed" = 'f' AND "todos"."todolist_id" = ? AND "todos"."completed" = 't' LIMIT 1  [["todolist_id", 1]]
=> nil

As you can see, the default scope is only being respected when using an explicit #where -- not when we just pass the options to #exists?.

David Heinemeier Hansson
Owner
dhh commented January 07, 2013

It appears that default_scope is also being ignored when you have has_many through associations. Example:

class Person < ActiveRecord::Base
  has_many :projects, through: :accesses
end

class Access < ActiveRecord::Base
  belongs_to :person
  belongs_to :project
end

class Project < ActiveRecord::Base
  default_scope -> { where trashed: false }
end

# Does not include the trashed: false condition
person.projects.to_sql
David Heinemeier Hansson
Owner
dhh commented January 07, 2013

(Note, this is a regression, not just a bug. I'm hitting this upgrading Basecamp from 3.2.9 to 4.0.0.beta).

Jon Leighton
Owner

Reproduced with the following

require "active_record"
require "logger"

ActiveRecord::Base.logger = Logger.new(STDERR)
ActiveRecord::Base.establish_connection adapter: 'sqlite3', database: ':memory:'

class Todolist < ActiveRecord::Base
  connection.create_table :todolists
  has_many :todos
end

class Todo < ActiveRecord::Base
  connection.create_table :todos do |t|
    t.integer :todolist_id
    t.boolean :trashed
    t.boolean :completed
  end

  default_scope -> { where trashed: false }
end

list = Todolist.create
list.todos.create trashed: true, completed: true

p list.todos.exists?(completed: true)
p list.todos.where(completed: true).exists?
Jon Leighton jonleighton closed this in 5f759ff January 18, 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.