2009-08-13 8 views
6

Ich habe ein Modell Konto und ein User-Modell:Validate max Menge af zugehörige Objekte

class Account < ActiveRecord::Base 
    has_many :users 
end 

class User < ActiveRecord::Base 
    belongs_to :account 
end

Benutzer gehören zu einem Konto und ein Konto hat einen Anwender ein Maximum (unterschiedlich für jedes Konto). Aber wie kann ich bestätigen, dass dieses Maximum beim Hinzufügen neuer Benutzer zu einem Konto nicht erreicht wurde?

Zuerst habe ich versucht, eine Validierung auf dem Benutzer hinzufügen:

class User < ActiveRecord::Base 
    belongs_to :account 
    validate :validate_max_users_have_not_been_reached 

    def validate_max_users_have_not_been_reached 
    return unless account_id_changed? # nothing to validate 
    errors.add_to_base("can not be added to this account since its user maximum have been reached") unless account.users.count < account.maximum_amount_of_users 
    end 
end

Das funktioniert aber nur, wenn ich hinzufüge, einen Benutzer zu einer Zeit.

Wenn ich mehrere Benutzer über @account.update_attributes(:users_attributes => ...) hinzufügen, geht es direkt durch, auch wenn nur Platz für einen weiteren Benutzer vorhanden ist.

Update:

Nur um zu klären: Die aktuelle Validierungsmethode bestätigt, dass account.users.count als account.maximum_amount_of_users weniger ist. So Beispiel sagen für das account.users.count 9 und account.maximum_amount_of_users 10 ist, dann wird die Validierung übergeben, da 9 < 10.

Das Problem ist, dass die Zählung von account.users.count zurückgegeben wird nicht erhöht, bis alle Benutzer in die Datenbank geschrieben wurden. Das bedeutet, dass das gleichzeitige Hinzufügen mehrerer Benutzer Validierungen bestehen kann, da die Anzahl der Benutzer gleich bleibt, bis sie alle validiert sind.

So wie askegg weist darauf hin, sollte ich auch die Validierung zum Account-Modell hinzufügen? Und wie soll das gemacht werden?

Antwort

16

Wenn Sie account.users.size anstelle von account.users.count aufrufen, enthält es auch Benutzer, die erstellt, aber nicht in der Datenbank gespeichert wurden.

JEDOCH das wird Ihr Problem nicht vollständig lösen. Wenn Sie account in einem Benutzer aufrufen, gibt es nicht dieselbe Kontoinstanz zurück, auf die @account verweist, sodass es über die neuen Benutzer nicht informiert wird. Ich glaube, dass dies in Rails 3 "behoben" wird, aber in der Zwischenzeit kann ich mir ein paar Lösungen vorstellen.

Wenn Sie das Konto die gleiche Zeit speichern, die Sie Benutzer hinzufügen (was ich nehme, da Sie update_attributes aufrufen) dann kann die Validierung dort gehen.

Ich bin mir nicht sicher, wie Sie die zugehörigen Modelle speichern, aber wenn die Kontoüberprüfung fehlschlägt, sollten sie nicht gespeichert werden.

Die andere Lösung besteht darin, die user.account -Instanz auf self zurückzusetzen, wenn Benutzerattribute aktualisiert werden. Sie können dies in der set-Methode users_attributes tun.

# in account.rb 
def users_attributes=(attributes) 
    #... 
    user.account = self 
    #... 
end 

Auf diese Weise Konto des Benutzers auf das gleiche Konto Instanz zeigen wird, so sollte account.users.size den Betrag zurück. In diesem Fall würden Sie die Validierungen im Benutzermodell beibehalten.

Es ist ein kniffliges Problem, aber hoffentlich gab es Ihnen einige Ideen, wie Sie es lösen können.

-2

Der Grund dafür ist, dass update_attributes keine Validierungen durchläuft.

Auch - Ihre Logik überprüft nur für die vorhandene Nummer des Kontos gegen ihre maximal zulässige. Es gibt keine Berechnung in Anbetracht der Anzahl der Benutzer, die versucht werden, hinzugefügt zu werden. Ich würde denken, dass diese Logik mehr in das Account-Modell (?) Gehört.

+0

update_attributes führt Validierungen durch - zumindest in Rails 2.3.2. Das Problem ist jedoch, dass die Validierungsmethode im Benutzermodell bestätigt, dass die maximale Anzahl nicht erreicht wird, verglichen mit der Anzahl der Benutzer, die bereits auf dem Konto sind. I.e. Wenn max == 10 und users.count == 9, dann werden - wenn zwei Benutzer gleichzeitig hinzugefügt werden - die Validierungen für beide ausgeführt, aber jedesmal wird diese 9 <10 überprüft. Da users.count wird nicht vor dem erhöht Benutzer werden in die Datenbank geschrieben. Aber wie würde man dies auf dem Account-Modell bestätigen? Sollte ich die update_attributes usw. überschreiben? –

+1

Ahh - Entschuldigung. Update_attribute (beachten Sie das fehlende "s" am Ende) umgeht Validierungen. Mein Fehler. Sieht aus wie Ryan (wer hat viel mehr Rubyfoo als ich) hat Ihre Frage beantwortet. Ich wusste nicht, dass die Methode "size" nicht gespeicherte Datensätze enthält. Du lernst jeden Tag etwas :) – askegg

Verwandte Themen