12

2 つまたは 3 つの主要な「セクション」を持つ Ruby/Rails アプリがあります。ユーザーがそのセクションにアクセスしたときに、サブナビゲーションを表示したいと考えています。3 つのセクションはすべて同じレイアウトを使用しているため、ナビゲーションをレイアウトに「ハード コード」することはできません。

これを行うには、いくつかの異なる方法を考えることができます。人々が投票するのを助けるために、私はそれらを答えとして入れます。

他のアイデアはありますか?または何に投票しますか?

4

9 に答える 9

9

各セクションに独自のコントローラーがあると仮定すると、パーシャルを使用してこれを簡単に行うことができます。

PostsUsersAdminという 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>
于 2008-10-01T13:01:46.767 に答える
7

サブメニューの内容については、各コントローラーで宣言的に行うことができます。

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 を宣言したい場合があることに注意してください。

于 2008-09-30T00:32:49.417 に答える
7
  1. 部分的なレンダリング。これはヘルパー メソッドと非常によく似ていますが、おそらくレイアウトに if ステートメントが含まれるか、それをヘルパーに渡します...
于 2008-09-29T22:46:28.827 に答える
3

警告: 高度なトリックが先にあります!

それらをすべてレンダリングします。CSS/Javascript を使用して必要のないものを非表示にします。CSS/Javascript は、さまざまな方法で簡単に初期化できます。(Javascript は、使用される URL、クエリ パラメータ、Cookie 内の何かなどを読み取ることができます。) これには、潜在的にキャッシュをより適切に処理できるという利点があります (なぜ 3 つのビューをキャッシュし、1 つをキャッシュできるのに、それらすべてを同時に失効させる必要があるのか​​)。 ?)、より良いユーザー エクスペリエンスを提供するために使用できます。

たとえば、サブ ナビゲーションを備えた一般的なタブ バー インターフェイスがあるとします。3 つのタブすべてのコンテンツを表示し (つまり、HTML で記述)、そのうちの 2 つを非表示にすると、2 つのタブ間の切り替えは簡単な Javascript であり、サーバーにヒットすることさえありません。大勝利!ユーザーの待ち時間はありません。サーバーの負荷はありません。

別の大きな勝利をしたいですか?この手法のバリエーションを使用して、ユーザー間で 99% は共通であるがユーザー状態を含むページをごまかすことができます。たとえば、すべてのユーザーに比較的共通しているサイトのフロント ページがあり、ログイン時に「こんにちは、ボブ」と言う場合があります。一般的でない部分 (「こんにちは、ボブ」) を Cookie に入れます。Cookie を読み取る Javascript を介して、ページのその部分を読み込むようにします。 ページ キャッシュでは、ログイン ステータスに関係なく、すべてのユーザーのページ全体をキャッシュします。 これにより、文字通り、一部のサイトで Rails スタック全体からアクセスの 70% を切り捨てることができます。

あなたのサイトが実際に Nginx で静的アセットを提供している場合、Rails がスケーリングできるかどうかは誰が気にしますか ;)

于 2008-09-30T08:12:52.710 に答える
1

私自身もほぼ同じ質問をしました。アドバイスが必要です:サブメニューのRailsビューの構造?最善の解決策は、おそらくパーシャルを使用することでした。

于 2008-10-01T10:16:05.027 に答える
1

これを行う別の可能な方法があります:ネストされたレイアウト

このコードをどこで見つけたか覚えていないので、元の作者に謝罪します。

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で配置場所を制御できます。

于 2008-10-01T12:45:21.330 に答える
1

http://rpheath.com/posts/309-rails-plugin-navigation-helperのナビゲーション プラグインのようなものを使用できます。

すぐに使用できるサブセクション ナビゲーションはありませんが、少し調整するだけで、おそらく同様の操作を行うように設定できます。

于 2008-09-30T00:06:22.787 に答える
1

パーシャルを使用することをお勧めします。いくつかの方法があります。特定の変数を必要とするという点で少しうるさいパーシャルを作成するときは、そのためのヘルパー メソッドも作成します。

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 内にある場合もあることに注意してください。

于 2008-09-30T00:23:12.497 に答える
0

この問題へのアプローチはほとんどありません。

セクションごとに異なるレイアウトを使用したい場合があります。

特定のディレクトリ内のすべてのビューに含まれるパーシャルを使用したい場合があります。

content_forビューまたはパーシャルのいずれかで埋められ、グローバル レイアウトがある場合はそれを使用したい場合があります。

個人的には、この場合は抽象化を避けるべきだと思います。

于 2008-12-26T20:08:07.897 に答える