Tintin81
Tintin81

Reputation: 10207

How to ensure one child record remains?

In my Rails 4 application I have users who can have many rates.

class Rate < ActiveRecord::Base

  belongs_to :user

  validates :name, :presence => true
  validates :amount, :presence => true

  ...

end

A rate has a name, an amount, and a boolean attribute default.

How can I make sure that the user cannot accidentally delete his last rate, i.e. that at least one rate always remains associated with the user and that that rate's default attribute is set to true if there is no other rate remaining?

Thanks for any ideas.

Upvotes: 1

Views: 179

Answers (3)

user4761987
user4761987

Reputation: 11

You could move the validation to the User, and manage the Rates as nested attributes. something like

class User < ActiveRecord::Base
  has_many :rates, dependent: :destroy 
  accepts_nested_attributes_for :rates, allow_destroy: true
  validates_presence_of :rates
end

and rates need not worry

class Rate < ActiveRecord::Base
  belongs_to :user
  after_initialize :set_default, if: ->{ user.rates.count == 1 }
  ...

private

  def set_default
   self.default = true
  end 
end

Upvotes: 1

user4748331
user4748331

Reputation: 21

maybe something like...

class Rate < ActiveRecord::Base

  belongs_to :user

  validates :name, :presence => true
  validates :amount, :presence => true

  after_initialize :set_default, if: ->{ user.rates.count == 1 }
  after_destroy :ensure_rate_exists

 private

   def set_default
    self.default = true
   end

   def ensure_rate_exists
    raise "Cannot remove.." if user.rates.count.zero?
   end

end

Upvotes: 2

pierallard
pierallard

Reputation: 3371

You can do it using a specific method like this

class User
  def delete_rate(rate)
    if rates.count > 1
      self.rates.delete(rate)
    else
      raise "User should have at least one rate"
    end
  end
end

Or you can add a validation like this :

class User
  validates :rates, length: { minimum: 1 }
end

but this last solution can introduce issues on User creation.

Upvotes: 2

Related Questions