Модель приложений Rails 3, чтобы гарантировать, что только одно логическое поле устанавливается в true одновременно
У меня есть модель логотипа с полями name: string, default: boolean. Я хочу, чтобы истинное значение было уникальным, так что только один элемент в базе данных можно установить равным true сразу. Как установить обновление и новые действия в контроллере, чтобы все остальные значения моих логотипов были установлены на false?
Скажем, у меня есть следующая настройка
в моей базе данных
Логотип модели
имя: строка | default: boolean |
Item1 | true |
Пункт2 | false |
Item3 | false |
Если я изменил значение по умолчанию для Item2 на true, я хочу, чтобы он перебирал все логотипы и устанавливал остальные из них в false, поэтому только одно значение true одновременно, поэтому оно выглядит так.
name: string | default: boolean |
Item1 | false |
Пункт2 | true |
Item3 | false |
Спасибо за любую помощь заранее.
Ответы
Ответ 1
Этот код украден из предыдущего ответа и немного упрощен:
def falsify_all_others
Item.where('id != ?', self.id).update_all("default = 'false'")
end
Этот метод можно использовать в обратном вызове before_save в вашей модели.
На самом деле, лучше "фальсифицировать" только записи, значения которых "истинны", например:
Item.where('id != ? and default', self.id).update_all("default = 'false'")
UPDATE: чтобы сохранить код DRY, используйте self.class
вместо Item
:
self.class.where('id != ? and default', self.id).update_all("default = 'false'")
Ответ 2
Я думаю, хорошо проверить, сохранен ли тот, который вы сохраняете, прежде чем вы фальсифицируете других. В противном случае вы производите фальсификацию всех, когда вы сохраняете активную запись.
def falsify_all_others
if self.default
self.class.where('id != ? and default', self.id).update_all("default = 'false'")
end
end
Ответ 3
В вашем коде контроллера вы можете сделать что-то вроде этого.... обратите внимание, что вы, вероятно, принимаете Item2 в качестве параметра [...], чтобы вы могли изменить это ниже
@items_to_be_falsified = Item.where('id != ?', Item2.id)
@items_to_be_falsified.each do |item|
item.default = false
item.save
end
Обратите внимание, когда вы это сделаете, его хорошая практика, чтобы переместить это в модель, превратить ее в функцию и назвать ее как Item2.falsify_all_others
, как показано ниже
def falsify_all_others
Item.where('id != ?', self.id).each do |item|
item.default = false
item.save
end
end
Наслаждайтесь!
Ответ 4
Я также рекомендую фальсифицировать все ваши записи, а затем сделать их истинными.
add_column :users, :name ,:boolean, default: false
Ответ 5
Хорошо, есть еще несколько вещей, которые вам понадобятся.
Не используйте имя поля по умолчанию, оно обычно зарезервировано для базы данных.
Сохранение записи со значением по умолчанию как false приведет к тому, что все записи будут ложными, это не то, что вы хотите. проверьте, установили ли мы эту запись в true и falseify.
before_save :falsify_all_others
def falsify_all_others
if is_default
self.class.where('id != ?', self.id).where('is_default').update_all(:is_default => false)
end
end
Ответ 6
если вы хотите, чтобы это работало для создания и обновления (rails v4)
обратите внимание на этот лакомый кусочек из направляющих рельсов
after_save запускается как для создания, так и для обновления, но всегда после более конкретные обратные вызовы after_create и after_update, независимо от порядка в котором выполнялись вызовы макросов.