2010-11-30 32 views
10

Làm cách nào để có thể tạo ít nhất hai bản ghi tùy chọn để gửi một sản phẩm?Đường ray thuộc tính lồng nhau: yêu cầu ít nhất hai bản ghi

class Product < ActiveRecord::Base 
    belongs_to :user 
    has_many :options, :dependent => :destroy 
    accepts_nested_attributes_for :options, :allow_destroy => :true, :reject_if => proc { |attrs| attrs.all? { |k, v| v.blank? } } 
    validates_presence_of :user_id, :created_at 
    validates :description, :presence => true, :length => {:minimum => 0, :maximum => 500} 
end 

class Option < ActiveRecord::Base 
    belongs_to :product 
    validates :name, :length => {:minimum => 0, :maximum => 60}     
end 
+0

Nó nên được khá đơn giản để làm với một xác nhận tùy chỉnh. Một cái gì đó như 'self.errors.add_to_base (" Hai tùy chọn được yêu cầu ") trừ khi self.options.length> = 2' – Todd

+0

cảm ơn bạn đã làm việc! – morcutt

+0

Nếu bạn đang sử dụng 'accept_nested_attributes_for' với' allow_destroy: true' thì bạn phải sử dụng 'marked_for_destruction?' Với liên kết con để tìm chiều dài chính xác của trẻ em, bởi vì nó có thể xảy ra trong khi đệ trình từ một số đối tượng đã được đánh dấu '_destroy: true' để hủy sau khi lưu đối tượng. Chiều dài, kích thước và số lượng sẽ không hoạt động hoàn hảo cho trường hợp đó. Liên kết này có câu trả lời hoàn hảo. [link] (http://stackoverflow.com/a/28476834/4377172) –

Trả lời

15
class Product < ActiveRecord::Base 
    #... all your other stuff 
    validate :require_two_options 

    private 
    def require_two_options 
     errors.add(:base, "You must provide at least two options") if options.size < 2 
    end 
end 
+1

add_to_base (msg) đã không được chấp nhận, sử dụng lỗi # add (: base, msg) thay vì – AnApprentice

+0

Đã chỉnh sửa, cảm ơn mẹo – karmajunkie

+4

options.count sẽ tạo truy vấn SQL COUNT để tìm số tùy chọn bạn có. Nếu các tùy chọn của bạn nằm trong bộ nhớ và không được lưu trong cơ sở dữ liệu, điều này sẽ đưa ra một câu trả lời không mong muốn vì chúng sẽ không được tính vào số đếm. [Trong trường hợp như thế này, hãy xem xét sử dụng kích thước.] (Http://stackoverflow.com/questions/6083219/activerecord-size-vs-count) –

12

Chỉ cần xem xét về câu trả lời karmajunkie: Tôi sẽ sử dụng size thay vì count bởi vì nếu một số xây dựng (và không được lưu) đối tượng lồng nhau có lỗi, nó sẽ không được xem xét (nó không phải trên cơ sở dữ liệu chưa) .

class Product < ActiveRecord::Base 
    #... all your other stuff 
    validate :require_two_options 

    private 
    def require_two_options 
     errors.add(:base, "You must provide at least two options") if options.size < 2 
    end 
end 
+0

.size là cách để đi như bạn đã nói nó xem xét nó ngay cả khi nó không có trong cơ sở dữ liệu. – wallerjake

+0

'.count' không hoạt động đối với tôi. '.ize' chắc chắn là con đường để đi. – Tintin81

1

Nếu biểu mẫu của bạn cho phép xóa hồ sơ thì .size sẽ không hoạt động vì biểu mẫu được đánh dấu để hủy.

Giải pháp của tôi là:

validate :require_two_options 

private 
def require_two_options 
    i = 0 
    product_options.each do |option| 
     i += 1 unless option.marked_for_destruction? 
    end 
    errors.add(:base, "You must provide at least two option") if i < 2 
end 
+0

+1 Điểm tốt về hồ sơ tư duy được đánh dấu để hủy diệt. Tuy nhiên, một cách hơi sạch hơn để có được 'i' có thể là' i = product_options.reject {| option | option.marked_for_destruction? } .size'. – februaryInk

0

ngăn nắp mã, thử nghiệm với Rails 5:

class Product < ActiveRecord::Base 
    OPTIONS_SIZE_MIN = 2 
    validate :require_two_options 

    private 

    def options_count_valid? 
    options.reject(&:marked_for_destruction?).size >= OPTIONS_SIZE_MIN 
    end 

    def require_two_options 
    errors.add(:base, 'You must provide at least two options') unless options_count_valid? 
    end 
end 
Các vấn đề liên quan