Rails validates_uniqueness_of игнорирует область
Я очень новичок в Rails и у меня проблемы с Rails/ActiveRecord, по-видимому игнорируя область видимости на validates_uniqueness_of
объявление в проекте, который я унаследовал. У меня есть следующая модель:
class User < ActiveRecord::Base
…
validates_uniqueness_of :email, scope: :brand_id, allow_nil: true
…
belongs_to :brand
…
end
Существует существующая запись пользователя с email
из foo@bar.com
и brand_id
из 1
,
При попытке обновить другую запись пользователя с id
из 123
, email
из foo@bar.com
и brand_id
из 2
Я получаю Validation failed: Email has already been taken
ошибка.
Я вижу, что следующие два запроса выполняются один за другим, когда возникает эта ошибка:
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;
Похоже, что второй запрос выполняет правильную проверку уникальности, но первый игнорирует область действия.
Буду признателен за любые советы о том, что посмотреть или как отлаживать дальше.
2 ответа
Это оказалось "проверяемым" поведением Devise, которое добавило свою собственную уникальную проверку поля электронной почты.
Нет ничего плохого в вашей логике в модели. Есть что-то еще, что останавливает запись, чтобы сохранить.
Вы можете поставить всю модель?
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 >