2011-01-29 14 views
45

Gli utenti possono aggiungere tag a un frammento:Convalida il numero di elementi has_many in Ruby on Rails

class Snippet < ActiveRecord::Base 

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

end 

voglio per convalidare il numero di tag: almeno 1, al massimo 6. Come sono io per Fai questo? Grazie.

risposta

63

È sempre possibile creare un custom validation.

Qualcosa di simile

validate :validate_tags 

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

avrei probabilmente usare 'tags.count' in modo che il DB fa il lavoro e non si carica tutti i tag solo per questo uno convalida. –

+7

@Beerlington: In effetti sembra che Nikita abbia ragione, non vuoi colpire il database per una convalida, vuoi controllare la lunghezza effettiva dei "tag" dell'oggetto. – tokland

+28

Se si utilizza tag.size, fa la cosa "giusta". vedere http://blog.hasmanythrough.com/2008/2/27/count-length-size –

43

Una soluzione migliore è stato fornito dal @SooDesuNe su this SO post

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

FWIW, il messaggio di errore predefinito per questo è "è troppo lungo (il numero massimo è 100 caratteri)" – user605331

5

penso che è possibile convalidare con l'utilizzo di .reject(&:marked_for_destruction?).length.

Che ne dici di questo?

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 questo.

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 

Quindi, è possibile comandare.

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

Grazie per la lettura.

Riferimenti:

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

+1

Non avevo idea della possibilità di passare un blocco ai metodi di associazione. È fenomenale, grazie. –

+0

Due anni dopo: il metodo 'length' nel blocco non viene mai chiamato. Un blocco passato a 'has_many' è in realtà chiamato un'estensione. Puoi creare nuovi "finder, creatori e altri metodi di tipo factory" con esso. https://apidock.com/rails/ActiveRecord/Associations/ClassMethods/has_many – haffla

Problemi correlati