Использование рельсов с именами routes и помощников url / view в настраиваемых шаблонах ERB

Мне нужна была помощь по включению и расширению модулей и классов Ruby.

Мой предыдущий вопрос касался именованных маршрутов, но не всех помощников представлений / тегов из-за хэша default_url_options. Проблема здесь в том, что методы ActionController :: UrlWriter, такие как url_for, вызывают атрибут класса default_url_options. Таким образом, при включении ActionController :: UrlWriter он расширяет синглтон текущего класса, но также должен расширять сам текущий класс. Если вы посмотрите на мой код ниже, MyBigClass должен иметь default_url_options в своем классе, а не в экземпляре. Это работает, но я не уверен, правильно ли это или потенциально что-то сломается.

Вот мой текущий модуль:

module MessageViewHelper
  module Methods
    def self.included(base)
        base.module_eval do
          include TemplatesHelper
          include LegacyUrlsHelper
          include ActionView::Helpers::TagHelper
          include ActionView::Helpers::AssetTagHelper
          include ActionView::Helpers::UrlHelper
          include ActionController::UrlWriter
        end

        MyBigClass.class_eval do
          cattr_accessor :default_url_options

          def self.default_url_options(options = {})
            options.merge({:host=>'www.myhostname.com'})
          end
        end

      unless ActionController::UrlWriter.method_defined?('old_url_for')
        ActionController::UrlWriter.class_eval do
          alias_method :old_url_for, :url_for
          def url_for(options)
            if options.is_a?(String)
              options
            else
              old_url_for(options)
            end
          end
        end
      end # unless method_defined?
    end
  end
end


class MyBigClass < ActiveRecord::Base
  def message(template_name)
    class << self; include MessageViewHelper::Methods; end
    # ... more stuff here
  end
end

Я знаю, что не совсем понимаю дизайн и расширения классов / модулей ruby. Кто-нибудь знает об этом? Следует ли отменить изменения MyBigClass в конце message?


person johnml    schedule 30.10.2009    source источник


Ответы (2)


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

person Azeem.Butt    schedule 30.10.2009

MyBigClass.class_eval do
  cattr_accessor :default_url_options

  def self.default_url_options(options = {})
     options.merge({:host=>'www.myhostname.com'})
   end
 end

Обычно class_eval определяет обычные методы экземпляра в классе.

Но в этом случае внутри блока class_eval вы определяете метод для себя. self внутри блока - это MyBigClass, поэтому он фактически создаст метод в одноэлементном классе MyBigClass. Любой метод в одноэлементном классе не является методом экземпляра.

person andHapp    schedule 30.10.2009