2

やや深くネストされた階層のビューを表示するRailsの方法は何ですか?簡単な質問のように思えますが、私に耐えようとすると、誰かが私の混乱を理解する(そしてうまくいけば解決する)かもしれません。

私のアプリはある種の単純な階層です(この議論の目的のためにもっと単純化されています):

  • 上部にドキュメントのインデックスがあります
  • いずれかをクリックすると、その章のリスト(インデックス)を含むドキュメントの詳細が表示されます。
  • そのリストからチャプターをクリックして、前と次のリンクのあるページと、現在のチャプターが強調表示された余白にある同様のチャプターのリストを取得します。

十分に単純ですが、私の質問は、次の方法を実行する方法です。

  1. リソースが深くなりすぎないように、リソースをネストしますか?
  2. ビューを構成しますか?

一見基本的なことを尋ねる理由は、最初のクリックから、「ドキュメント」(document#show)だけでなく、それに含まれるチャプター(chapters#index)も表示しているためです。では、2つのうちどちらにビューを作成する必要がありますか?

チャプターの冒頭を見ている次のクリックと同じです。それはchapters#showまたはpages#indexアクションである可能性があります。とはいえ、おそらくそれはによっても処理できる(そしておそらくそうすべきである)と思いますpages#show

考え?私は物事を考えすぎていますか?(おそらく)

4

2 に答える 2

4

ルート

次のようにルートを設定して、Rails の組み込みのネストされたリソースを利用できます。

resources :documents, :only => [:index, :show] do
  resources :chapters, :only => :show do
    resources :pages, :only => :show
  end
end

これは、次のカスタム ルートの設定とほぼ同じです。

get '/documents' => 'documents#index',
    :as => 'documents'
get '/documents/:id' => 'documents#show',
    :as => 'document'
get '/documents/:document_id/chapters/:id' => 'chapters#show',
    :as => 'document_chapter'
get '/documents/:document_id/chapters/:chapter_id/pages/:id' => 'pages#show',
    :as => 'document_chapter_page'

URL が思っていたよりも少し長くて扱いにくい場合、またはカスタム パラメーターを使用したい場合 (たとえば、ID ではなく番号でページを識別する場合) は、いつでも代わりにカスタム ルートを記述できます。

resources :documents, :only => [:index, :show]
get '/documents/:document_id/:id' => 'chapters#show',
    :as => 'document_chapter'
get '/documents/:document_id/:chapter_id/:page' => 'pages#show',
    :as => 'document_chapter_page'

詳細については、ルーティング ガイドを参照してください。

コントローラー

ユーザーが章に直接アクセスできるようにするのではなく、章の最初のページを表示する必要があります。ただし、章の URL がページ番号なしで機能することは間違いなく便利です (特に、ページ番号が章内の位置ではなくドキュメント内の位置を参照する場合)。

showしたがって、章コントローラーのアクションから最初のページにリダイレクトできます。

class ChaptersController < ApplicationController
  def show
    chapter = Chapter.find(params[:id])
    redirect_to [chapter.document, chapter, chapter.pages.first]
  end
end

ビュー

異なるビュー間で章のリストを共有するには、次の 2 つの方法があります。

  1. モデル オブジェクトのコレクションをレンダリングするための Rails の組み込みサポートを使用します。あなたviews/documents/show.html.erbviews/chapters/show.html.erb次のようなものを含めることができます(各アクションが@document変数を設定すると仮定しています):

    <ol>
      <%= render @document.chapters %>
    </ol>
    

    Rails は と呼ばれる部分ビューを探し、views/chapters/_chapter.html.erbそれをチャプターごとにレンダリングします。次のようになります。

    <li><%= link_to chapter, [chapter.document, chapter] %></li>
    
  2. リスト全体を 1 つの部分で共有します。たとえば、次をviews/documents/show.html.erbandに追加できviews/chapters/show.html.erbます。

    <%= render 'chapters/list', :chapters => @document.chapters %>
    

    と呼ばれる部分ビューを作成しますviews/chapters/_list.html.erb

    <ol>
      <% chapters.each do |chapter| %>
        <li><%= link_to chapter, [chapter.document, chapter] %></li>
      <% end %>
    </ol>
    

詳細については、レイアウトとレンダリング ガイドのパーシャルの使用に関するセクションを参照してください。

于 2012-09-20T22:49:20.300 に答える
0

ネストを乱用してはならないことを何度も読んだことがあります.2レベルは明らかに問題なく、それが理にかなっている場合は3レベルですが、3レベルを超えるものは、おそらく物事を再考する必要があります.

3 レベルの入れ子で行うことができます。つまり、

/docs/:id/:chapter/:ページ

しかし、これを行うことも理にかなっているかもしれません

/docs/:id/:ページ

つまり、章を指定することを気にせずに、ドキュメントのページを直接参照します。

章が数字でページが数字の場合、ルーティングはどのように区別されますか。

/docs/1001/1

それは doc 1001 の 1 ページですか? それともdoc 1001の第1章?

悪魔の擁護者を演じて、深く巣を作ろうとすると潜在的な欠点を示します。

最も自然なことは次のとおりだと思います。

'/docs' => 'docs#index'  # show all docs
'/docs/:id'  => 'docs#show' # show all chapters in a doc
'/docs/:id/chapter/:chpt' => 'docs#show_chapter' # show all pages in a chapter in a doc
'/docs/:id/:page'  => 'docs#show'  # show a page in a doc

the show actions would have:
if params[:page]
  # show page specified
else
  # show all chapters
end

the order of the routes is important

これをお勧めする理由は、ブック/ページのクエリ セマンティクスがおそらくブック/章/ページよりも一般的だからです。

関連付けは次のようになります。

class Doc < ActiveRecord::Base
  has_many :pages
  has_many :chapters
end

ルーティングで end_page を公開しません。:page を受け入れる任意のルートに '?endpage=X' を追加するだけです。たとえば、show アクションでは次のようになります。

if params[:page]
  if params[:end_page]
    # show pages :page through :end_page
  else
    # show single :page
  end
else
  # show all chapters
end
于 2012-09-20T21:10:02.033 に答える