2013-07-23 22 views
14

Tôi có hai mô hình: ProjectProjectDiscipline:Rails 3: xác nhận sự hiện diện của ít nhất một có rất nhiều thông qua mục liên

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 

Về hình thức/chỉnh sửa Project mới, tôi có một danh sách các môn học và một tấm séc hộp cho mỗi người trong số họ để người dùng có thể chọn kỷ luật:

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

Tôi muốn thêm xác thực để yêu cầu ít nhất một môn học được chọn. Tôi đã thử nhưng tôi vẫn chưa tìm ra. Làm cách nào tôi có thể thêm xác thực này?

Trả lời

15

Lưu ý phụ trước câu trả lời, dựa trên cấu trúc của mô hình, tôi sẽ sử dụng has_and_belongs_to_many thay vì sử dụng mô hình liên kết rõ ràng này vì nó xuất hiện mô hình liên kết không thêm bất kỳ giá trị nào.

Dù bằng cách nào, câu trả lời là giống nhau, đó là sử dụng xác thực tùy chỉnh. Tùy thuộc vào việc bạn có đi theo mọi thứ theo cách của chúng hay đơn giản hóa đến một has_and_belongs_to nhiều người mà bạn sẽ muốn xác thực một cách hơi khác nhau.

validate :has_project_disciplines 

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

hoặc với 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

Bạn có thể xem lại câu trả lời của tôi không? – asiniy

+0

Nếu bạn sau đó phá hủy kỷ luật, nó có thể xảy ra rằng một dự án không có kỷ luật nữa và do đó đang ở trạng thái không hợp lệ. – wacha

+1

'.empty?' Sẽ phù hợp hơn ở đây, các truy vấn trống trả về bản ghi từ DB, trống rỗng 'SELECT 1 AS một FROM' project_disciplines 'WHERE AND' project_disciplines '.'id' = 1 LIMIT 1', hơi hiệu quả hơn. –

3

Bạn có thể viết validator của riêng bạn

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

Bạn có thể xem lại câu trả lời của tôi không? – asiniy

11

Tôi thích cách tiếp cận đơn giản hơn:

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

Mã này làm hoàn toàn tương tự như mã bởi John Naegle hoặc Alex Peachey, bởi vì validates_presence_of cũng khai thác phương thức blank?.

+2

Có, nhưng phụ thuộc vào cách thức thiết lập biểu mẫu của bạn, có thể không phải là nơi rất tốt để báo cáo lỗi, sẽ được đính kèm vào: liên kết ngành (không tồn tại). Các cách tiếp cận khác thêm lỗi vào: base, có lẽ là thích hợp hơn. – KenB

Các vấn đề liên quan