2016-05-20 25 views
1

Ich habe das folgende Setup, das funktioniert gut ohne Validierung, aber ich möchte eine schreiben, um sicherzustellen, dass ein Benutzer immer mit dem Produkt verbunden ist.rails4 benutzerdefinierte Validierung funktioniert nicht

Also ohne Validierung ist alles in Ordnung. Wenn ich meine Produktform (für Rest der Daten) fülle und diese Linie @product.product_users.build(user_id: current_user.id, role: "owner") in die Steuerung einfüge, dann wird sowohl die Product mit ihrer AttrS und die ProductUser mit user_id: current_user.id und role: "owner" gespeichert. Wenn ich jedoch die folgende Validierung hinzufüge, wird das Produkt nicht erstellt, und es besagt, dass die Validierung nicht bestanden wird. ("Es ist kein Benutzer verbunden")!

def product_users_limit(min: 1) 
    if product_users.count < min 
    errors.add :base, "There is no user associated!" 
    end 
end 

Was ist falsch an dieser Validierung?

Modelle

User has_many :products, through: :product_users 
User has_many :product_users 
Product has_many :users, through: :product_users 
Product has_many :product_users 
ProductUser belongs_to :user 
ProductUser belongs_to :product 

product_users Tisch

create_table "product_users", force: :cascade do |t| 
    t.integer "user_id", null: false 
    t.integer "product_id", null: false 
    t.string "role",  null: false 
end 

Produkte Controller

def create 
    @product = Product.new(product_params) 
    @product.product_users.build(user_id: current_user.id, role: "owner") 
    authorize @product 
    if @product.save 
    ........ 

UPDATE

Die folgende Validierung mit Zahl arbeitet. Die Branchen müssen im Formular über Auswählen ausgewählt werden. Das Produkt < -> Industrie-Setup ist das gleiche wie Produkt < -> Benutzer. Der einzige Unterschied, dass diese im Formular eingereicht werden.

def product_industries_limit(max: 5, min: 1) 
    if industries.reject(&:marked_for_destruction?).count > max 
    errors.add :base, "You can't choose more than #{pluralize(max, 'industry')}." 
    elsif industries.reject(&:marked_for_destruction?).count < min 
    errors.add :base, "You have to choose at least #{pluralize(min, 'industry')}." 
    end 
end 

Antwort

4

In diesem Stadium Ihre product_users.count Rufauslösers eine Datenbankabfrage und die zugehörigen Datensätze sind nicht noch erstellt. Verwenden Sie stattdessen size.

Relevant: ActiveRecord: size vs count

+0

Fred, es funktioniert, aber es ist super seltsam. Ich benutze für den Rest der Validierungen, die funktionieren (Frage aktualisiert). Der einzige Unterschied besteht darin, dass diese über das Formular übermittelt werden. Warum ist das so? –

+0

Ihr Aufruf zum Zurückweisen konvertiert die Zuordnung in ein Array. Und so ist die Zählmethode diejenige von Array. Also passiert alles in Erinnerung ;-) – Fred

+0

Fred, könntest du mir neben dem vorherigen noch ein paar zusätzliche Ressourcen empfehlen? Ich meine nicht nur den Unterschied zwischen Anzahl gegen Größe und Länge, sondern wann sollte ich welche verwenden und warum? Ich habe schon ein bisschen darüber gelesen, aber es geht immer um Geschwindigkeit. Zum Beispiel hatte ich keine Ahnung, dass es für Validierungen wichtig sein könnte. –

Verwandte Themen