0

I’m very new to Rails and am having trouble with Rails/ActiveRecord seemingly ignoring scope on a validates_uniqueness_of declaration in a project I’ve inherited. I have the following model:

class User < ActiveRecord::Base
  …
  validates_uniqueness_of :email, scope: :brand_id, allow_nil: true
  …
  belongs_to :brand
  …
end

There is an existing user record with an email of foo@bar.com and a brand_id of 1.

When trying to update another user record with an id of 123, email of foo@bar.com and a brand_id of 2, I get a Validation failed: Email has already been taken error.

I see the following two queries run one after the other when this error occurs:

SELECT  1 AS one FROM "users" WHERE ("users"."email" = 'foo@bar.com' AND "users"."id" != 123) LIMIT 1;
SELECT  1 AS one FROM "users" WHERE ("users"."email" = 'foo@bar.com' AND "users"."id" != 123 AND "users"."brand_id" = 2) LIMIT 1;

It looks like the second query is doing the correct uniqueness check, but the first one is ignoring the scope.

Any tips on what to look at or how to debug further would be appreciated.

Jaik Dean
  • 1,109
  • 2
  • 9
  • 13

2 Answers2

0

There's nothing wrong with your logic in the model. There's something else that's stopping the Record to save.

Can you put the whole model?

class Artwork < ApplicationRecord

  ...

  validates_uniqueness_of :artwork_file_name, scope: :game_id

  ...

end


2.3.1 :810 > Artwork.new(artwork_file_name: 'asd', game_id: 100).save
   (12.5ms)  BEGIN
  Artwork Exists (92.1ms)  SELECT  1 AS one FROM `artworks` WHERE `artworks`.`artwork_file_name` = BINARY 'asd' AND `artworks`.`game_id` = 100 LIMIT 1
  SQL (64.1ms)  INSERT INTO `artworks` (`game_id`, `artwork_file_name`, `created_at`, `updated_at`) VALUES (100, 'asd', '2017-02-17 10:25:25', '2017-02-17 10:25:25')
   (17.9ms)  COMMIT
 => true
2.3.1 :811 > Artwork.new(artwork_file_name: 'asd', game_id: 100).save
   (0.2ms)  BEGIN
  Artwork Exists (0.5ms)  SELECT  1 AS one FROM `artworks` WHERE `artworks`.`artwork_file_name` = BINARY 'asd' AND `artworks`.`game_id` = 100 LIMIT 1
   (6.1ms)  ROLLBACK
 => false
2.3.1 :812 > Artwork.new(artwork_file_name: 'asd', game_id: 101).save
   (0.2ms)  BEGIN
  Artwork Exists (45.4ms)  SELECT  1 AS one FROM `artworks` WHERE `artworks`.`artwork_file_name` = BINARY 'asd' AND `artworks`.`game_id` = 101 LIMIT 1
  SQL (6.7ms)  INSERT INTO `artworks` (`game_id`, `artwork_file_name`, `created_at`, `updated_at`) VALUES (101, 'asd', '2017-02-17 10:26:05', '2017-02-17 10:26:05')
   (6.3ms)  COMMIT
 => true
2.3.1 :813 >
Vlad
  • 902
  • 4
  • 14
0

It turned out to be Devise's "validatable" behaviour, which added it's own unique validation of the email field.

Jaik Dean
  • 1,109
  • 2
  • 9
  • 13