如何在Sinatra中过滤之前创建Rails?

时间:2013-04-20 00:42:41

标签: ruby sinatra

class Foo
  def do_before
    ...
  end

  def do_something
    ...

有没有办法在do_before类(如Foo)中的其他方法之前运行do_something方法?

似乎Sinatra before块在每个HTTP请求之前运行,这与此类无关。

编辑:正如Michael在评论中指出的那样,Rails提供的唯一类似功能是在Controller中。但是,Rails和Sinatra都提供类似于此功能的东西。

3 个答案:

答案 0 :(得分:6)

在注释中指出iain,您指定的示例并不特定于Rails / Sinatra。我假设你想要像Rails中那样过滤之前想要的,这就是Sinatra提供的:

Sinatra的模块化应用程序:

class Foo < Sinatra::Base

  before do
    "Do something"
  end

  get '/' do
    "Hello World"
  end
end

class Bar < Sinatra::Base

  before do
    "Do something else"
  end

  get '/' do
    "Hello World"
  end
end

config.rb文件中,

require 'foo.rb'
require 'bar.rb'

map '/foo' do
  run Foo
end

map '/bar' do
  run Bar
end

这是Sinatra中Rails控制器最接近的类比。创建更多这样的类,你将拥有类似的功能(类似,但可能与你在Rails世界中所期望的相同)。

答案 1 :(得分:3)

您还可以使用一些元编程来创建前置过滤器。例如:

class Foo
  def method_1; p "Method 1"; end
  def method_2; p "Method 2"; end
  def preprocess_method; p "Pre-Processing method"; end

  def self.before_filter m
    current_methods = instance_methods(false) - [m]
    self.new.instance_eval do
      current_methods.each do |meth|
        inst_method =  public_method(meth)
        self.class.send :define_method,inst_method.name do
          public_send m
          inst_method.call
        end
      end
    end
  end
  before_filter :preprocess_method
end

o = Foo.new
o.method_1
#output: 
"Pre-Processing method"
"Method 1"

o.method_2
#outputs
"Pre-Processing method"
"Method 2"

在这种情况下,在每次调用Foo类中定义的任何实例方法之前,将调用preprocess_method(在您的示例中为do_before)。

答案 2 :(得分:3)

不知道你在做什么让人难以知道如何回答,但是要在网上增加信息;)我将替代@ fmendez的回答:

module Filterable
  def self.included(base)
    base.extend ClassMethods
  end
  module ClassMethods
    def do_before( name, &block )
      before_filters[name.to_sym] = block
    end
    def before_filters
      @before_filters ||= {}
    end
    def method_added( name )
      return if name.to_s.start_with?("unfiltered_")
      return if before_filters.has_key? name
      before_filters[name.to_sym] ||= nil
      alias_method "unfiltered_#{name}", name
      define_method name do |*args,&block|
        self.class.before_filters[name.to_sym].call if self.class.before_filters[name.to_sym]
        send "unfiltered_#{name}", *args, &block
      end
    end
  end
end

class Foo
  include Filterable

  def something( x )
    x * 3
  end

  do_before :something do
    puts "Before…"
  end
end

Foo.new.something 4

输出:

  

在...
   #=&gt; 12