web-dev-qa-db-ja.com

アプリケーションレイアウト内でエンジンをレンダリングする

バックグラウンド

コアといくつかのモジュールで構成されるアプリケーションを作成しています。モジュールはRailsエンジンであり、コア自体がホストとしてのみ機能するため、実際の機能を提供します。エンジンは/libからホストされ、それぞれのパスにマウントされます。

coreApp
└──lib
   ├── module1
   ├── module2
   └── etc

次に、モジュールは次のようにマウントされます

mount Module1::Engine => "/module1", :as => "module1"
mount Module2::Engine => "/module2", :as => "module2"

ログイン自体はモジュールによって実行されますが、コアはセッションの処理も担当します。

問題

コアアプリケーションのレイアウトをエンジンと共有するための優れた方法をまだ見つけていません。今のところ、これは私がレイアウトをエンジンで利用できるようにする方法です:

coreApp
└── app
    └── views
        └── layouts
            ├── application.html.erb
            └── core.html.erb

ファイルcore.html.erbには

<%= render :template => 'layouts/application' %>

このように各モジュールに含まれています

module Module1
  class ApplicationController < ActionController::Base
    layout "core"
  end
end

特にエレガントではありませんが、正常に機能し、モジュールのコンテンツは、アプリケーションレイアウトのyieldステートメントの場所にレンダリングされます。

問題は次のとおりです。

1.モジュール固有のスタイルシートはヘッダーに含まれていません

アクティブなモジュールのスタイルシートを含める方法が必要です。

2.ヘッダーは、ログインしたユーザーに関する情報にアクセスする必要があります

ヘッダーには、次のようなログインユーザーに関する情報が含まれています。

Logged in as <%= @user[:realname] %>

これはコアから来ていますhome_controller

def index
  @user = User.find_by_id(session[:user])
end

しかし、モジュールにアクセスしようとすると、次のエラーが発生します

NoMethodError in Module1/home#index

You have a nil object when you didn't expect it!
You might have expected an instance of Array.
The error occurred while evaluating nil.[]

明らかに@userを参照しています。

質問

エンジン側をあまり改ざんすることなく、これを可能な限りエレガントにDRY)で解決するにはどうすればよいでしょうか。

私はこれをグーグルで検索しましたたくさんしかしそれを解決する方法について頭を悩ませることはできません。 Railsがどのように機能するかについての洞察がまったくない可能性があるため、Railsをよく知っている人にとって、この質問が意味をなさない可能性があります。 。

不明な点やあいまいな点があればコメントしてください。詳しく説明します。

30
Jørgen R

使用する layout 'layouts/application'

また、main_app.your_pathを使用したくない場合は、次を追加することもできます。

module YourEngine
  module ApplicationHelper
    def method_missing(method, *args, &block)
      if (method.to_s.end_with?('_path') || method.to_s.end_with?('_url')) && main_app.respond_to?(method)
        main_app.send(method, *args)
      else
        super
      end
    end
  end
end
17
montrealmike

私も自分のアプリケーションで同じことをしました。私がしたのは:

  1. / app/view/layouts /のエンジンレイアウトを削除します
  2. Application_controllerをに変更します

    module EngineModule
      class ApplicationController < ::ApplicationController
        layout 'layouts/application' 
      end
    end
    
  3. あなたの見解では、login_pathなどのパスを参照する場合は、main_app.login_pathを介して参照できます。

6
ShadyKiller