编写简单的ActiveRecord代码的方式更像ruby

时间:2015-06-27 23:45:47

标签: ruby-on-rails ruby

这是一些相当标准的Ruby on Rails 4 ActiveRecord代码:

  def hide(user)    
    self.hidden = true
    self.hidden_on = DateTime.now
    self.hidden_by = user.id
  end

  def unhide
    self.hidden = false
    self.hidden_on = nil
    self.hidden_by = nil
  end

  def lock(user)
    self.locked = true
    self.locked_on = DateTime.now
    self.locked_by = user.id
  end

  def unlock
    self.locked = false
    self.locked_on = nil
    self.locked_by = nil
  end

  # In effect this is a soft delete
  def take_offline(user)
    hide(user)
    lock(user)
  end

代码易于理解,并且不会试图变得聪明。然而,它感觉很冗长。什么是更简洁或规范的方式来指定此代码/行为?

2 个答案:

答案 0 :(得分:3)

嗯,这是一个权衡,但如果你想变得更聪明,你可以这样做:

def self.def_toggle(type, field)
  define_method(type) do |user|
    send("#{field}=", true)
    send("#{field}_on=", DateTime.now)
    send("#{field}_by=", user.id)
  end

  define_method("un#{type}") do
    send("#{field}=", false)
    send("#{field}_on=", nil)
    send("#{field}_by=", nil)
  end
end

def_toggle(:hide, :hidden)
def_toggle(:lock, :locked)

答案 1 :(得分:1)

除非你有很多这些或者你想要封装更多的逻辑,否则它有点极端。但您可以使用composed_of

执行以下操作
class Model < ActiveRecord::Base
  composed_of :hidden, class_name: 'State', mapping: %w(hidden, hidden_on, hidden_by)
  composed_of :locked, class_name: 'State', mapping: %w(locked, locked_on, locked_by)

  def hide(user)
    hidden.on
  end

  def unhide
    hidden.off
  end

  def lock(user)
    locked.on
  end

  def unlock
    locked.off
  end
end


class State < Struct.new(:state, :on, :by)
  def on(user)
    set(true, user)
  end

  def off
    set(false, nil, nil)
  end

  def on?
    state
  end

  def off?
    !on
  end

  private

  def set(state, by, on = Time.current)
    self.state = state
    self.by = by
    self.on = on
  end
end