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
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.
Comments