How to validate the number of children records?

Andy Harvey

I have Rails 4 app with two models.

class User 
  has_many :bids
end

class Bid
  belongs_to :user
end 

A User can only create one bid per week, so I added the following to the Bid table

add_column :bids, :expiry, :datetime, default: DateTime.current.end_of_week

and the following scopes to the Bid model

scope :default, -> { order('bids.created_at DESC') }
scope :active, -> { default.where('expiry > ?', Date.today ) }

I can now prevent a User creating multiple Bids at the controller level like so:

class BidsController
  def new
    if current_user.bids.active.any?
      flash[:notice] = "You already have an active Bid. You can edit it here."
      redirect_to edit_bid_path(current_user.bids.active.last)
    else
      @bid = Bid.new
      respond_with(@bid)
    end
  end
end

But what is the best approach for validating this at the model level?

I've been trying to set up a custom validation, but am struggling to see the best way to set this up so that the current_user is available to the method. Also, am I adding errors to the correct object?

class Bid
  validate :validates_number_of_active_bids
  def validates_number_of_active_bids
    if Bid.active.where(user_id: current_user).any?
      errors.add(:bid, "too much") 
    end
  end 
end
Abraham Sangha

In order to maintain separation of concerns, keep the current_user knowledge out of the model layer. Your Bid model already has a user_id attribute. Also, I'd add an error like so since the validation is not checking a "bid" attribute on Bid, but rather the entire Bid may be invalid.

class Bid
  validate :validates_number_of_active_bids
  def validates_number_of_active_bids
    if Bid.where(user_id: user_id).active.any?
      errors[:base] << "A new bid cannot be created until the current one expires"
    end
  end 
end

Collected from the Internet

Please contact [email protected] to delete if infringement.

edited at
0

Comments

0 comments
Login to comment

Related