外部宝石からモデルの拡張
-
26-09-2019 - |
質問
私はあまり技術スタッフの更新内容をできるように私たちのサイトに refinerycms を使用しています。宝石の中に、彼らは、サイト上の各トップレベルのページをマップPageクラスを持っています。私は、このページクラスにacts_as_taggable宝石を使用したいと思います。今私はpage.rbファイルに直接acts_as_taggle宣言を追加することができますが、その後、私は私のバージョンと公式リリースの違いを追跡するために、別々のGitのレポを維持する必要があると思います。
はここSO I上のいくつかの他の質問に基づいて、そのように初期化子と拡張子を作成しました
の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
設定/初期化子/ pants.rb
require 'page_extensions'
Page.send :include, Pants::Extensions::Page
アプリ/ビュー/レイアウト/ application.html.erb
...
Tags: <%= @page.tag_list %>
最初の時間は、私はそれが正しくページ上のすべてのタグを出力し、サーバーからページを要求します。私はリフレッシュヒットした場合しかし、私の代わりにtag_listが定義されていないことを示すNoMethodError
を取得します。
私はレールに新たなんだので、おそらく私の仮定が間違っているが、私はPage.sendへの呼び出しはPageクラスにではなく、クラスの特定のインスタンスへの永続的な変更を加えると期待されます。だから、どのように私は要求ごとにページクラスに追加acts_as_taggableになるだろう?
解決
あなたはconfig.to_prepare do
ブロックにあなたのmodule_evalコードを配置する必要があります。これを行うための最も簡単な場所はconfig/application.rb
であるか、エンジンを作成します。コード、それはあなたが唯一のconfig.before_initialize do
ブロックに(ファイルが必要な別名)初期化プロセスの前に実行されるサイトだけでなく、初めて(特に開発モードに適用されている)とのコードを実行するたびに実行を除いて同じです。
config.to_prepare
が重要である理由です。あなたが上module_evalを実行しているPage
は、一度だけmodule_eval実行を持っていますが、すべての要求自体をリロードすることをこれが意味。 config.to_prepare
は、このような状況のために大きな利便性を提供する一つ一つの時間を実行しているRailsのフックです。
の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
エンジンアプローチ
あなたがconfig/application.rb
を変更したくない場合は、製油所CMSで、次のようになりvendor/engines/add_page_extensions/lib/add_page_extensions.rb
を作成することができます:
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
:あなたがエンジンを使用する場合は、あなたは、単純なgemspecが含まれている必要がありvendor/engines/add_page_extensions/add_page_extensions.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
そして、あなたのGemfile
にこの行を追加します:
gem 'add_page_extensions', :path => 'vendor/engines'
あなたはエンジンのアプローチを行っている場合、あなたはおそらくlib
コードを含むエンジンのPants::Extensions::Page
ディレクトリ内にあなたのロジックのすべてを置くことになるでしょう。
ホープ、このことができます。