ruby class declaration question
in ruby you can have:
class ApplicationController < ActionController::Base
before_filter :require_login
end
i just wonder what is before_filter? it's a method from ActionController::Base?
and what will happen if i create an obje开发者_JS百科ct of ApplicationController? The before_filter method will be run?
thanks!
Yes, before_filter
is a method on ActionController::Base. Anything specified in before_filter
will run before the action(s) being called.
API Documentation: http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000316
EDIT:
When you write directly into a class, that code is executed when the class is loaded into the interpreter.
Typing this into IRB:
>> class Hello
>> p "hello"
>> end
"hello"
so in the case you mentioned ruby sees the before_filter
method and it tries to find it. It starts looking in its class, then it goes into the parent and the parent's parent, and so on until it gets to Object
. In this case, it will go up to the ActionController::Base class and look for the before_filter
and then up the chain to class, module and object.
>> ActionController::Base.class
=> Class
>> ActionController::Base.class.superclass
=> Module
>> ActionController::Base.class.superclass.superclass
=> Object
>> ActionController::Base.class.superclass.superclass.superclass
If you are up for reading, I highly recommend MetaProgramming Ruby, it does a much better job of explaining the object model than I can.
When you execute a method inside a class definition, you are actually doing this:
class ApplicationController
self.before_filter
end
when self is the class object itself (for instance, try puts self
in the class definition)
For example, a poor man way of defining a filter would be
class Filterable
@@filters = []
def self.before_filter(method_name)
@@filters << method_name
end
def self.filters
@@filters
end
def some_important_method
self.class.filters.each do |method_name|
# Halt execution if the return value of one of them is false or nil
return unless self.send(method_name)
end
puts "I'm in some important method"
# Continue with method execution
end
end
class SomeClass < Filterable
before_filter :first_filter
before_filter :second_filter
attr_accessor :x
def initialize(x)
@x = x
end
def first_filter
puts "I'm in first filter"
true
end
def second_filter
puts "I'm in second filter"
@x > 5
end
end
And you can test it
SomeClass.new(8).some_important_method
# => I'm in first filter
# I'm in second filter
# I'm in some important method
SomeClass.new(3).some_important_method
# => I'm in first filter
# I'm in second filter
Hope it is clarifying
It is important to know that on ruby the code inside a class declaration isn't "special".
It's just regular code. You are not limited to defining methods and class variables - your code there can do pretty much anything.
You can, for example, do stuff like this:
class MyClass
print "wow"
end
After the end, this prints "wow" and returns nil.
I'll say that again: You can do include much anything you want inside a class definition. Including invoking methods that modify the class itself.
That is exactly what before_filter
does. It modifies the class, in a way that "before any method on this class is invoked, require_login
must be automatically called".
This link explains it pretty well. Basically Ruby is allowing syntactic "sugar" allowing you to define a block of ruby code that will run at a specific time. In the before_filter
case it will be run before any action methods.
精彩评论