Увеличивая модель от внешнего драгоценного камня

StackOverflow https://stackoverflow.com/questions/4018701

Вопрос

я использую RefineryCms. На нашем сайте, чтобы позволить менее техническому обновлению персонала. Внутри GEM у них есть класс страницы, который отображает каждую страницу верхнего уровня на сайте. Я хотел бы использовать GEM ACTS_AS_TAGBALE на этой классе страницы. Теперь я могу добавить декларацию ACTS_AS_TAGGLE непосредственно к файлу Page.rb, но тогда мне придется поддерживать отдельный репо Git для отслеживания различий между моей версией и официальным выпуском.

Основываясь на некоторых других вопросах здесь, поэтому я создал инициализатор и расширение, как так:

lib / page_extensions.rb:

module Pants
  module Extensions

    module Page
      module ClassMethods
        def add_taggable
          acts_as_taggable
        end
      end

      def self.included(base)
        base.extend(ClassMethods).add_taggable
      end

    end

  end
end

Конфигурация / Инициализаторы / штаны.

require 'page_extensions'

Page.send :include, Pants::Extensions::Page

Приложение / Просмотры / Макеты / Application.html.erb

...
Tags: <%= @page.tag_list %>

Первый раз, когда я прошу страницу с сервера, он правильно выводит все теги на странице. Однако, если я ударю обновление, я вместо этого получаю NoMethodError Указывает на то, что tag_list не определен.

Я новичок в рельсах, так что, возможно, мои предположения не являются неправильными, но я ожидал, что звонок на страницу. Предыдущий сделает постоянное изменение в классе страницы, а не для конкретного случая класса. Итак, как бы я получил acts_as_taggable добавленным к классу страницы по каждому запросу?

Это было полезно?

Решение

Вам нужно будет поставить свой код Module_eval в config.to_prepare do блокировать. Самое простое место для этого в config/application.rb или создать двигатель. Код идентичен, за исключением того, что он выполняет каждый раз, когда вы запускаете сайт не только в первый раз (который особенно относится к режиму разработки) и кода, который выполняет только до процесса инициализации (AKA, требующий файлов) в config.before_initialize do блокировать.

Причина этого config.to_prepare Важно, потому что в режиме разработки код перезаряжен на каждом запросе, но инициализаторы обычно не являются. Это означает, что Page, который вы используете Module_eval включен, только когда-то запустится Module_eval, но перезагрузится каждый запрос. config.to_prepare Является ли рельсы крючком, который проходит каждый вариант, обеспечивающий отличное удобство для таких ситуаций.

Подход Config / application.rb

class Application < Rails::Application
  # ... other stuff ...

  config.before_initialize do
    require 'page_extensions'
  end

  config.to_prepare do
    Page.send :include, Pants::Extensions::Page
  end
end

Подход двигателя

Если вы не хотите изменять config/application.rb Тогда вы можете, в НПЗ CMS, создать vendor/engines/add_page_extensions/lib/add_page_extensions.rb который бы выглядел так:

require 'refinery'

module Refinery
  module AddPageExtensions
    class Engine < Rails::Engine

      config.before_initialize do
        require 'page_extensions'
      end

      config.to_prepare do
        Page.send :include, Pants::Extensions::Page
      end

    end
  end
end

Если вы используете подход к двигателям, вам также нужно будет создать vendor/engines/add_page_extensions/add_page_extensions.gemspec который должен содержать простые Gemspec:

Gem::Specification.new do |s|
  s.name = 'add_page_extensions'
  s.require_paths = %w(lib)
  s.version = 1.0
  s.files = Dir["lib/**/*"]
end

А потом в вашем Gemfile Добавить эту строку:

gem 'add_page_extensions', :path => 'vendor/engines'

Если вы идете подход двигателя, вы, вероятно, захотите поставить всю свою логику внутри двигателя lib каталог, включая то Pants::Extensions::Page код.

Надеюсь это поможет

Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top