2009-08-13 12 views
6

que tienen un modelo de cuenta y un modelo de usuario:Validar máxima cantidad af objetos asociados

class Account < ActiveRecord::Base 
    has_many :users 
end 

class User < ActiveRecord::Base 
    belongs_to :account 
end

los usuarios pertenecen a una cuenta y una cuenta de usuario tiene un máximo (diferente para cada cuenta). Pero, ¿cómo puedo validar que este máximo no se ha alcanzado al agregar nuevos usuarios a una cuenta?

principio traté de añadir una validación de la usuaria:

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

Pero esto sólo funciona si estoy añadiendo un usuario a la vez.

Si agrego varios usuarios a través de @account.update_attributes(:users_attributes => ...), pasa directamente aunque solo haya espacio para un usuario más.

Actualización:

Solo para aclarar: El método de validación actual valida que account.users.count es menor que account.maximum_amount_of_users. Así que decir por ejemplo, que es account.users.count 9 y account.maximum_amount_of_users es 10, entonces la validación pasará porque 9 < 10.

El problema es que el recuento de regresar de account.users.count no aumentará hasta que todos los usuarios se han escrito en la base de datos. Esto significa que al agregar múltiples usuarios al mismo tiempo se pasarán las validaciones, ya que el conteo de usuarios será el mismo hasta que todos sean validados.

Así como askegg señala, ¿debería agregar la validación al modelo de Cuenta también? ¿Y cómo debería hacerse eso?

Respuesta

16

Si llama al account.users.size en lugar de account.users.count, también incluirá usuarios que se han creado pero no se han guardado en la base de datos.

SIN EMBARGO esto no resolverá completamente su problema. Cuando llama al account en un usuario, no devuelve la misma instancia de cuenta a la que apunta @account, por lo que no conoce los nuevos usuarios. Creo que esto se "arreglará" en Rails 3, pero mientras tanto puedo pensar en un par de soluciones.

Si está guardando la cuenta al mismo tiempo que está agregando usuarios (que supongo que ya que está llamando al update_attributes), entonces la validación puede ir allí.

# 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 

no estoy seguro de cómo va a guardar los modelos asociados, pero si falla la validación de la cuenta que no sería salvo.

La otra solución es restablecer la instancia user.account a sí mismo al actualizar los atributos del usuario. Puede hacer esto en el método setter de users_attributes.

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

De esta manera la cuenta de usuario apuntará a la misma instancia cuenta para account.users.size debe devolver la cantidad. En este caso, mantendría las validaciones en el modelo de usuario.

Es un problema espinoso pero espero que esto le haya dado algunas ideas sobre cómo resolverlo.

-2

La razón por la que está pasando es porque update_attributes no pasa por validaciones.

Además, su lógica solo verifica el número existente de cuentas contra su máximo permitido. No hay cálculos teniendo en cuenta la cantidad de usuarios que intentan agregarse. Creo que esta lógica pertenece más al modelo de Cuenta (?).

+0

atributos_actualización ejecuta validaciones, al menos en Rails 2.3.2. Pero el problema es que el método de validación en el modelo de usuario valida que no se alcanza el máximo en comparación con la cantidad de usuarios que ya está en la cuenta. Es decir. si max == 10 y users.count == 9, entonces - al agregar dos usuarios al mismo tiempo - las validaciones se ejecutan para ambos, pero validando cada vez 9 <10. Dado que users.count no aumentará antes del los usuarios se escriben en la base de datos. Pero, ¿cómo se puede validar eso en el modelo de Cuenta? ¿Debo anular los atributos de actualización, etc.? –

+1

Ahh - disculpe. Update_attribute (tenga en cuenta las "s" que faltan al final) pasa por alto las validaciones. Mi error. Parece que Ryan (que tiene mucho más Rubyfoo que yo) ha respondido a su pregunta. No sabía que el método de "tamaño" incluye registros no guardados. Aprendes algo cada día :) – askegg

Cuestiones relacionadas