14

ho due modelli: Project e ProjectDiscipline:Rails 3: convalidare presenza di almeno uno ha molti attraverso voce associazione

class Project < ActiveRecord::Base 
    has_many :project_disciplinizations, :dependent => :destroy 
    has_many :project_disciplines, through: :project_disciplinizations 
    attr_accessible :project_discipline_ids 
    attr_accessible :project_disciplines_attributes 
    accepts_nested_attributes_for :project_disciplines, :reject_if => proc { |attributes| attributes['name'].blank? } 
end 

class ProjectDiscipline < ActiveRecord::Base 
    attr_accessible :name 
    has_many :project_disciplinizations, :dependent => :destroy 
    has_many :projects, through: :project_disciplinizations 
end 

class ProjectDisciplinization < ActiveRecord::Base 
    attr_accessible :project_discipline_id, :project_id 
    belongs_to :project_discipline 
    belongs_to :project 
end 

Sul nuovo modulo/modificare Project, ho una lista di discipline e un assegno scatola per ognuno di loro, così gli utenti possono scegliere le discipline:

<div class="control-group"> 
    <label class="control-label">Check disciplines that apply</label> 
    <div class="controls"> 
    <%= f.collection_check_boxes(:project_discipline_ids, ProjectDiscipline.order('name'), :id, :name, {}, {:class => 'checkbox'}) {|input| input.label(:class => 'checkbox') { input.check_box + input.text }} %> 
    <p class="help-block">You must choose at least one discipline.</p> 
    </div> 
</div> 

voglio aggiungere una convalida di esigere che almeno una disciplina sia selezionata. Ho provato ma non ho ancora capito. Come posso aggiungere questa convalida?

risposta

15

Nota a margine prima della risposta, in base alla struttura dei modelli, utilizzerei has_and_belongs_to_many anziché utilizzare questo esplicito modello di collegamento poiché sembra che il modello di collegamento non aggiunga nulla di valore.

In entrambi i casi, la risposta è la stessa, ovvero utilizzare una convalida personalizzata. A seconda che tu segua le cose come sono o che semplifichi un has_and_belongs_ a molti, ti consigliamo di convalidare leggermente in modo diverso.

validate :has_project_disciplines 

def has_project_disciplines 
    errors.add(:base, 'must add at least one discipline') if self.project_disciplinizations.blank? 
end 

o con has_and_belongs_to_many

validate :has_project_disciplines 

def has_project_disciplines 
    errors.add(:base, 'must add at least one discipline') if self.project_disciplines.blank? 
end 
+0

Puoi rivedere la mia risposta? – asiniy

+0

Se si distrugge la disciplina, potrebbe accadere che un progetto non abbia più discipline e quindi sia in uno stato non valido. – wacha

+1

'.empty?' Sarebbe più appropriato qui, query vuote restituiscono il record dal DB, vuoto fa 'SELECT 1 AS uno FROM' project_disciplines 'WHERE AND' project_disciplines' .'id' = 1 LIMIT 1', che è leggermente più efficiente. –

3

È possibile scrivere il proprio validatore

class Project < ActiveRecord::Base 

    validate :at_least_one_discipline 

    private 
    def at_least_one_discipline 
    # Check that at least one exists after items have been de-selected 
    unless disciplines.detect {|d| !d.marked_for_destruction? } 
     errors.add(:disciplines, "must have at least one discipline") 
    end 
    end 
end 
+0

Puoi rivedere la mia risposta? – asiniy

11

preferisco approccio più semplice:

class Project < ActiveRecord::Base 
    validates :disciplines, presence: true 
end 

Questo codice non fare assolutamente lo stesso codice di di John Naegle o Alex Peachey, a causa del metodo sfrutta anche il metodo .

+2

Sì, ma a seconda di come è impostato il modulo, probabilmente non è un ottimo posto per segnalare un errore, che verrà allegato all'associazione: discipline (che non esiste). Gli altri approcci aggiungono l'errore a: base, che è probabilmente più appropriato. – KenB

Problemi correlati