before_save if attribute.present?

时间:2016-03-06 20:09:21

标签: ruby-on-rails ruby methods before-save

before_save :date_started_sets_deadline, if date_started.present?

如果before_save,我不希望此:date_started == nil运行。我已经尝试了上面这一行的各种版本,所以不确定我是否必须改变它或方法本身。

def date_started_sets_deadline
  if self.date_started > Date.tomorrow
    self.deadline = self.date_started
  end
end

我试图在用户尝试创建没有NoMethodError (undefined method '>' for nil:NilClass): app/models/challenge.rb:35:in 'date_started_sets_deadline'

的挑战时避免错误date_started

4 个答案:

答案 0 :(得分:4)

before_save语句更改为以下内容:

before_save :date_started_sets_deadline, if: :date_started?

如果您向symbol提供if,则rails会对其进行评估 在实例的上下文中。通过添加?,它是一个自动生成的方法,与date_started.present?基本相同。

此外,如果date_started实现中需要date_started_sets_deadline,我还会明确添加检查,而不是仅仅依赖于在回调逻辑上添加if条件。

def date_started_sets_deadline
  if self.date_started.present? && (self.date_started > Date.tomorrow)
    self.deadline = self.date_started
  end
end

有关详细信息,请参阅Using :if and :unless with a Symbol

答案 1 :(得分:1)

这样做的一种方法是在方法中添加条件。

def date_started_sets_deadline
  if self.date_started != nil 
    if self.date_started > Date.tomorrow
     self.deadline = self.date_started
    end
  end
end

修改

试试这个,我在个人项目上查了一下。

before_save :date_started_sets_deadline, if: self.date_started.present?

答案 2 :(得分:1)

另一个答案提到要提供要调用的符号,我建议您创建自己的方法作为该符号,以便您可以包含您感兴趣的所有条件,即

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

我认为这比在before_save和setter中重复逻辑要清晰得多。

答案 3 :(得分:0)

您可以检查条件并更改回调方法中的数据。

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

但我认为分担这些责任是一个好主意。例如,您可以在另一个方法中移动支票。

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

对于简单的条件,很难找到好的方法名称或感觉有点过度设计,因此您可以使用procs和lambdas直接在回调定义中进行检查。但你应该仔细使用它。

before_save :set_deadline, if: ->() { date_started.present? }

def set_deadline
  self.deadline = date_started if self.date_started > Date.tomorrow
end