目標
id情報を取得する。
パラメーター関連でうまくいかないときの解決手順の参考になれば幸いです。
開発環境
ruby 2.5.7
Rails 5.2.4.3
OS: macOS Catalina
google chrome
前提
※ ▶◯◯ を選択すると、説明等が出てきますので、
よくわからない場合の参考にしていただければと思います。
今回はパラメーターのid取得で躓いてしまったため、
備忘録として記載させていただきます。
状況
- 投稿機能は実装済み
- 削除機能の実装を試みる
- コントローラー、ルーティング、viewそれぞれ記述
- destroyがnilになる。
これらを解決していきます。
controllerを疑う
def destroy
# binding.pry
@img_searchs = current_customer.img_searchs
@img_search = @img_searchs.find_by(id: params[:id])
unless @img_search
redirect_to new_img_search_path
end
if @img_search.destroy
redirect_to request.referer
else
render :new
end
end
binding.pryを記述し確認するも、
@img_search = @img_searchs.find_by(id: params[:id])がnilになってしまう。
記述自体は問題なさそうだが、idが渡せていない。
paramsを確認するとid='new'になっている。
(※後述しますがここをしっかり確認できていれば解決は早かったです)
→viewの記述がおかしい可能性あり。
viewを疑う
<% @img_searchs.each do |img_search| %>
...
<%= link_to "削除", new_img_search_path(img_search), method: :delete %>
<% end %>
each文の中で変数自体も合っており、記述ミスもなさそう。
ただし、今までdestroyメソッドを使ったときには、
img_search_path(img_search), method: :delete
このようにnewがない状態であったため、少し違和感。→ルーティングを確認。
routesを疑う
resources :img_searchs, only: [:create, :destroy, :new]
合っている。。。
念の為下記も実行。
$ rails routes
new_img_search GET /img_searchs/new(.:format)
public/img_searchs#new
DELETE /img_searchs/:id(.:format)
public/img_searchs#destroy
やはり合っている。。。
もう一度viewを確認するもやはり記述自体はあっている。
しかし、画面のカーソルを削除リンクに合わせると。。。
(google chromeでは左下にリンク先のURLが表示されます)
localhost:3000/img_searchs/new.15
/img_searchs/:idの形になっていない!
この時はなぜnewが入るのか全くわかりませんでした。
ただ先程の違和感は解消しておかなければと思い、
あまりきれいな記述ではないものの、ルーティングを書き換えることにしました。
resources :img_searchs, only: [:create, :new]
delete 'img_searchs/:id' => 'img_searchs#destroy'
そしてもう一度実行すると
$ rails routes
new_img_search GET /img_searchs/new(.:format)
public/img_searchs#new
DELETE /img_searchs/:id(.:format)
public/img_searchs#destroy
結果は全く同じでした。
なので、asでパスを指定してみることに。
resources :img_searchs, only: [:create, :new]
delete 'img_searchs/:id' => 'img_searchs#destroy', as: 'img_search'
そしてもう一度実行すると下記のようにエラー発生。
内容としては既にそのパス名は使われてますよ。とのこと。
$ rails routes
rails aborted!
ArgumentError: Invalid route name, already in use: 'img_search'
You may have defined two routes with the same name using the `:as` option, or you may be overriding a route already defined by a resource with the same naming. For the latter, you can restrict the routes created with `resources` as explained here:
...
そんな馬鹿な!と思い調べてみると、
別のページのURLでas: 'img_search'を使っていました。
これが今回の原因です。
そのため下記のようにパス名を変更。
resources :img_searchs, only: [:create, :new]
delete 'img_searchs/:id' => 'img_searchs#destroy', as: 'img_search_destroy'
その後、viewのパス名を変更。
<% @img_searchs.each do |img_search| %>
...
<%= link_to "削除", img_search_destroy_path(img_search), method: :delete %>
<% end %>
正常に動作しました。
まとめ
今回は手早く修正する必要があったため、
既にあったas: 'img_search'を変更するのではなく、
新しく追加した as: 'img_search'を as: 'img_search_destroy'に変更しました。
また今回起こってしまった要因としては、
私自身がroutes.rbの優先順を忘れてしまっていたがために、起こってしまったので、
同じエラーが起きた人の解決の一助になれたら幸いです。
ちなみにroutes.rbの優先順は上に記述したものが優先されます。
エラー解決の方法はいくつもあるため、一歩一歩焦らず蓄えていく必要がありそうです。