Вызовы методов Ruby объявлены в теле класса - PullRequest
57 голосов
/ 28 августа 2009

Я только начал изучать ruby ​​на рельсах, и я столкнулся с кодом, как показано ниже:

class Post < ActiveRecord::Base
 validates_presence_of   :title
 belongs_to :user
end

В теле класса есть два вызова метода. Мне было трудно найти любую рубиновую документацию, которая описывает, как работают вызовы методов внутри тела класса (но вне любого метода). Все книги, которые у меня есть, только описывают, как определять методы класса и экземпляра и как вызывать их из других методов.

У меня есть следующие вопросы: Как и когда вызываются эти методы? Как они определены? Это миксины, определенные в каком-то активном модуле записи?

Ответы [ 5 ]

33 голосов
/ 28 августа 2009

Тело определения класса является контекстом выполнения для кода, как и любой другой. Код там выполняется в контексте класса (значение self - это объект класса, который является экземпляром класса). Вы можете иметь локальные переменные и переменные экземпляра (которые будут принадлежать самому объекту класса, а не экземплярам класса), и вы можете вызвать любой метод, на который отвечает объект класса. Код запускается после завершения блока определения класса.

В этом случае ActiveRecord :: Base определяет методы класса validates_presence_of и belongs_to.

17 голосов
/ 28 августа 2009

У Иегуды Каца есть хорошее объяснение этому в его блоге. См. Пункт 4: Тела класса не являются особенными .

12 голосов
/ 28 августа 2009

Re: Как и когда называются эти методы?

[Они вызываются, когда класс загружается. Вы можете установить точку останова в одном из методов и увидеть, что она вызывается как часть запуска вашего проекта rails.]

Как они определены?

[Это классовые методы. Поскольку это рубин, их можно определить несколькими способами.]

Это миксины, определенные в каком-то активном модуле записи?

[В этом случае

validates_presence_of определено в продавец / Перила / ActiveRecord / Библиотека / active_record / validations.rb

принадлежит_, определено в продавец / Перила / ActiveRecord / Библиотека / active_record / associations.rb

ActiveRecord - это большая система, включающая множество миксинов, модулей и т. Д.

Обратите внимание: чтобы увидеть, где определены методы, я использую http://www.gotapi.com/rubyrails для каждого метода, см. Ссылку «Показать источник» в нижней части определения.

]

11 голосов
/ 28 августа 2009

Это методы класса или «синглтон». Один из них, с которым вы должны быть знакомы, это attr_accessor. Мы можем реализовать что-то подобное в тестовом классе.

class Klass
  def self.add_getter_and_setter(symbol)
    module_eval "def #{symbol}; @#{symbol}; end"
    module_eval "def #{symbol}=(val); @#{symbol} = val; end"
  end
end

class Person < Klass
  add_getter_and_setter :name
  add_getter_and_setter :phone
end

person = Person.new
person.name = 'John Smith'
person.phone = '555-2344'
person # returns <Person:0x28744 @name="John Smith", @phone="555-2344">

В приведенном выше примере мы создали метод класса с помощью 'def self.add_getter_and_setter', но это не единственный способ.

class Klass
  class << self # opens the singleton class
    def add_getter_and_setter(symbol)  # note we dont specify self as it is already within the context of the singleton class
      ..
    end
  end
end

Использование расширения. Модуль # extends - это метод, который расширяет класс методами класса, также как и метод Module # include включает класс с методами экземпляра.

class Klass
  extend(Module.new do
    def add_getter_and_setter(symbol)
      ..
    end
  end)
end

Если Klass уже определен, мы можем открыть его снова, чтобы добавить методы класса

class Klass
end

def Klass.add_getter_and_setter(symbol)
  ..
end

# or 

class << Klass
  def add_getter_and_setter(symbol)
    ..
  end
end

Ну, вот несколько способов, которыми я знаю, как это сделать, поэтому, если вы видите другой синтаксис, просто поймите, что все это делает одно и то же.

Примечание: в rails распространенным методом класса, который мы все используем, является 'find'. Он запускается непосредственно из класса Model.

person = Person.find(1) # finds a person with id:1
3 голосов
/ 28 августа 2009

То, что вы видите, это методы уровня класса для объекта ActiveRecord. Чтобы написать свои собственные методы, которые работают так, вы бы написали их как плагин, а затем включили их в ActiveRecord, заново открыв определение класса. Руководство по созданию плагина в Ruby on Rails:

http://guides.rubyonrails.org/plugins.html

Охватывает, как написать такие методы на уровне плагина / класса. Это хороший документ о том, как понять, что означают эти методы и как они взаимодействуют с экземплярами.

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