开发者

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.

0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜