Rails nested attributes: require at least two records

两盒软妹~` 提交于 2019-12-04 19:25:29

问题


How can I make it so that at least two option records are required to submit a product?

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

回答1:


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



回答2:


Just a consideration about karmajunkie answer: I would use size instead of count because if some built (and not saved) nested object has errors, it would not be considered (its not on database yet).

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



回答3:


If your form allows records to be deleted then .size will not work as it includes the records marked for destruction.

My solution was:

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



回答4:


Tidier code, tested with 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


来源:https://stackoverflow.com/questions/4309354/rails-nested-attributes-require-at-least-two-records

工具导航Map