Frage

Ich bin mit refinerycms in unserer Website, die weniger technischen Personal Aktualisierung von Inhalten zu lassen. Im Innern des Edelsteins, haben sie eine Page-Klasse, die jede Top-Level-Seite auf der Website abbildet. Ich mag das acts_as_taggable Juwel auf dieser Seite Klasse. Jetzt kann ich die acts_as_taggle Erklärung direkt an die page.rb Datei hinzufügen, aber dann müsste ich einen separaten git Repo pflegen Unterschiede zwischen meiner Version und der offiziellen Veröffentlichung zu verfolgen.

Basierend auf einigen anderen Fragen hier auf SO Ich habe einen initializer und Erweiterung wie folgt:

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 / layout / application.html.erb

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

Das erste Mal, dass ich eine Seite vom Server anfordern gibt sie korrekt alle Tags auf der Seite. Allerdings, wenn ich refresh schlagen stattdessen erhalte ich eine NoMethodError darauf hinweist, dass tag_list nicht definiert ist.

Ich bin neu auf Schienen so vielleicht sind meine Annahmen falsch, aber ich erwartete, dass Anruf Page.send würde eine dauerhafte Veränderung Klasse auf der Seite machen, anstatt auf eine bestimmte Instanz der Klasse. Also, wie würde ich die acts_as_taggable auf die Page-Klasse auf jede Anfrage erhalten hinzugefügt?

War es hilfreich?

Lösung

Sie müssen Ihren module_eval Code in einen config.to_prepare do Block setzen. Der einfachste Ort, dies zu tun, ist in config/application.rb oder einen Motor zu schaffen. Der Code ist identisch, außer es jedes Mal, führt Sie die Website nicht nur das erste Mal laufen (die in dem Entwicklungsmodus gilt vor allem) und Code, der ausführt, nur vor dem Initialisierungsprozess (aka erfordern Dateien) in einen config.before_initialize do Block.

Der Grund, dass config.to_prepare wichtig ist, weil im Entwicklungsmodus, der Code bei jeder Anfrage neu geladen wird, aber initializers ist in der Regel nicht. Dies bedeutet, dass Page, die Sie auf einen module_eval ausführen, wird nur einmal die module_eval laufen, sondern wird sich jede Anfrage neu zu laden. config.to_prepare ist ein Rails Haken, der jedes Mal bietet große Bequemlichkeit für Situationen wie diese ausgeführt wird.

config / application.rb Ansatz

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

Motor Ansatz

Wenn Sie nicht config/application.rb ändern möchten, dann können Sie, in Refinery CMS, schaffen vendor/engines/add_page_extensions/lib/add_page_extensions.rb, die wie folgt aussehen:

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

Wenn Sie die Motoren verwenden nähern Sie auch vendor/engines/add_page_extensions/add_page_extensions.gemspec müssen schaffen, die eine einfache gemspec enthalten sollte:

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

Und dann in Ihrem Gemfile diese Zeile hinzufügen:

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

Wenn Sie den Motor Ansatz gehen, werden Sie wahrscheinlich wollen alle Ihre Logik innerhalb des Motors lib Verzeichnis setzen, einschließlich der Pants::Extensions::Page Code.

Hope, das hilft

Lizenziert unter: CC-BY-SA mit Zuschreibung
Nicht verbunden mit StackOverflow
scroll top