вопрос объявления класса ruby - PullRequest
3 голосов
/ 13 июля 2010

в рубине вы можете иметь:

class ApplicationController < ActionController::Base
  before_filter :require_login
end

Мне просто интересно, что такое before_filter? это метод из ActionController :: Base?

а что будет, если я создам объект ApplicationController? Будет запущен метод before_filter?

спасибо!

Ответы [ 4 ]

8 голосов
/ 13 июля 2010

Да, before_filter - это метод в ActionController :: Base. Все, что указано в before_filter, будет выполнено до вызова действия (й).

Документация по API: http://api.rubyonrails.org/classes/ActionController/Filters/ClassMethods.html#M000316

EDIT:

Когда вы пишете непосредственно в класс, этот код выполняется, когда класс загружается в интерпретатор.

Набрав это в IRB:

>> class Hello
>> p "hello"
>> end
"hello"

так что в случае, когда вы упомянули, ruby ​​видит метод before_filter и пытается найти его. Он начинает искать в своем классе, затем переходит к родителю и родителю родителя и так далее, пока не доберется до Object. В этом случае он перейдет к классу ActionController :: Base и будет искать before_filter, а затем подниматься по цепочке до класса, модуля и объекта.

>> ActionController::Base.class
=> Class
>> ActionController::Base.class.superclass
=> Module
>> ActionController::Base.class.superclass.superclass
=> Object
>> ActionController::Base.class.superclass.superclass.superclass

Если вы готовы к чтению, я настоятельно рекомендую MetaProgramming Ruby , он гораздо лучше объясняет объектную модель, чем я.

3 голосов
/ 13 июля 2010

Когда вы выполняете метод внутри определения класса, вы фактически делаете это:

class ApplicationController
  self.before_filter
end

когда self - это сам объект класса (например, попробуйте puts self в определении класса)

Например, способ определения фильтра для бедного человека будет

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

И вы можете проверить это

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

Надеюсь, это проясняет

2 голосов
/ 13 июля 2010

Важно знать, что на ruby ​​код внутри объявления класса не является "особым".

Это просто обычный код.Вы не ограничены определением методов и переменных класса - ваш код может делать практически все, что угодно.

Вы можете, например, делать такие вещи:это печатает «вау» и возвращает ноль.

Я скажу это еще раз: вы можете включить в определение класса все, что захотите. Включая вызов методов, которые изменяют сам класс .

Это именно то, что делает before_filter.Он изменяет класс таким образом, что «перед вызовом любого метода в этом классе require_login должен быть вызван автоматически».

0 голосов
/ 13 июля 2010

Эта ссылка объясняет это довольно хорошо. По сути, Ruby допускает синтаксический «сахар», позволяющий определить блок кода ruby, который будет запускаться в определенное время. В случае before_filter он будет запущен перед любыми методами действий.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...