Reputation: 2866
before_save :date_started_sets_deadline, if date_started.present?
I don't want this before_save
to run if :date_started == nil
. I've tried various versions of the above line so not sure if I have to change that or the method itself.
def date_started_sets_deadline
if self.date_started > Date.tomorrow
self.deadline = self.date_started
end
end
I'm trying to avoid the error NoMethodError (undefined method '>' for nil:NilClass): app/models/challenge.rb:35:in 'date_started_sets_deadline'
whenever a user tries to create a challenge without a date_started
Upvotes: 3
Views: 4732
Reputation: 46
You can check the conditions and change the data inside the callback method.
before_save :date_started_sets_deadline
def date_started_sets_deadline
if date_started.present? && self.date_started > Date.tomorrow
self.deadline = self.date_started
end
end
But i think it's a good idea to split this responsibilities. For example you can move the check inside another method.
before_save :set_deadline, if: :set_deadline?
def set_deadline?
date_started.present? && date_started > Date.tomorrow
end
def set_deadline
self.deadline = date_started
end
For simple conditions it's very hard to find good method names or it feels a little bit over engineered, so you can check it directly at callback definition with procs and lambdas. But you should use it carefully.
before_save :set_deadline, if: ->() { date_started.present? }
def set_deadline
self.deadline = date_started if self.date_started > Date.tomorrow
end
Upvotes: 0
Reputation: 27961
Another answer mentions providing the symbol to be called, I would recommend creating your own method to be that symbol so that you can include all the conditions you're interested in, ie.
before_save :set_deadline, if: :starts_after_tomorrow?
def starts_after_tomorrow?
date_started? && date_started > Date.tomorrow
end
def set_deadline
self.deadline = date_started
end
I think that's much cleaner than having the logic repeated in your before_save
and setter.
Upvotes: 1
Reputation: 6438
Change the before_save
statement to the following:
before_save :date_started_sets_deadline, if: :date_started?
If you provide a symbol
to the if
, then rails
evaluates it
in the context of the instance. By adding ?
, it is a auto generated method which is essentially same as date_started.present?
.
Also, if the date_started
is required within the date_started_sets_deadline
implementation, I would also add the check explicitly instead of solely depending on adding the if
condition on the callback logic.
def date_started_sets_deadline
if self.date_started.present? && (self.date_started > Date.tomorrow)
self.deadline = self.date_started
end
end
Refer to Using :if and :unless with a Symbol for more info.
Upvotes: 5
Reputation: 1213
One way to do it will be putting a conditional if in side the method.
def date_started_sets_deadline
if self.date_started != nil
if self.date_started > Date.tomorrow
self.deadline = self.date_started
end
end
end
EDIT
Try this, I checked it on a personal project.
before_save :date_started_sets_deadline, if: self.date_started.present?
Upvotes: 1