Question

J'utilise refinerycms sur notre site pour laisser le contenu moins de mise à jour du personnel technique. A l'intérieur du bijou, ils ont une classe page qui mappe chaque page de niveau supérieur sur le site. Je voudrais utiliser la pierre précieuse acts_as_taggable sur cette classe page. Maintenant, je peux ajouter la déclaration acts_as_taggle directement au fichier page.rb, mais je dois maintenir un git distinct pour suivre les différences entre ma version et la version officielle.

Sur la base d'autres questions ici sur le SO j'ai créé un initialiseur et l'extension comme ceci:

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 / initializers / pants.rb

require 'page_extensions'

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

app / views / layouts / application.html.erb

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

La première fois que je demande une page du serveur il affiche correctement toutes les balises sur la page. Cependant, si j'actualisez je hériterez d'une NoMethodError indiquant que liste_balise est indéfini.

Je suis nouveau sur les rails alors peut-être mes suppositions sont fausses, mais je m'y attendais appel à Page.send ferait un changement permanent à la classe page plutôt que d'une instance spécifique de la classe. Alors, comment pourrais-je obtenir la acts_as_taggable ajoutée à la classe la page sur chaque demande?

Était-ce utile?

La solution

Vous aurez besoin de mettre votre code module_eval dans un bloc de config.to_prepare do. Le endroit le plus facile de le faire est en config/application.rb ou pour créer un moteur. Le code est identique sauf qu'il exécute chaque fois que vous exécutez le site non seulement la première fois (ce qui vaut en particulier pour le mode de développement) et le code qui exécute seulement avant que le processus d'initialisation (alias nécessitant des fichiers) dans un bloc config.before_initialize do.

La raison pour laquelle config.to_prepare est important parce que dans le mode de développement, le code est rechargé à chaque demande, mais initializers ne sont généralement pas. Cela signifie que Page, que vous exécutez un module_eval sur, n'aura la course module_eval une fois, mais va se recharger chaque demande. config.to_prepare est un crochet Rails qui fonctionne à chaque fois offrant un grand confort pour des situations comme celle-ci.

approche 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

approche moteur

Si vous ne voulez pas modifier config/application.rb alors vous pouvez, dans la raffinerie de CMS, créer vendor/engines/add_page_extensions/lib/add_page_extensions.rb qui ressemblerait à ceci:

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

Si vous utilisez les moteurs l'approche que vous aurez besoin aussi de créer vendor/engines/add_page_extensions/add_page_extensions.gemspec qui devrait contenir simple 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

Et puis dans votre Gemfile ajouter cette ligne:

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

Si vous allez l'approche du moteur, vous voudrez probablement mettre tout votre logique à l'intérieur du répertoire lib du moteur, y compris le code Pants::Extensions::Page.

Hope this helps

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top