jeudi 26 octobre 2017

Rails 4 - ensure has_many associated objects (integer) start at 0 and have no "gap" in the incremental values

I have two models sharing a has many/belong to relations

A Deal has_many Steps.

Each step as an attribute called "Appearance Order" which define when it appears (different than the id).

It's an integer that I validate is >= 0 and <15

I input the Steps directly in Active Admin's Deal edition thanks to:

accepts_nested_attributes_for :steps, allow_destroy: true

I already have in place a validation that ensures that there can't be one Step belonging to the same Deal and sharing the similar 'Appearance Order' thanks to:

validates :appearance_order, uniqueness: { scope: [:deal_id] }

But today, A Deal where the various associated Steps would have as 'Appearance Order" 1, 5, 7,14 would be accepted. I need to find a validation that reject that case.

On the Deal model I need validations that ensure:

  • among one deal(id:4).steps (steps associated with the Deal) , there is at least one with the 'Appearance Order' equal to 0

  • then the deal(id:4).steps' 'Appearance order' have no "gap" between each of their value. It must be 0,1,2,3,4,....and so on.

For example if I create a Deal with 4 Steps who have 'Appearance Order' attribute of 0,1,2,5 should be rejected because there is a gap between 2 and 5.

Here is my code:

models/step.rb

class Step < ActiveRecord::Base
  belongs_to :deal,             :foreign_key => 'deale_id'
   validates :appearance_order,
              presence: true,
              numericality: { greater_than_or_equal_to: 0,
                              less_than_or_equal_to: 14}

   validates :appearance_order, uniqueness: { scope: [:deal_id] }
end

models/deal.rb

class Deal < ActiveRecord::Base

  has_many   :steps,          dependent:  :destroy do   
    # source: http://ift.tt/2jhaYEm
    def length
      reject(&:marked_for_destruction?).length
    end
  end 

  validates :steps, length: { maximum: 15 }

end

Aucun commentaire:

Enregistrer un commentaire