29

ネストされたリソース、エッジRailsについての私の理解として、すべきではありません

link_to 'User posts', @user.posts

指し示す

/users/:id/posts

ルート.rbファイルには次のものが含まれています

map.resources :users, :has_many => :posts

これがデフォルトの動作ではない場合、他のことを実行して実行できますか?

4

4 に答える 4

63

リシャフと同じ線に沿って:

link_to "User Posts", [@user, :posts]

これが私のブログからの説明です。

Railsの非常に早い段階で、次のようなルートを作成します。

redirect_to :controller => "posts", :action => "show", :id => @post.id

showこれが行うことは、内部のアクションに忠実にリダイレクトし、返された値を使用してパラメーターをPostsController渡すことです。典型的な302応答。id@post.id

次に、Rails 1.2が登場し、次のようなルーティングヘルパーを使用できるようになりました。

redirect_to post_path(@post)

そして人々は喜んだ。

これは事実上同じことをします。ここでは、次のようなオブジェクトをpost_path使用してルートを構築し、そのルートに302応答を返し、ブラウザはそれに従います。@post/posts/1redirect_to

その後、それ以降のバージョン(どれを思い出せないか)では、次のような構文が許可されました。

redirect_to @post

そして人々は二度目に喜びました。

魔法ですが、実際にはそうではありません

十分に進んだ技術は魔法と見分けがつかない。

これは魔法のように見えますが、そうではありません。これがしていることは、実際には非常に、非常にきちんとしています。このメソッドは、そのいとことredirect_toよく似ており、すべて共通のメソッドを使用してURLを作成します。これは。と呼ばれます。このメソッドは、上記の例のように、文字列、ハッシュ、さらにはモデルのインスタンスなど、さまざまな種類のオブジェクトを受け取ります。link_toform_forurl_forurl_for

これらのオブジェクトで何が行われるかは、非常に適切です。redirect_to @post上記の呼び出しの場合、@post オブジェクトを検査し、それがクラスのオブジェクトであることPostを確認し(とにかく)、そのオブジェクトを呼び出して、そのオブジェクトがデータベースのどこかに永続化されているかどうかを確認しますpersisted?

「永続化」とは、Rubyオブジェクトのデータベースのどこかに一致するレコードがあることを意味します。persisted?Active Recordのメソッドは、次のように実装されます。

def persisted?
  !(new_record? || destroyed?)
end

そのような呼び出しによってオブジェクトが作成されなかった場合、Model.newそれは新しいレコードにはなりません。また、destroy呼び出されたメソッドがない場合、オブジェクトも破棄されません。これらの両方のケースが当てはまる場合、オブジェクトはレコードの形式でデータベースに永続化されている可能性があります。

永続化されている場合はurl_for、このオブジェクトがどこかで見つかる可能性があり、その場所が。というメソッドの下にある可能性が高いことを認識していますpost_path。したがって、このメソッドを呼び出し、to_paramこのオブジェクトの値(通常は。)を渡しますid

要するに、それは効果的にこれを行っています:

#{@post.class.downcase}_path(@post.to_param)

これはこれであることがわかります:

post_path(1)

そして、そのメソッドが呼び出されると、次の小さな文字列が得られます。

"/posts/1"

素晴らしい!

これはポリモーフィックルーティングと呼ばれます。のようなメソッドにオブジェクトを渡すことができredirect_to、それは使用するものの正しいURLを見つけ出そうlink_toform_forします。

form_forの形式

form_forさて、Railsをコーディングしているときは、かなり前にこのように使用したことがあるかもしれません。

<% form_for @post, :url => { :controller => "posts", :action => "create" } do |f| %>

もちろん、Railsの進歩により、これを単純化することができます。

<% form_for @post, :url => posts_path do |f| %>

フォームはデフォルトでPOSTHTTPメソッドを持つことになり、したがって、へのリクエストposts_pathは、 createアクションでPostsControllerはなく、のアクションに移動indexするためです。これは、GETリクエストの場合に発生します。

しかし、なぜそこで止まるのですか?なぜこれを書いてみませんか?

<%= form_for @post do |f| %>

個人的には、そうしない理由はありません...これほど単純なものであれば。このform_forメソッドは、フォームをどこに配置するかをurl_for決めるのと同じように、下を 使用します。オブジェクトがクラスredirect_toに属していることを認識し(ここでも想定します)、オブジェクトが永続化されているかどうかを確認します。そうである場合は、を使用します。そうでない場合は、。@postPostpost_path(@post)posts_path

メソッド自体は、form_for渡されたオブジェクトも永続化されているかどうかを確認し、永続化されている場合はデフォルトでPUTHTTPメソッドになり、そうでない場合はPOST

したがって、これは、aとviewform_forの両方で同じ構文を持つのに十分な柔軟性を備えている方法です。最近では、タグ全体を1つの部分にまとめて、ページと ページの両方に含めることがますます一般的になっています。neweditform_fornewedit

より複雑な形式

したがってform_for、通常のオブジェクトを渡す場合はかなり簡単ですが、オブジェクトの配列を渡すとどうなりますか?このように、例えば:

<%= form_for [@post, @comment] do |f| %>

ええと、両方url_forform_forあなたもそこでカバーしましたか。

このurl_forメソッドは、これが配列であることを検出し、各部分を分離して個別に検査します。まず、これは何 @postですか?さて、この場合、それが永続化され、IDが1 のPostインスタンスであると仮定しましょう。次に、このオブジェクトは何ですか?これは、データベースにまだ永続化されていないインスタンスです。@commentComment

ここurl_forで行うことは、各部分を配列に配置し、それをルーティングメソッドに結合し、必要な引数を使用してそのルーティングメソッドを呼び出すことにより、URLヘルパーメソッドを1つずつ構築することです。

まず、@postオブジェクトがPostクラスのものであり、永続化されていることを認識しているため、URLヘルパーは。で始まりますpost。次に、@commentオブジェクトがCommentクラスのものであり、永続化されていないことを認識しているため、URLヘルパービルドcommentsに従います。現在知っているpost部分はです。url_for[:post, :comments]

このurl_forメソッドは、これらの個々の部分をアンダースコアと組み合わせて、それがその末尾になりpost_comments、その後に追加_path されるようにして、結果としてpost_comments_path。次に、永続化されたオブジェクトだけをそのメソッドの呼び出しに渡し、次のような呼び出しになります。

post_comments_path(@post)

そのメソッドを呼び出すと、次のようになります。

"/posts/1/comments"

最良の部分?オブジェクトが永続化されたオブジェクトでない場合、および永続化されている場合は、form_for引き続き使用することを認識します。覚えておくとよいのは、は常に配列で指定された最後のオブジェクト用であるということです。その前のオブジェクトは、単にネストされているだけで、それ以上のものではありません。POST@commentPUTform_for

追加するオブジェクトが多いほどurl_for、ハードヤードを実行してパスを構築する時間が長くなります...ただし、2つの部分に留めておくことをお勧めします。

象徴的な形

のオブジェクトを含む配列の使用について説明しform_forたので、別の一般的な使用法を見てみましょう。次のように、少なくとも1つのSymbolオブジェクトを含む配列:

<%= form_for [:admin, @post, @comment] do |f| %>

ここでのurl_for方法は非常に簡単です。があることを確認Symbolし、そのまま使用します。の最初の部分は、 url単に記号と同じになりますadminurl_forこの時点で知っているURLはただ[:admin]です。

次にurl_for、アレイの残りの部分を調べます。@postこの場合、とが両方とも@comment永続化されており、IDがそれぞれ1と2であると仮定します。以前と同じクラス。次に、構築しているURLにもurl_for追加し、結果として。postcomment[:admin, :post, :comment]

次に、結合が発生し、のメソッドが生成されます。admin_post_comment_path両方@post@commentがここで永続化されるため、これらが渡され、次のメソッド呼び出しが発生します。

admin_post_comment_path(@post, @comment)

これは(通常)このパスになります:

/admin/posts/1/comments/2

redirect_tolink_toおよびform_forメソッドを使用して、ポリモーフィックルーティングの配列形式を使用できます。私が今覚えていない他の方法もおそらくそれを行うことができます...それは通常、URLを受け取るRailsのすべてのものです。

ハッシュを使用して2を超えるRailsバージョンでURLを作成する必要はありません。それはかなり古い学校です。

代わりに、ポリモーフィックルーティングの新しい知識を試して、最大限に活用してください。

于 2009-10-10T22:08:47.353 に答える
16

これは機能するはずです:

 
 link_to "ユーザー投稿"、user_posts_path(@user)

詳細については、以下をご覧ください。

http://guides.rubyonrails.org/routing.html

于 2009-10-10T14:06:37.887 に答える
2

link_toを使用url_forしますpolymorphic_url

polymorphic_url

したがって、他の人が言ったように、あなたは使用する必要があります:

link_to 'User Posts', [@user, :posts]

パスは次のとおりです。

user_posts_path(@user)
^^^^ ^^^^^      ^^^^^
1    2          3
  1. @userそれはアクティブレコードであるためのクラス
  2. 記号のため文字列に変換
  3. アクティブレコードのため、呼び出し引数として追加

それは良いヘルパーメソッドを構築します。

于 2014-11-09T11:47:03.233 に答える
1

最新のRailsでネストされたリソースにリンクする方法は次のとおりです。

link_to'コメントを破棄'、post_comment_path(comment.post、comment)

注:これは部分的なものであるため、はありません@

于 2013-10-08T15:28:14.223 に答える