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?

Foi útil?

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

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top