A link
ha due components
: componenta_id
e componentb_id
. A tal fine, nel file Link
modello che ho:Come modellare questa convalida complessa per l'univocità nei campi combinati
belongs_to :componenta, class_name: "Component"
belongs_to :componentb, class_name: "Component"
validates :componenta_id, presence: true
validates :componentb_id, presence: true
validates :componenta_id, uniqueness: { scope: :componentb_id }
validates :componentb_id, uniqueness: { scope: :componenta_id }
E nel file di migrazione:
create_table :links do |t|
t.integer :componenta_id, null: false
t.integer :componentb_id, null: false
...
end
add_index :links, :componenta_id
add_index :links, :componentb_id
add_index :links, [:componenta_id, :componentb_id], unique: true
Domanda: Questa tutte le opere. Ora voglio che la combinazione di componanta
e componentb
sia unica, indipendentemente dal loro ordine. Quindi, indipendentemente da quale componente sia componenta
e quale sia componentb
(dopotutto è lo stesso link, un collegamento tra i due stessi componenti). Così i due record di seguito non dovrebbe essere consentito in quanto rappresentano lo stesso link e quindi non sono unici:
- componenta_id = 1; componentb_id = 2
- componenta_id = 2; componentb_id = 1
Come posso creare questa convalida di unicità? Ho una validazione del modello funzionante (vedi sotto) ma mi chiedo se e come dovrei aggiungere anche la validazione a livello di migrazione/db ...?
validazione del modello
ho convalida modello di lavoro con il codice qui sotto:
before_save :order_links
validates :componenta_id, uniqueness: { scope: :componentb_id }
private
def order_links
if componenta_id > componentb_id
compb = componentb_id
compa = componenta_id
self.componenta_id = compb
self.componentb_id = compa
end
end
Il seguente test conferma le opere di cui sopra:
1. test "combination of two links should be unique" do
2. assert @link1.valid?
3. assert @link2.valid?
4. @link1.componenta_id = 3 #@link2 already has combination 3-4
5. @link1.componentb_id = 4
6. assert_not @link1.valid?
7. @link1.componenta_id = 4
8. @link1.componentb_id = 3
9. assert_raises ActiveRecord::RecordNotUnique do
10. @link1.save
11. end
12.end
Migrazione/convalida db:
Come ulteriore livello di sicurezza, esiste anche un modo per incorporare la convalida a livello di db? In caso contrario, è ancora possibile scrivere entrambi i seguenti record nel database: componenta_id = 1 ; componentb_id = 2
e componenta_id = 2 ; componentb_id = 1
.
In [questa conversazione] (http://stackoverflow.com/questions/635937/how-do-i-specify-unique-constraint-for-multiple-columns-in-mysql) il suggerimento è di creare una relazione molti-a-molti: ' ha molti: componenti ' 'validates_length_of: components, maximum: 2' – skahlert