是否可以在Ruby中执行before_action(如在Rails中)?

时间:2014-05-03 13:18:53

标签: ruby

是否可以在某些指定方法之前调用before_action,例如在rails中?

class Calculator
  before_action { raise Exception, "calculator is empty" if @numbers.nil? }, 
                 only: [:plus, :minus, :divide, :times]

  def push number
    @numbers ||= [] 
    @numbers << number
  end

  def plus
    # ... 
  end

  def minus
    # ... 
  end

  def divide
    # ... 
  end

  def times
    # ... 
  end

    # ... 
end

4 个答案:

答案 0 :(得分:6)

可以用纯红宝石来完成!一种方法是使用method aliasing

class Foo
  def bar
    #true bar
  end

  alias_method :original_bar, :bar

  def bar
    before_stuff
    original_bar
    after_stuff
  end
end

但是对于更通用的方法,您可以阅读this thread

您的代码的示例可以是:

class Calculator

    def plus
      ...
    end

    def end
      ...
    end

    def divide
      ...
    end

    den times
      ...
    end

    [:plus, :minus, :divide, :times].each do |m|
      alias_method "original_#{m.to_s}".to_sym, m

      define_method m do
        check_numbers
        send("original_#{m.to_s}".to_sym)
      end
    end

    private

    def check_numbers
      raise Exception, "calculator is empty" if @numbers.nil? 
    end
end

答案 1 :(得分:3)

您正在寻找的是Aspect oriented programming对红宝石的支持。有几个宝石实现了这一点,比如aquarium

我认为,在你的情况下,一些懒惰的检查就足够了:

class Calculator
  def numbers
    raise Exception, "calculator is empty" if @numbers.nil?
    @numbers
  end

  def push number
    @numbers ||= [] 
    @numbers << number
  end

  def plus
    numbers.inject(:+) # <-- will throw the correct Exception if `@numbers` is nil
    # ... 
  end

  def minus
    # ... 
  end

  def divide
    # ... 
  end

  def times
    # ... 
  end

    # ... 
end

答案 2 :(得分:1)

您可以添加active_support中的ActiveSupport::Callbacks并定义您需要的任何回调:

文档中的示例:

class Record
  include ActiveSupport::Callbacks
  define_callbacks :save

  def save
    run_callbacks :save do
      puts "- save"
    end
  end
end

class PersonRecord < Record
  set_callback :save, :before, :saving_message
  def saving_message
    puts "saving..."
  end

  set_callback :save, :after do |object|
    puts "saved"
  end
end

person = PersonRecord.new
person.save

# Output: 
# saving...
# - save
# saved

答案 3 :(得分:0)

你可以编写自己的逻辑,所以它是可能的。但在这种情况下,我认为你不需要。 Ruby为您提供了一个处理它的工具。您可以使用类initialize方法,该方法在首次初始化类时调用:例如,Calculate.new

class Calculator
  def initialize(inputs)
    raise Exception, "calculator is empty" unless inputs
  end

  # ... rest of the class
end

您需要输入任何数学运算,为什么不添加init方法?如果没有传入数字,那么很难做任何数学运算。

小心将Rails控制器逻辑移植到纯Ruby。 Rails控制器本身不是典型的OOP,它们违反了许多OOP规则。 Ruby更灵活。