Reputation: 731
I have default_scope
on most of my models that scopes by current_user.company
. I'm using the client_side_validations gem on my sign up page which means there is no tenant set.
When the uniqueness validator runs on @user.email
the default_scope prevents the validation from running properly (because company_id
is nil) and therefore always looks like a unique result.
My user model:
# user.rb
...
default_scope { where(company_id: Company.current_id) }
...
This query is run when validating email:
Started GET "/validators/uniqueness?case_sensitive=true& \
user%5Bemail%5D=me%2B40%40example.com&_=1423897339854" \
for 76.175.168.2 at 2015-02-14 07:02:30 +0000
User Exists (0.4ms) SELECT 1 AS one FROM "users" WHERE \
"users"."company_id" IS NULL AND "users"."email" = '[email protected]' LIMIT 1
When I remove the default_scope
from my user model I get the correct result and proper validation:
Started GET "/validators/uniqueness?case_sensitive=true& \
user%5Bemail%5D=me%2B40%40example.com&_=1423897339854" \
for 76.175.168.2 at 2015-02-14 07:02:30 +0000
User Exists (0.4ms) SELECT 1 AS one FROM "users" WHERE \
"users"."email" = '[email protected]' LIMIT 1
What's the most practical way for me to override the default_scope
when this gem runs the email validator?
Upvotes: 0
Views: 236
Reputation: 731
I ended up money patching the gem within my app to fix my issue. I'll also submit the change to the gem author since I'm not sure if this is a bug or their original desired behaviour.
# lib/client_side_validations/active_record/middleware.rb
def self.is_unique?(klass, attribute, value, params)
...
!klass.where(relation).exists?
end
# patched the above line to: !klass.unscoped.where(relation).exists?
Upvotes: 0
Reputation: 201
Generally i would say: don't use default_scope cause you will run to all sorts of problems like this. Default scope is okay for ordering in my opinion.
But here you can solve it like this:
class User < ActiveRecord::Base
def self.default_scope
#i don't know what company represents here
where(company_id: Company.current_id) if Company.present?
end
end
You can define default scope as class method like you see above.
See doc: http://apidock.com/rails/ActiveRecord/Base/default_scope/class
Upvotes: 1
Reputation: 156
I don't think override the default_scope is a good idea.
You should move the logic to controller. I don't know if you are using pundit. It will provider a scope function.
If not, try to move this scope to controller.
def current_users
@users||= User.where(company_id: Company.current_id)
end
Upvotes: 0