2 つまたは 3 つの主要な「セクション」を持つ Ruby/Rails アプリがあります。ユーザーがそのセクションにアクセスしたときに、サブナビゲーションを表示したいと考えています。3 つのセクションはすべて同じレイアウトを使用しているため、ナビゲーションをレイアウトに「ハード コード」することはできません。
これを行うには、いくつかの異なる方法を考えることができます。人々が投票するのを助けるために、私はそれらを答えとして入れます。
他のアイデアはありますか?または何に投票しますか?
2 つまたは 3 つの主要な「セクション」を持つ Ruby/Rails アプリがあります。ユーザーがそのセクションにアクセスしたときに、サブナビゲーションを表示したいと考えています。3 つのセクションはすべて同じレイアウトを使用しているため、ナビゲーションをレイアウトに「ハード コード」することはできません。
これを行うには、いくつかの異なる方法を考えることができます。人々が投票するのを助けるために、私はそれらを答えとして入れます。
他のアイデアはありますか?または何に投票しますか?
各セクションに独自のコントローラーがあると仮定すると、パーシャルを使用してこれを簡単に行うことができます。
Posts、Users、Adminという 3 つのセクションがあり、それぞれに独自のコントローラーPostsController
があるUsersController
としAdminController
ます。
対応する各ディレクトリで、パーシャルviews
を宣言します。_subnav.html.erb
/app/views/users/_subnav.html.erb /app/views/posts/_subnav.html.erb /app/views/admin/_subnav.html.erb
これらの subnav パーシャルのそれぞれで、そのセクションに固有のオプションを宣言するため、/users/_subnav.html.erb
以下が含まれる場合があります。
<ul id="subnav">
<li><%= link_to 'All Users', users_path %></li>
<li><%= link_to 'New User', new_user_path %></li>
</ul>
含まれている/posts/_subnav.html.erb
可能性がありますが:
<ul id="subnav">
<li><%= link_to 'All Posts', posts_path %></li>
<li><%= link_to 'New Post', new_post_path %></li>
</ul>
最後に、これを行ったら、subnav パーシャルをレイアウトに含めるだけです。
<div id="header">...</div>
<%= render :partial => "subnav" %>
<div id="content"><%= yield %></div>
<div id="footer">...</div>
サブメニューの内容については、各コントローラーで宣言的に行うことができます。
class PostsController < ApplicationController
#...
protected
helper_method :menu_items
def menu_items
[
['Submenu 1', url_for(me)],
['Submenu 2', url_for(you)]
]
end
end
これで、ビューから menu_items を呼び出すたびに、特定のコントローラーに対して反復する正しいリストが得られます。
これは、このロジックをビュー テンプレート内に配置するよりもクリーンなソリューションだと思います。
ApplicationController 内でもデフォルト (空?) の menu_items を宣言したい場合があることに注意してください。
警告: 高度なトリックが先にあります!
それらをすべてレンダリングします。CSS/Javascript を使用して必要のないものを非表示にします。CSS/Javascript は、さまざまな方法で簡単に初期化できます。(Javascript は、使用される URL、クエリ パラメータ、Cookie 内の何かなどを読み取ることができます。) これには、潜在的にキャッシュをより適切に処理できるという利点があります (なぜ 3 つのビューをキャッシュし、1 つをキャッシュできるのに、それらすべてを同時に失効させる必要があるのか)。 ?)、より良いユーザー エクスペリエンスを提供するために使用できます。
たとえば、サブ ナビゲーションを備えた一般的なタブ バー インターフェイスがあるとします。3 つのタブすべてのコンテンツを表示し (つまり、HTML で記述)、そのうちの 2 つを非表示にすると、2 つのタブ間の切り替えは簡単な Javascript であり、サーバーにヒットすることさえありません。大勝利!ユーザーの待ち時間はありません。サーバーの負荷はありません。
別の大きな勝利をしたいですか?この手法のバリエーションを使用して、ユーザー間で 99% は共通であるがユーザー状態を含むページをごまかすことができます。たとえば、すべてのユーザーに比較的共通しているサイトのフロント ページがあり、ログイン時に「こんにちは、ボブ」と言う場合があります。一般的でない部分 (「こんにちは、ボブ」) を Cookie に入れます。Cookie を読み取る Javascript を介して、ページのその部分を読み込むようにします。 ページ キャッシュでは、ログイン ステータスに関係なく、すべてのユーザーのページ全体をキャッシュします。 これにより、文字通り、一部のサイトで Rails スタック全体からアクセスの 70% を切り捨てることができます。
あなたのサイトが実際に Nginx で静的アセットを提供している場合、Rails がスケーリングできるかどうかは誰が気にしますか ;)
私自身もほぼ同じ質問をしました。アドバイスが必要です:サブメニューのRailsビューの構造?最善の解決策は、おそらくパーシャルを使用することでした。
これを行う別の可能な方法があります:ネストされたレイアウト
このコードをどこで見つけたか覚えていないので、元の作者に謝罪します。
libフォルダーにnested_layouts.rbというファイルを作成し、次のコードを含めます。
module NestedLayouts
def render(options = nil, &block)
if options
if options[:layout].is_a?(Array)
layouts = options.delete(:layout)
options[:layout] = layouts.pop
inner_layout = layouts.shift
options[:text] = layouts.inject(render_to_string(options.merge({:layout=>inner_layout}))) do |output,layout|
render_to_string(options.merge({:text => output, :layout => layout}))
end
end
end
super
end
end
次に、layoutsフォルダーにさまざまなレイアウトを作成します(たとえば、「admin.rhtml」や「application.rhtml」)。
次に、コントローラーでこれをクラス内に追加します。
include NestedLayouts
そして最後に、アクションの最後にこれを行います。
def show
...
render :layout => ['admin','application']
end
配列内のレイアウトの順序は重要です。管理者レイアウトは、「yeild」がどこにあっても、アプリケーションレイアウト内にレンダリングされます。
この方法は、サイトのデザインやさまざまな要素の編成方法によっては、非常にうまく機能します。たとえば、含まれているレイアウトの1つに、特定のアクションで表示する必要のあるコンテンツを含む一連のdivを含めることができ、上位のレイアウトのCSSで配置場所を制御できます。
http://rpheath.com/posts/309-rails-plugin-navigation-helperのナビゲーション プラグインのようなものを使用できます。
すぐに使用できるサブセクション ナビゲーションはありませんが、少し調整するだけで、おそらく同様の操作を行うように設定できます。
パーシャルを使用することをお勧めします。いくつかの方法があります。特定の変数を必要とするという点で少しうるさいパーシャルを作成するときは、そのためのヘルパー メソッドも作成します。
module RenderHelper
#options: a nested array of menu names and their corresponding url
def render_submenu(menu_items=[[]])
render :partial => 'shared/submenu', :locals => {:menu_items => menu_items}
end
end
パーシャルには menu_items という名前のローカル変数があり、これを反復処理してサブメニューを作成できます。ハッシュの順序は予測できないため、ハッシュの代わりにネストされた配列を提案することに注意してください。
メニューにどのアイテムを表示するかを決定するロジックは、render_submenu 内にある場合もあることに注意してください。
この問題へのアプローチはほとんどありません。
セクションごとに異なるレイアウトを使用したい場合があります。
特定のディレクトリ内のすべてのビューに含まれるパーシャルを使用したい場合があります。
content_for
ビューまたはパーシャルのいずれかで埋められ、グローバル レイアウトがある場合はそれを使用したい場合があります。
個人的には、この場合は抽象化を避けるべきだと思います。