validations validates validate uniqueness rails multiple greater_than custom columns ruby-on-rails validation model unique-constraint

ruby-on-rails - uniqueness - rails validates greater_than



¿Cómo se valida la unicidad de un par de identificadores en Ruby on Rails? (6)

Cuando está creando un nuevo registro, eso no funciona porque el id de su modelo principal aún no existe en el momento de las validaciones.

Esto debería funcionar para ti.

class B < ActiveRecord::Base has_many :ab has_many :a, :through => :ab end class AB < ActiveRecord::Base belongs_to :b belongs_to :a end class A < ActiveRecord::Base has_many :ab has_many :b, :through => :ab after_validation :validate_uniqueness_b private def validate_uniqueness_b b_ids = ab.map(&:b_id) unless b_ids.uniq.length.eql? b_ids.length errors.add(:db, message: "no repeat b''s") end end end

En el código anterior, obtengo todos b_id de la colección de parámetros, luego comparo si la longitud entre los valores únicos y b_id obtenidos son iguales.
Si son iguales significa que no se repite b_id .

Nota: no olvide agregar un único en las columnas de su base de datos .

Supongamos que la siguiente migración de base de datos en Ruby:

create_table :question_votes do |t| t.integer :user_id t.integer :question_id t.integer :vote t.timestamps end

Supongamos además que deseo que las filas en el DB contengan pares únicos (user_id, question_id). ¿Cuál es el polvo adecuado para poner en el modelo para lograr eso?

validates_uniqueness_of :user_id, :question_id parece simplemente hacer que las filas sean únicas por ID de usuario y únicas por ID de pregunta, en lugar de únicas por el par.


De RailsGuides . validates trabajos también:

class QuestionVote < ActiveRecord::Base validates :user_id, :uniqueness => { :scope => :question_id } end


Excepto por escribir su propio método de validación, lo mejor que puede hacer con validates_uniqueness_of es esto:

validates_uniqueness_of :user_id, :scope => "question_id"

Esto verificará que user_id sea único dentro de todas las filas con el mismo id_pregunta como el registro que está intentando insertar.

Pero eso no es lo que quieres .

Creo que está buscando la combinación de :user_id y :question_id para ser único en toda la base de datos.

En ese caso, debes hacer dos cosas:

  1. Escribe tu propio método de validación.
  2. Cree una restricción en la base de datos porque aún existe la posibilidad de que su aplicación procese dos registros al mismo tiempo.

La mejor forma es usar ambos, ya que los rieles no son 100% confiables cuando se realiza la validación de exclusividad.

Puedes usar:

validates :user_id, uniqueness: { scope: :question_id }

y para ser 100% seguro, agregue esta validación en su db (MySQL ex)

add_index :question_votes, [:user_id, :question_id], unique: true

y luego puedes manejar tu controlador usando:

rescue ActiveRecord::RecordNotUnique

Entonces ahora estás 100% seguro de que no tendrás un valor duplicado :)


Si usa mysql, puede hacerlo en la base de datos usando un índice único. Es algo como:

add_index :question_votes, [:question_id, :user_id], :unique => true

Esto generará una excepción cuando intente guardar una combinación duplicada de question_id / user_id, por lo que tendrá que experimentar y descubrir qué excepción capturar y manejar.


validates_uniqueness_of :user_id, :scope => [:question_id]

si necesita incluir otra columna (o más), puede agregar eso al alcance también. Ejemplo:

validates_uniqueness_of :user_id, :scope => [:question_id, :some_third_column]