Подтвердить что ты не робот

Модель приложений 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 |

Спасибо за любую помощь заранее.

4b9b3361

Ответ 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, независимо от порядка в котором выполнялись вызовы макросов.