validations validates_uniqueness_of validates validate uniqueness rails multiple method custom columns ruby-on-rails validates-uniqueness-of

ruby on rails - validates_uniqueness_of - Los rieles validan la singularidad solo si son condicionales



rails validations (3)

Tengo una clase de preguntas:

class Question < ActiveRecord::Base attr_accessible :user_id, :created_on validates_uniqueness_of :created_on, :scope => :user_id end

Un usuario determinado solo puede crear una única pregunta por día, por lo que quiero forzar la unicidad en la base de datos a través de un índice único y la clase de Pregunta a través de validates_uniqueness_of.

El problema con el que me estoy topando es que solo quiero esa restricción para usuarios que no son administradores. Así que los administradores pueden crear tantas preguntas por día como quieran. ¿Alguna idea de cómo lograrlo con elegancia?


La única forma que conozco para garantizar la singularidad es a través de la base de datos (por ejemplo, un índice único). Todos los enfoques basados ​​en Rails solo involucran condiciones de carrera Dadas sus limitaciones, creo que lo más fácil sería establecer una columna separada e indexada de forma única que contenga una combinación del día y la identificación del usuario, que dejaría null para los administradores.

En cuanto a validates_uniqueness_of , puede restringir la validación a no administradores mediante el uso de una opción if o unless , como se explica en http://apidock.com/rails/ActiveRecord/Validations/ClassMethods/validates_uniqueness_of


Puede hacer que una validación sea condicional pasando una cadena simple de Ruby para ser ejecutada, un Proc o un nombre de método como un símbolo como un valor a :if o :unless en las opciones para su validación. Aquí hay unos ejemplos:

Antes de la versión 5.2 de Rails, podría pasar una cadena:

# using a string: validates :name, uniqueness: true, if: ''name.present?''

Desde 5.2 en adelante, las cadenas ya no son compatibles, dejándole las siguientes opciones:

# using a Proc: validates :email, presence: true, if: Proc.new { |user| user.approved? } # using a Lambda (a type of proc ... and a good replacement for deprecated strings): validates :email, presence: true, if: -> { name.present? } # using a symbol to call a method: validates :address, presence: true, if: :some_complex_condition def some_complex_condition true # do your checking and return true or false end

En tu caso, podrías hacer algo como esto:

class Question < ActiveRecord::Base attr_accessible :user_id, :created_on validates_uniqueness_of :created_on, :scope => :user_id, unless: Proc.new { |question| question.user.is_admin? } end

Eche un vistazo a la sección de validación condicional en las guías de rieles para obtener más detalles: http://edgeguides.rubyonrails.org/active_record_validations.html#conditional-validation


Solo agregue una condición a la llamada validates_uniqueness_of .

validates_uniqueness_of :created_on, scope: :user_id, unless: :has_posted? def has_posted exists.where(user_id: user_id).where("created_at >= ?", Time.zone.now.beginning_of_day) end

Pero aún mejor, solo crea una validación personalizada:

validate :has_not_posted def has_not_posted posted = exists.where(user: user).where("DATE(created_at) = DATE(?)", Time.now) errors.add(:base, "Error message") if posted end