2016-07-20 13 views
0

Ich erstelle eine Rails-Migration für Provinzen und Länder. Die Idee ist, dass wir für jedes Land nicht mehr als eine Provinz mit dem gleichen Namen zulassen dürfen.
Meine create_provinces Migration ist:Eindeutigkeit mit has_many on Rails-Migration (ohne durch)

class CreateProvinces < ActiveRecord::Migration 
def change 
    create_table :provinces do |t| 
     t.string :name 
     t.references :country, index: true, foreign_key: true 
    end 
end 


Mein country.rb ist:

class Country < ActiveRecord::Base 
    has_many :provinces, :uniq => true 
end 

Mein province.rb ist:

class Province < ActiveRecord::Base 
    belongs_to :country 
    private 
    validates_presence_of :country 
    validate :canada_or_usa? 
    validates_presence_of :name 
    validate :in_right_country? 
    validates_associated :country 
    def canada_or_usa? 
    errors.add(:country, "can only add province for Canada or the United States") unless (country.name == "Canada" || country.name == "United States") 
    end 
    def in_right_country? 
    if country.name == "Canada" 
     errors.add(:name, "Name must be the name of a province in Canada") unless (DataHelper::canada_provinces_with_caption.include? name) 
    end 
    if country.name == "United States" 
     errors.add(:name, "Name must be the name of a province in the United States") unless (DataHelper::usa_provinces_with_caption.include? name) 
    end 
    end 
end 

Mit :uniq => true in country.rb, ich bin Den Fehler erhalten, der besagt: uniq ist kein bekannter Schlüssel. Beachten Sie, dass ich auch through nicht nach anderen Fragen verwende. Gibt es eine Möglichkeit sicherzustellen, dass jedes Land nicht zwei Provinzen mit demselben Namen haben kann?

Antwort

0

Zunächst einmal, dass :uniq => true nichts als eine Einzigartigkeit Ihrer Daten vortäuscht. Das fügt eine DISTINCT-Klausel in der Abfrage hinzu, wenn Provinzen von some_country_instance.provinces abgerufen werden. Damit können Sie zwei Provinzen mit demselben Namen für ein Land einfügen. Ich schlage vor, dass Sie das entfernen. Sie wollen nicht ausgetrickst werden.

Was Sie eigentlich tun sollten, ist die Paare [country_id, provincent_name] Spalten als Primärschlüssel Ihrer Tabelle Provinzen hinzuzufügen.

Sie, dass mit diesem Code mit Migrations erreichen:

... 
def change 
    add_index :provinces, [:country_id, :name], unique: true 
end 
... 

ich Ihren Tisch unter der Annahme provinces hat country_id als Fremdschlüsselspalte countries und name Spalte Halte Namen Provinzen.

Um Daten in dem Modell zu validieren Ich schlage vor:

... 
validates :name, uniqueness: { scope: :country_id, 
      message: "My world my rules. Country cannot have provinces with same name." } 
... 

Damit Sie elegant Ihren Job mit wenigen Zeilen Code erreichen und alle Vorteile des Rails-Frameworks nehmen.

0

In Ihrem Provinz Modell benötigen Sie

validates uniqueness: { scope: :country } 

Diese Sie Provinzen mit dem gleichen Namen haben können hinzufügen, aber nicht innerhalb eines einzigen Landes.

0

korrekte Syntax würde

has_many :provinces, -> { uniq } 

sein aber das ist nur eine Assoziation ist die Definition und nicht tatsächlich die Eingabe in der Datenbank zu validieren. und wenn Sie auf sql schauen, werden Sie etwas wie sehen.

Select distinct provinces from provinces where provinces.country_id = '';