Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Rails accepts_nested_attributes count validation

I've got three models. Sales, items, and images. I'd like to validate that when a sale is created there are at least three photos per sale and one or more items. What would be the best way to achieve this?

Sales Model:

class Sale < ActiveRecord::Base
   has_many :items, :dependent => :destroy
   has_many :images, :through => :items

   accepts_nested_attributes_for :items, :reject_if => lambda { |a| a[:title].blank? }, :allow_destroy => true
end

Items Model:

class Item < ActiveRecord::Base

  belongs_to :sale, :dependent => :destroy
  has_many :images, :dependent => :destroy

  accepts_nested_attributes_for :images

end

Images Model:

class Image < ActiveRecord::Base
  belongs_to :item, :dependent => :destroy
end
like image 893
Elliot Avatar asked Mar 29 '12 19:03

Elliot


2 Answers

Create custom methods for validating

In your sales model add something like this:

validate :validate_item_count, :validate_image_count

def validate_item_count
  if self.items.size < 1
    errors.add(:items, "Need 1 or more items")
  end
end

def validate_image_count
  if self.items.images.size < 3
    errors.add(:images, "Need at least 3 images")
  end
end

Hope this helps at all, good luck and happy coding.

like image 79
Donavan White Avatar answered Sep 23 '22 13:09

Donavan White


Another option is using this little trick with the length validation. Although most examples show it being used with text, it will check the length of associations as well:

class Sale < ActiveRecord::Base
   has_many :items,  dependent: :destroy
   has_many :images, through: :items

   validates :items,  length: { minimum: 1, too_short: "%{count} item minimum" }
   validates :images, length: { minimum: 3, too_short: "%{count} image minimum" }
end

You just need to provide your own message as the default message mentions a character count.

like image 45
Graham Conzett Avatar answered Sep 23 '22 13:09

Graham Conzett