web-dev-qa-db-ja.com

Rails --link_to、ルート、ネストされたリソース

Edge Railsのネストされたリソースに関する私の理解として、

link_to 'User posts', @user.posts

指し示す

/users/:id/posts

ルート.rbファイルには

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

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

27
knoopx

リシャフと同じように:

_link_to "User Posts", [@user, :posts]
_

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

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

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

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

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

_redirect_to post_path(@post)
_

そして人々は喜んだ。

これは実質的に同じことを行います。ここで_post_path_は、_@post_のように見える_/posts/1_オブジェクトを使用してルートを構築し、_redirect_to_はそのルートに302応答を返し、ブラウザはそれに従います。

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

_redirect_to @post
_

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

魔法ですが、実際には

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

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

それで、これらのオブジェクトでそれが何をするかは、かなりきちんとしています。上記の_redirect_to @post_呼び出しの場合、_@post_オブジェクトを検査し、それがPostクラスのオブジェクトであることを確認し(とにかく)、そのオブジェクトが永続化されているかどうかを確認します。どこかでデータベースを_persisted?_で呼び出す。

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

_def persisted?
  !(new_record? || destroyed?)
end
_

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

永続化されている場合、_url_for_は、このオブジェクトがどこかにあること、およびその場所が_post_path_と呼ばれるメソッドの下にある可能性が高いことを認識しています。そのため、このメソッドを呼び出し、通常はidであるこのオブジェクトの_to_param_値を渡します。

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

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

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

_post_path(1)
_

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

_"/posts/1"
_

美しい!

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

Form_forの形式

今、あなたがコーディングしているときRailsあなたは非常に昔にこのように_form_for_を使用したかもしれません:

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

もちろん、Railsの進歩により、次のように単純化できます。

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

フォームはデフォルトでPOSTHTTPメソッドを持つため、_posts_path_へのリクエストはcreateアクションではなく、PostsControllerindexアクションに送られます。これはGETの場合に発生します。リクエスト。

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

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

個人的には、そうしない理由はありません...これほど単純なものであれば。 _form_for_メソッドは、_url_for_と同様に、その下に_redirect_to_を使用して、フォームの配置先を決定します。 _@post_オブジェクトがPostクラス(ここでも想定)であることを認識し、オブジェクトが永続化されているかどうかを確認します。そうである場合は、post_path(@post)を使用します。そうでない場合は、_posts_path_です。

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

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

より複雑な形式

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

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

まあ、_url_for_と_form_for_の両方について説明しました。

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

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

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

_url_for_メソッドは、これらの個々の部分をアンダースコアと組み合わせて_post_comments_になり、その最後に__path_を追加して、_post_comments_path_になります。次に、永続化されたオブジェクトのみをそのメソッドの呼び出しに渡し、次のような呼び出しを行います。

_post_comments_path(@post)
_

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

_"/posts/1/comments"
_

最良の部分? _form_for_は、_@comment_オブジェクトが永続オブジェクトでない場合はPOSTを使用し、永続オブジェクトである場合はPUTを使用することを引き続き認識します。覚えておくとよいのは、_form_for_は常に配列で指定されたlastオブジェクト用であるということです。その前のオブジェクトは、単に入れ子になっているだけです。

追加されるオブジェクトが多いほど、_url_for_がハードヤードを実行してパスを構築する回数が多くなります... 2つの部分に保つことをお勧めします。

象徴的な形

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

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

ここで_url_for_メソッドが行うことは非常に簡単です。 Symbolがあることを確認し、それをそのまま受け取ります。 urlの最初の部分は単に記号と同じです:admin。 _url_for_がこの時点で知っているURLは_[:admin]_です。

次に、_url_for_は配列の残りの部分を通過します。この場合、_@post_と_@comment_の両方が永続化されており、IDがそれぞれ1と2であると仮定します。以前と同じクラス。次に、_url_for_は、構築しているURLにpostを追加し、commentも追加して、_[:admin, :post, :comment]_になります。

次に、結合が発生し、_admin_post_comment_path_のメソッドが生成されます。また、_@post_と_@comment_の両方がここに保持されるため、これらが渡され、次のメソッド呼び出しが発生します。

_admin_post_comment_path(@post, @comment)
_

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

_/admin/posts/1/comments/2
_

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

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

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

54
Ryan Bigg

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

 
 link_to "User Posts"、user_posts_path(@user)
 

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

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

16
Rishav Rastogi

link_tourl_for を使用します polymorphic_url を使用します。

polymorphic_url

したがって、他の人が言ったように、あなたは使うべきです:

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

パスは次のとおりです。

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

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

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

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

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

1
Chloe