вызов метода в определении класса? - PullRequest
4 голосов
/ 09 февраля 2012
class Person < ActiveRecord::Base
  validates :terms_of_service, :acceptance => true
end

В вышеприведенном, что такое validates с точки зрения Ruby? Это не метод определение , это не определение или объявление данных, поэтому, очевидно, это метод вызов , прямо в теле класса. Я никогда не видел, чтобы метод вызывался подобным образом непосредственно в классе (т.е. вне определения метода), даже в учебнике по программированию на Ruby, который я сейчас прохожу: http://ruby -doc.org / docs / ProgrammingRuby / .

Итак, если это вызов метода, в какой момент он вызывается. В качестве теста я попробовал следующее:

class Person   

  print "cat"

end

#p = Person.new
#q = Person.new

print "cat" выполняется ровно один раз, независимо от того, объявляются ли какие-либо реальные объекты Person или нет, поэтому, очевидно, просто при синтаксическом анализе определения класса Ruby видит метод print и говорит: «Хорошо, я просто продолжу и выполню это сейчас ", но никогда не делает это снова.

ТАК где документация по Ruby, которая поможет мне понять, что происходит с validates выше

Спасибо.

1 Ответ

9 голосов
/ 09 февраля 2012

В Ruby объявления классов - это просто фрагменты кода, выполняемые по порядку.

Важно помнить, что внутри определения класса self указывает на сам класс. validates - это метод класса ActiveRecord. Поскольку класс определяется, код в определении выполняется. Метод validates преобразуется в метод класса ActiveRecord, поэтому он называется во время определения класса .

В вашем примере Person он будет напечатан только один раз, потому что вы определяете класс только один раз.

Примите во внимание следующее:

class Foo
  def self.validates_nothing(sym)
    (@@syms ||= []) << sym
    puts "!!! Here there be logic"
  end

  def validate
    @@syms.each { |s| puts s }
  end
end

Это определяет класс с методом класса validates_nothing и методом экземпляра validate. validates_nothing просто собирает любые аргументы, которые ему даны, validate просто выводит их.

class Bar < Foo
  validates_nothing :anything
  validates_nothing :at_all
end

Это определяет подкласс. Обратите внимание, что когда вызывается метод класса validates_nothing, он печатает:

Here there be logic
Here there be logic

Если мы создадим новый бар и вызовем validate, мы получим ожидаемый результат:

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