6

私たちのサイトでは、技術力の低いスタッフがコンテンツを更新できるように、refinerycmsを使用しています。gem 内には、サイトの各トップ レベル ページをマップする Page クラスがあります。この Page クラスで act_as_taggable gem を使用したいと思います。これで、acts_as_taggle 宣言を page.rb ファイルに直接追加できますが、その場合、自分のバージョンと公式リリースの違いを追跡するために別の git リポジトリを維持する必要があります。

SOに関する他のいくつかの質問に基づいて、次のような初期化子と拡張機能を作成しました。

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

アプリ/ビュー/レイアウト/application.html.erb

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

サーバーからページを初めてリクエストすると、ページ上のすべてのタグが正しく出力されます。ただし、更新を押すと、代わりにNoMethodErrortag_list が未定義であることを示すメッセージが表示されます。

私はレールに慣れていないので、おそらく私の仮定は間違っていますが、 Page.send への呼び出しは、クラスの特定のインスタンスではなく Page クラスに永続的な変更を加えると予想していました。では、リクエストごとにacts_as_taggableをPageクラスに追加するにはどうすればよいでしょうか?

4

1 に答える 1

14

config.to_prepare domodule_eval コードをブロックに入れる必要があります。これを行う最も簡単な場所は、エンジン内config/application.rbまたはエンジンを作成することです。コードは、最初だけでなくサイトを実行するたびに実行されること(特に開発モードに適用される)と、config.before_initialize doブロックへの初期化プロセス(別名ファイルを必要とする)の前にのみ実行されるコードを除いて同じです。

重要な理由config.to_prepareは、開発モードではすべてのリクエストでコードがリロードされますが、初期化子は通常そうではないためです。つまりPage、module_eval を実行している では、module_eval が 1 回だけ実行されますが、リクエストごとに再ロードされます。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は、Refinery 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

エンジン アプローチを使用する場合vendor/engines/add_page_extensions/add_page_extensions.gemspecは、シンプルな 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ます。

お役に立てれば

于 2010-10-25T21:36:27.403 に答える