質問をすることでしか得られない、回答やアドバイスがある。

15分調べてもわからないことは、質問しよう!

新規登録して質問してみよう
ただいま回答率
85.35%
Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

ルーティング

ルーティングとは、TCP/IPネットワークにおいて、目的のホストまでパケットを送る為のパス選定のプロセスを言います。

Q&A

解決済

2回答

5591閲覧

【Railsチュートリアル】パーシャル実装によるルーティングの不正

chai_mitsuya

総合スコア18

Ruby

Rubyはプログラミング言語のひとつで、オープンソース、オブジェクト指向のプログラミング開発に対応しています。

Ruby on Rails

Ruby on Railsは、オープンソースのWebアプリケーションフレームワークです。「同じことを繰り返さない」というRailsの基本理念のもと、他のフレームワークより少ないコードで簡単に開発できるよう設計されています。

ルーティング

ルーティングとは、TCP/IPネットワークにおいて、目的のホストまでパケットを送る為のパス選定のプロセスを言います。

0グッド

0クリップ

投稿2017/02/15 20:49

###前提・実現したいこと
Ruby on Railsのチュートリアルで勉強をしていたところ、演習で行き詰まってしまいました。ルーティングが不正と思われることまでは確認できたのですが、それを正しく修正する方法がわかりません。

###発生している問題・エラーメッセージ
ログインしたユーザのプロフィールを編集するというページで、更新のボタンを押下した際にエラーが発生し、正しく処理されません。

以下のURLの演習2が正しく実装されていないようです。
URL:https://railstutorial.jp/chapters/updating_and_deleting_users?version=5.0#sec-edit_form

Routing Error No route matches [PATCH] "/users/1/edit"

###該当のソースコード

Ruby

1[route.rb] 2Rails.application.routes.draw do 3 root 'static_pages#home' 4 get '/help', to: 'static_pages#help' 5 get '/about', to: 'static_pages#about' 6 get '/contact', to: 'static_pages#contact' 7 get '/signup', to: 'users#new' 8 get '/login', to: 'sessions#new' 9 post '/login', to: 'sessions#create' 10 post '/signup', to: 'users#create' 11 delete '/logout', to: 'sessions#destroy' 12 resources :users 13end

Ruby

1[edit.html.erb] 2<% provide(:title, 'Edit user') %> 3<% provide(:button_text, 'Save changes') %> 4<% provide(:url, edit_user_path) %> <!-- ←試しに実装して失敗 --> 5<h1>Update your profile</h1> 6<div class="row"> 7 <div class="col-md-6 col-md-offset-3"> 8 <%= render 'form' %> 9 <div class="gravatar_edit"> 10 <%= gravatar_for @user %> 11 <a href="http://gravatar.com/emails" target="_blank">Change</a> 12 </div> 13 </div> 14</div>

Ruby

1[_form.html.erb] 2<%= form_for(@user,url: yield(:url)) do |f| %> 3 <%= render 'shared/error_messages', object: @user %> 4 5 <%= f.label :name %> 6 <%= f.text_field :name, class: 'form-control' %> 7 8 <%= f.label :email %> 9 <%= f.email_field :email, class: 'form-control' %> 10 11 <%= f.label :password %> 12 <%= f.password_field :password, class: 'form-control' %> 13 14 <%= f.label :password_confirmation %> 15 <%= f.password_field :password_confirmation, class: 'form-control' %> 16 17 <%= f.submit yield(:button_text), class: "btn btn-primary" %> 18<% end %>

###試したこと
元々「_form.html.erb」の内容は「edit.html.erb」に実装されており、その時点では上手くいきました。
「_form.html.erb」の内容は他のソースと重複するので、リファクタリングしようというのが演習で、今のようなソースコードに修正した際に問題が発生しました。

演習前のソースに戻して画面上でソースを確認したところ、formのaction属性が「action="/users/1"(1はユーザID)」となっているので、この形式にルーティングをしようとしました。以下のようにルーティングを確認して、「route.rb」に『patch '/edit_user' to: 'users#update'』のようなルーティングの設定をいくつか試してみたのですが、解決には至りませんでした。

$ rails routes Prefix Verb URI Pattern Controller#Action root GET / static_pages#home help GET /help(.:format) static_pages#help about GET /about(.:format) static_pages#about contact GET /contact(.:format) static_pages#contact signup GET /signup(.:format) users#new login GET /login(.:format) sessions#new POST /login(.:format) sessions#create POST /signup(.:format) users#create logout DELETE /logout(.:format) sessions#destroy users GET /users(.:format) users#index POST /users(.:format) users#create new_user GET /users/new(.:format) users#new edit_user GET /users/:id/edit(.:format) users#edit user GET /users/:id(.:format) users#show PATCH /users/:id(.:format) users#update PUT /users/:id(.:format) users#update DELETE /users/:id(.:format) users#destroy

###補足情報(言語/FW/ツール等のバージョンなど)
環境:Cloud9
ruby:2.3.0
Rails:5.0.0.1

よろしくお願いいたします。

気になる質問をクリップする

クリップした質問は、後からいつでもMYページで確認できます。

またクリップした質問に回答があった際、通知やメールを受け取ることができます。

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

guest

回答2

0

ベストアンサー

ruby

1_form.html.erb 2<%= form_for(@user,url: yield(:url)) do |f| %>

ここがまずいです。
railsはeditの時はupdate
newの時はcreateにpostします。
この場合自分自身editの場合はeditにpostしています。
もちろんそんなルーティングはありません。

ruby

1_form.html.erb 2<%= form_for(@user) do |f| %>

urlの指定を解除してください。
特殊なことをしていなければ(レールに乗っていれば)後はよろしくやってくれます。

投稿2017/02/16 01:56

moke

総合スコア2241

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

chai_mitsuya

2017/02/16 20:59

自分で誤ったURLに誘導していたのですね・・・ 指摘のとおりに修正したら、無事に直りました! ありがとうございました!
guest

0

今更掘り返してごめんなさい。

もう質問者様はとっくにTutorialを終えてご活躍されていることと思いますが、私が現在Tutorialを進めていて同箇所でエラーが出てこの質問に辿り着いたところ、気になる点がありました。
moke様の回答で確かに成功したのかもしれませんが、必ずしも適切とは思えませんでしたので、回答させてください。

リファクタリングのために_form.html.erbを作成した際、new.html.erbに

<%= form_for(@user, url: signup_path) do |f| %>

としてパスを指定している部分があったため、パーシャルで

<%= form_for(@user) do |f| %>

としてurl指定を外してしまうのは適切ではないはずです。

だからこそリファクタリングの演習において

例えば筆者であれば、リスト 10.5のテクニックをリスト 10.6に適用してみたり、リスト 10.7のテクニックをリスト 10.5に適用してみたりするでしょう。)

(言及されているリスト10.6と10.7ではyieldとprovideを使用)

とあり、つまりyieldとprovideを使う必要がありますよという旨が述べられていたのでしょう。

moke様の回答にあるように、

railsはeditの時はupdate

newの時はcreateにpostします。
この場合自分自身editの場合はeditにpostしています。
もちろんそんなルーティングはありません。

ですので**、editのときupdateにpostするように(provideで)パスを指定すれば良い**のです。

質問に

ルーティングを確認して、「route.rb」に『patch '/edit_user' to: 'users#update'』のようなルーティングの設定をいくつか試してみたのですが、解決には至りませんでした。

とありますが、もしかするとその際に指定したパスが(例えばtypoなどで)間違っていたのかもしれません。
質問者様が試した方法そのものは正しかったはずです。

patch '/edit_user' to: 'users#update'するためには、form_forヘルパーに直で書くなら

<%= form_for(@user, url: user_path) do |f| %>

とすればよいです。

Tutorialに従ってprovideとyieldを使うなら、質問者様の_form.html.erbに従うと、edit.html.erbには

<% provide(:path, user_path) %>

とするとうまくいきます。

以上をぐっと短くまとめると、質問者様がedit_user_pathとしてしまったところをuser_pathにすればよいという話ですね。
私も最初そのように間違えてしまいました。

(私の場合、さらにコントローラ内でupdate_attributesというメソッドの末尾の複数形のsをつけ忘れており、さらにエラー解決に時間がかかりましたが…汗)

他に同じエラーで悩まれている方の助けになれば幸いです。

投稿2018/04/08 17:49

編集2018/04/08 17:50
paya

総合スコア11

バッドをするには、ログインかつ

こちらの条件を満たす必要があります。

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

15分調べてもわからないことは
teratailで質問しよう!

ただいまの回答率
85.35%

質問をまとめることで
思考を整理して素早く解決

テンプレート機能で
簡単に質問をまとめる

質問する

関連した質問