Reputation: 12653
A Rails app has an Event and Vote model. Events should be unique.
If a User attempts to create an Event that already exists, save should be prevented, and instead a Vote should be created for the existing Event.
I can prevent the Event from being saved using a custom validation or a before_create
action. However, this also prevents the create_vote_on_existing_event
method from being run.
Is there a way to selectively run methods when before_create
returns false?
My models look something like this
class Event
has_many :votes
before_create :check_event_is_unique
private
def check_event_is_unique
if Event.where( attributes_to_match).any?
errors.add(:base, :duplicate)
create_vote_on_existing_event
return false
end
end
def create_vote_on_existing_event
event = Event.where( attributes_to_match).last
self.user.vote_on event
end
end
class Vote
belongs_to :event
end
Upvotes: 0
Views: 1673
Reputation: 368
You need a custom validator. Something like this might be suitable:
class Event
validate :check_event_is_unique, :on => :create
after_create :create_vote_on_existing_event
def check_event_is_unique
if Event.where( attributes_to_match).any?
errors.add(:base, :duplicate)
return false
end
end
end
You can also have your after_create
for other methods.
More information on custom validation methods can be found here: http://guides.rubyonrails.org/active_record_validations.html#custom-methods
EDIT: One option is to pass validate: false to the save method. api.rubyonrails.org/classes/ActiveRecord/Validations.html
Another option is after_validation
. This could call your create_vote_on_existing_event
if your validation fails. The order of callbacks is as follows:
before_validation
after_validation
before_save
before_create
after_create
after_save
after_commit
after_validation
is the last thing to run if validations fail, so you should be able to run some code from there.
Upvotes: 1