class Foo
def do_before
...
end
def do_something
...
有没有办法在do_before
类(如Foo
)中的其他方法之前运行do_something
方法?
似乎Sinatra before
块在每个HTTP请求之前运行,这与此类无关。
答案 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