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:
- Escribe tu propio método de validación.
- 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]