14

Ich habe zwei Modelle: Project und ProjectDiscipline:Rails 3: Vorhandensein von mindestens zu validieren hat man viele durch Vereinigung Artikel

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 

Auf der neuen bearbeiten/Project Form habe ich eine Liste von Disziplinen und einem Scheck für jeden von ihnen Box, so dass Benutzer Disziplinen auswählen können:

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

ich, dass zumindest eine eine Validierung erfordern hinzufügen möchten Disziplin überprüft wird. Ich habe es versucht, aber ich habe es noch nicht herausgefunden. Wie kann ich diese Validierung hinzufügen?

Antwort

15

Seitennotiz vor der Antwort, basierend auf der Struktur Ihrer Modelle würde ich has_and_belongs_to_many anstelle dieses expliziten Verknüpfungsmodells verwenden, da es scheint, dass das Verknüpfungsmodell nichts Wertvolles hinzufügt.

Wie auch immer, die Antwort ist die gleiche, die eine benutzerdefinierte Validierung verwenden soll. Abhängig davon, ob Sie mit den Dingen gehen, wie sie sind, oder zu einem has_and_belongs_to vereinfachen, sollten Sie etwas anders validieren.

validate :has_project_disciplines 

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

oder mit 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

Können Sie meine Antwort überprüfen? – asiniy

+0

Wenn Sie die Disziplin später zerstören, kann es passieren, dass ein Projekt keine Disziplinen mehr hat und somit in einem ungültigen Zustand ist. – wacha

+1

'.lepty?' Wäre hier besser geeignet, leere Abfragen gibt den Datensatz aus der DB zurück, leer 'SELECT 1 AS one FROM 'Projekt_disziplinen' WHERE UND 'project_disciplines' .'id' = 1 LIMIT 1', was leicht ist effizienter. –

3

Sie können Ihre eigenen Validator

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

Können Sie meine Antwort überprüfen? – asiniy

11

Ich ziehe es einfacher Ansatz schreiben:

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

Dieser Code tun absolut die gleichen wie Code von John Naegle oder Alex Peachey, wegen validates_presence_of Exploit blank? Methode auch.

+2

Ja, aber abhängig davon, wie Ihr Formular eingerichtet ist, gibt es wahrscheinlich keinen guten Ort, um einen Fehler zu melden, der an die: disciplines association (die nicht existiert) angehängt wird. Die anderen Ansätze fügen den Fehler zu: base, was wahrscheinlich geeigneter ist. – KenB