class Foo
def do_before
...
end
def do_something
...
Is there a way to run do_before
method before each other method in the Foo
class (like do_something
)?
It seems that the Sinatra before
block runs before each HTTP request, which has nothing to do with this class.
EDIT: As Michael pointed out in the comments, the only similar functionality that Rails offers is in the Controller. However, both Rails and Sinatra offer something similar to this functionality.
As iain pointed out in the comments, the example you specify is not specific to Rails/Sinatra. I'm assuming you want before filter like the ones in Rails and this is what Sinatra offers:
Sinatra's modular apps:
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
In your config.rb
file,
require 'foo.rb'
require 'bar.rb'
map '/foo' do
run Foo
end
map '/bar' do
run Bar
end
This is the nearest analogy for a Rails controller in Sinatra. Create more classes like this and you'll have a similar functionality (similar, but may not be the same as you might expect in Rails world).
You can also use a bit of meta-programming to create a before filter. For instance:
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"
In this case, the preprocess_method
(that is the do_before on your example) will be called before each call to any instance method defined within the Foo class.
Not knowing what you're doing makes it difficult to know how to answer, but to increase the information out there on the web;) I'll give an alternative to @fmendez's answer:
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
output:
Before…
# => 12