Aumentando um modelo de uma jóia externa
-
26-09-2019 - |
Pergunta
estou a usar Refinarias Em nosso site, para permitir que o menos técnico atualizasse o conteúdo. Dentro da gema, eles têm uma classe de página que mapeia cada página de nível superior no site. Eu gostaria de usar o ACTS_AS_TAGGABLE GEM Nesta classe de página. Agora, posso adicionar a declaração Atos_as_taggle diretamente ao arquivo Page.rb, mas então eu precisaria manter um repositório Git separado para rastrear as diferenças entre minha versão e a versão oficial.
Com base em outras perguntas aqui, então eu criei um inicializador e uma extensão como assim:
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
config/inicializadores/calças.rb
require 'page_extensions'
Page.send :include, Pants::Extensions::Page
App/Views/Layouts/Application.html.erb
...
Tags: <%= @page.tag_list %>
A primeira vez que solicito uma página do servidor, ele produz corretamente todas as tags na página. No entanto, se eu atingir a atualização, eu recebo um NoMethodError
indicando que o tag_list está indefinido.
Eu sou novo no Rails, então talvez minhas suposições estejam erradas, mas eu esperava que a chamada para Page.send faria uma alteração permanente na classe da página, e não em uma instância específica da classe. Então, como eu obteria o Atos_as_taggable adicionado à classe Page em cada solicitação?
Solução
Você precisará colocar seu código Module_eval em um config.to_prepare do
quadra. O lugar mais fácil para fazer isso é config/application.rb
ou para criar um motor. O código é idêntico, exceto que ele é executado toda vez que você executa o site não apenas a primeira vez (que se aplica especialmente ao modo de desenvolvimento) e o código que é executado apenas antes do processo de inicialização (também conhecido como arquivos) em um config.before_initialize do
quadra.
A razão disso config.to_prepare
É importante porque, no modo de desenvolvimento, o código é recarregado em todas as solicitações, mas os inicializadores geralmente não são. Isso significa que Page
, em que você está executando um Module_eval, só terá o Module_Eval Run uma vez, mas recarregará todas as solicitações. config.to_prepare
é um gancho de trilhos que corre toda vez, proporcionando grande conveniência para situações como essa.
Abordagem 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
Abordagem do motor
Se você não quiser modificar config/application.rb
Então você pode, no CMS da refinaria, criar vendor/engines/add_page_extensions/lib/add_page_extensions.rb
o que seria assim:
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
Se você usar a abordagem dos motores, você também precisará criar vendor/engines/add_page_extensions/add_page_extensions.gemspec
que deve conter um gemSpec simples:
Gem::Specification.new do |s|
s.name = 'add_page_extensions'
s.require_paths = %w(lib)
s.version = 1.0
s.files = Dir["lib/**/*"]
end
E então em seu Gemfile
Adicione esta linha:
gem 'add_page_extensions', :path => 'vendor/engines'
Se você for a abordagem do motor, provavelmente desejará colocar toda a sua lógica dentro do motor lib
diretório, incluindo o Pants::Extensions::Page
código.
Espero que isto ajude