2011-01-29 8 views
45

Los usuarios pueden añadir etiquetas a un fragmento:Validar el número de elementos has_many en Ruby on Rails

class Snippet < ActiveRecord::Base 

    # Relationships 
    has_many :taggings 
    has_many :tags, :through => :taggings 
    belongs_to :closing_reason 

end 

que desea validar el número de etiquetas: al menos 1, como mucho 6. ¿Cómo estoy a punto de ¿hacer esto? Gracias.

Respuesta

63

Siempre puede crear un custom validation.

Algo así como

validate :validate_tags 

    def validate_tags 
    errors.add(:tags, "too much") if tags.size > 5 
    end 
+12

que probablemente usar 'tags.count' de manera que el PP hace el trabajo y no se cargan todas las etiquetas sólo para éste validación. –

+7

@Beerlington: De hecho, parece que Nikita tiene razón, no desea acceder a la base de datos para una validación, quiere verificar la longitud real de las "etiquetas" del objeto. – tokland

+28

Si usa tags.size, hace lo "correcto". vea http://blog.hasmanythrough.com/2008/2/27/count-length-size –

43

Una mejor solución ha sido proporcionada por @SooDesuNe en this SO post

validates :tags, length: { minimum: 1, maximum: 6 } 
+1

FWIW, el mensaje de error predeterminado para esto es "es demasiado largo (máximo 100 caracteres)" – user605331

5

creo que se puede validar con el uso de .reject(&:marked_for_destruction?).length.

¿Qué tal esto?

class User < ActiveRecord::Base 
    has_many :groups do 
    def length 
     reject(&:marked_for_destruction?).length 
    end 
    end 
    accepts_nested_attributes_for :groups, allow_destroy: true 
    validates :groups, length: { maximum: 5 } 
end 

O este.

class User < ActiveRecord::Base 
    has_many :groups 
    accepts_nested_attributes_for :groups, allow_destroy: true 
    GROUPS_MAX_LENGTH = 5 
    validate legth_of_groups 

    def length_of_groups 
    groups_length = 0 
    if groups.present? 
     groups_length = groups.reject(&:marked_for_destruction?).length 
    end 
    errors.add(:groups, 'too many') if groups_length > GROUPS_MAX_LENGTH 
    end 
end 

Luego, puede ordenar.

@user.assign_attributes(params[:user]) 
@user.valid? 

Gracias por leer.

Referencias:

http://homeonrails.com/2012/10/validating-nested-associations-in-rails/ http://qiita.com/asukiaaa/items/4797ce44c3ba7bd7a51f

+1

No tenía idea acerca de la capacidad de pasar un bloque a los métodos de asociación. Eso es fenomenal, gracias. –

+0

Dos años después: el método 'length' en el bloque en realidad nunca se llama. Un bloque pasado a 'has_many' se llama realmente una extensión. Puede crear nuevos "buscadores, creadores y otros métodos de tipo fábrica" ​​con él. https://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many – haffla