2009-08-13 12 views
6

Ho un modello di account e un modello User:Convalida max importo af oggetti associati

class Account < ActiveRecord::Base 
    has_many :users 
end 

class User < ActiveRecord::Base 
    belongs_to :account 
end

utenti appartenere a un account e un account di avere un massimo utente (diverso per ogni account). Ma come convalidare che questo massimo non sia stato raggiunto quando si aggiungono nuovi utenti a un account?

Per prima cosa ho provato ad aggiungere una convalida sull'utente:

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

Ma questo funziona solo se io sono l'aggiunta di un utente alla volta.

Se aggiungo più utenti tramite @account.update_attributes(:users_attributes => ...), viene eseguito direttamente anche se c'è spazio per un altro utente.

Aggiornamento:

Giusto per chiarire: Il metodo di validazione in corso conferma che account.users.count è inferiore a account.maximum_amount_of_users. Quindi, dire per esempio che account.users.count è 9 e account.maximum_amount_of_users è 10, quindi la validazione passerà perché 9 < 10.

Il problema è che il conteggio tornato da account.users.count non aumenterà fino a quando tutti gli utenti sono stati scritti nel database. Ciò significa che l'aggiunta di più utenti allo stesso tempo passerà le convalide poiché il conteggio degli utenti sarà lo stesso fino a quando non saranno tutti convalidati.

Così come askegg punti, devo aggiungere la convalida anche al modello Conto? E come dovrebbe essere fatto?

risposta

16

Se si chiama account.users.size anziché account.users.count includerà anche utenti che sono stati creati ma non salvati nel database.

TUTTAVIA questo non risolverà completamente il problema. Quando si chiama account in un utente, non viene restituita la stessa istanza di account a cui punta @account in modo che non sappia dei nuovi utenti. Credo che questo sarà "risolto" in Rails 3, ma nel frattempo posso pensare a un paio di soluzioni.

Se si sta salvando l'account nello stesso momento in cui si aggiungono utenti (che presumo in modo tale da quando si chiama update_attributes), la convalida può andare lì.

# in account.rb 
def validate_max_users_have_not_been_reached 
    errors.add_to_base("You cannot have more than #{maximum_amount_of_users} users on this account.") unless users.size < maximum_amount_of_users 
end 

io non sono sicuro di come si sta salvando i modelli associati, ma se la convalida non riesce conto che non dovrebbero essere salvati.

L'altra soluzione è di reimpostare l'istanza user.account durante l'aggiornamento degli attributi utente. Potresti farlo nel metodo setter users_attributes.

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

questo modo conto dell'utente punterà alla stessa istanza conto così account.users.size dovrebbe restituire l'importo. In questo caso manterrai le convalide nel modello utente.

È un problema complicato, ma spero che questo vi abbia dato alcune idee su come risolverlo.

-2

Il motivo per cui sta passando è perché update_attributes non passa attraverso le convalide.

Inoltre, la logica controlla solo il numero di account esistente rispetto al massimo consentito. Non c'è alcun calcolo considerando il numero di utenti che cercano di essere aggiunti. Penserei che questa logica appartenga più al modello Account (?).

+0

update_attributes esegue convalide - almeno in Rails 2.3.2. Ma il problema è che il metodo di convalida sul modello Utente convalida che il numero massimo non viene raggiunto rispetto al numero di utenti già presenti nell'account. Cioè se max == 10 e users.count == 9, quindi - quando si aggiungono due utenti contemporaneamente - le convalide vengono eseguite per entrambe, ma ogni volta convalidando 9 <10. Poiché users.count non aumenterà prima del gli utenti sono scritti nel database. Ma come si potrebbe verificarlo sul modello Conto? Devo sovrascrivere gli update_attributes ecc.? –

+1

Ahh - mi scusi. Update_attribute (notare la "s" mancante alla fine) ignora le convalide. Errore mio. Sembra che Ryan (che ha molto più Rubyfoo di me) abbia risposto alla tua domanda. Non sapevo che il metodo "size" includesse record non salvati. Impari qualcosa ogni giorno :) – askegg

Problemi correlati