Увеличивая модель от внешнего драгоценного камня
-
26-09-2019 - |
Вопрос
я использую 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
код.
Надеюсь это поможет