Augmentierenden ein Modell von einem externen gem
-
26-09-2019 - |
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?
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