如果记录存在,Rails如何改进?

时间:2013-08-11 19:06:02

标签: ruby-on-rails ruby ruby-on-rails-3 ruby-on-rails-3.2

我有这个型号:

class Device < ActiveRecord::Base
  has_many :events

  def last_event
     events.last
  end
end

如您所见,我有一种方法可以获取设备的最后一个事件。现在,在Device模型的其他地方我有这个方法:

def place
   self.last_event.place
end

现在,如果我在此设备的事件中没有任何记录,我会收到错误“nil的未定义方法'地点':NilClass”。

所以我补充道:

def place
   self.last_event.place if self.last_event.present?
end

这个模式在整个应用程序中重复出现,我不得不添加“if self.last_event.present?”所以它也不会在其他地方崩溃。

我确信必须有更好的方法来处理这种事情,而无需检查last_event是否存在于何处?

有什么建议吗?

谢谢,

3 个答案:

答案 0 :(得分:3)

try方法(ActiveSupport的添加)允许这样做。如果在nil对象上调用它,它也将返回nil。因此,以下两行是等效的:

self.last_event.try(:place)
# equivalent to
self.last_event.place if self.last_event

答案 1 :(得分:0)

另一个选择是让方法返回一个响应调用的空白对象:

class Device < ActiveRecord::Base
  has_many :events

   def last_event
      events.last || Event.new
   end

   def place
      self.last_event.place
   end
end

2.0.0p247 :001 > d = Device.new
 => #<Device id: nil, name: nil, created_at: nil, updated_at: nil>
2.0.0p247 :002 > d.place
 => nil
2.0.0p247 :003 > d.last_event
 => #<Event id: nil, device_id: nil, created_at: nil, updated_at: nil, place: nil>

这个想法是,如果一个方法总是返回一个期望类型的对象,你就不必担心后续调用遇到一个nil对象。当然,这可能会产生其他影响 - 例如需要确定您是否拥有有效对象或新对象,但稍后可以通过以下方式进行检查:

2.0.0p247 :005 > d.last_event.new_record?
 => true

答案 2 :(得分:0)

在这种情况下,您可以使用代理

delegate :last, to: events, allow_nil: true,  prefix: :event
delegate :place, to: event_last, allow_nil: true