Как включить метод экземпляра в обратный вызов before_save в плагине? - PullRequest
2 голосов
/ 29 января 2010

Я создаю плагин и с трудом определяю фильтр before_save, который вызывает метод экземпляра, который я только что определил. Вот быстрый пример:

module ValidatesAndFormatsPhones
  def self.included(base)
    base.send :extend, ClassMethods
  end

  module ClassMethods

    def validates_and_formats_phones(field_names = [:phone])
      send :include, InstanceMethods

      # the following variations on calls to :format_phone_fields fail

      before_save send(:format_phone_fields, field_names)

      before_save format_phone_fields(field_names)

      before_save lambda { send(:format_phone_fields, field_names) }

      # EACH OF THE ABOVE RETURNS 'undefined_method :format_phone_fields'
    end
  end

  module InstanceMethods

    def format_phone_fields(fields = [:phone], *args)
      do stuff...
    end

  end
end

ActiveRecord::Base.send :include, ValidatesAndFormatsPhones

Полагаю, вопрос в том, как мне изменить контекст на экземпляр, а не на класс?

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

Спасибо!

Ответы [ 2 ]

4 голосов
/ 29 января 2010

Включите ваш метод в нужный момент: когда вы расширяете базовый класс:

module ValidatesAndFormatsPhones
  def self.included(base)
    base.send :extend, ClassMethods
    base.send :include, InstanceMethods
  end

  module ClassMethods
    def validates_and_formats_phones(field_names = [:phone])
      before_save {|r| r.format_phone_fields(field_names)}
    end
  end

  module InstanceMethods
    def format_phone_fields(fields = [:phone], *args)
      # do stuff...
    end
  end
end

ActiveRecord::Base.send :include, ValidatesAndFormatsPhones

Я не запускал код, но он должен работать. Я делал подобные вещи достаточно часто.

2 голосов
/ 29 января 2010

поскольку вы используете макросы обратного вызова, вы можете передать символ только для метода, который хотите запустить, передача аргументов невозможна. «Обходной путь» из документации по rails - использовать «строку метода», которая оценивается в правильном контексте:

before_save 'self.format_phone_fields(....)'

другая возможность: сохранить имена полей как переменные класса и получить доступ к ним в вашем экземпляре, затем вы можете использовать before_save: format_phone_fields

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