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

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

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

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

Ruby on Rails

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

Q&A

解決済

1回答

1421閲覧

destroyアクションが反応しない

divclass123

総合スコア35

Ruby

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

Ruby on Rails

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

0グッド

0クリップ

投稿2020/11/23 09:00

編集2020/11/28 02:28

前提・実現したいこと

userを削除したいのですが
destroyアクションがうまく機能しません

発生している問題・エラーメッセージ

エラーメッセージが表示されません

該当のソースコード

users_controller

ruby

1class UsersController < ApplicationController 2 include SessionsHelper 3 4 5 def destroy 6 user = User.find(params[:id]) 7 #binding.pry 8 user.destroy 9 redirect_to root_url 10 end 11 12 13

drinks/index.html.erb

erb

1<%= link_to "退会する", user_path(current_user),method: :delete %>

current_userは自分で定義したヘルパーメソッドです

sessions_helper.rb

ruby

1 # 現在ログインしているユーザーの情報を取得 2 def current_user 3 # DBの問い合わせの数を可能な限り小さくしたい 4 # logged_in?メソッドでも使われてるし、、、 5 if user_id = session[:user_id] 6 # セッションがある場合 7 # すなわちログインしてる時のみ 8 9 # sessionにアクセスした結果を変数に 10 # 入れておいてあとで使いまわした方が 11 # 早くなる 12 @current_user ||= User.find_by(id: user_id) 13 # find_byでデータベースにクエリを投げる 14 # ブラウザのセッションにあるuser_idをもとにUser定義 15 16 # find_byの実行結果をインスタンス変数に保存する 17 # ことで、1リクエスト内におけるデータベースへの 18 # 問い合わせは最初の一回だけになり、 19 # 以後の呼び出しではインスタンス変数の結果を 20 # 再利用する 21 22 # すでに@current_userが存在する場合って何? 23 # 一回current_userを実行したら、 24 # @current_userがあるのでそれを使ってね 25 26 # sessionのuser_idがあるということは 27 # 既にログインしてるといてDBにユーザーの情報があるはず。 28 # だからsessionのuser_idをDBでfind_byかければいい 29 elsif (user_id = cookies.signed[:user_id]) 30 # sessionが張られてなかったらcookiesにあるかも 31 user = User.find_by(id: user_id) 32 if user && user.authenticated?(cookies[:remember_token]) 33 # nilガード 34 # クッキーのuser_idとremember_tokenが一致してる 35 log_in user 36 @current_user = user 37 end 38 end 39 end

user.rb

ruby

1class User < ApplicationRecord 2 attr_accessor :remember_token 3 # remember_tokenというメソッドを作成 4 # password,password_comfirmationみたいな 5 # 変数のように扱える 6 # u.remember_token的なことができる 7 has_many :drinks, dependent: :delete_all 8 before_save { self.email = email.downcase } 9 has_secure_password 10 validates :nickname, presence: true, length: { maximum: 50 } 11 VALID_EMAIL_REGEX = /\A[\w+\-.]+@[a-z\d\-.]+.[a-z]+\z/i 12 validates :email, presence: true, length: { maximum: 255 }, 13 format: { with: VALID_EMAIL_REGEX }, 14 uniqueness: { case_sensitive: false } 15 validates :password, presence: true, length: { minimum: 6 },allow_nil: true 16 # ユーザー更新時に空のパスワードでも大丈夫 17 # has_secure_passwordの方でpasswordの存在性を検証するから大丈夫 18 19 20 21 # 渡された文字列のハッシュ値を返す 22 def User.digest(string) 23 cost = ActiveModel::SecurePassword.min_cost ? BCrypt::Engine::MIN_COST : 24 BCrypt::Engine.cost 25 BCrypt::Password.create(string, cost: cost) 26 end 27 28 # ランダムなトークンを返す 29 def User.new_token 30 SecureRandom.urlsafe_base64 31 end 32 33 # 永続的にログインするためにトークンをDBに保存 34 def remember 35 self.remember_token = User.new_token 36 # 何のトークンか分かりやすいから 37 # remember_tokenって名前を作った 38 update_attribute(:remember_digest,User.digest(remember_token)) 39 # ハッシュ化したトークンをremember_digestに保存 40 end 41 42 # 渡されたトークンがダイジェストと一致したらtrue 43 # を返す 44 def authenticated?(remember_token) 45 return false if remember_digest.nil? 46 # 二種類のブラウザを使用してログアウトした場合 47 # cookiesのremember_tokenはあるけど、 48 # サーバー側でremember_digestをnilにしてるから 49 # nilに対して.is_password?とかやるとfor nil classエラーが起きちゃう 50 # remember_digestがnilの場合はfalseを返して、処理を止める 51 52 # 後置if文に当てはまる条件があれば処理を止めて! 53 # って場合はreturnとかで明示的に書くとif ~ else ~ end 54 # とか書かなくて済む 55 BCrypt::Password.new(remember_digest).is_password?(remember_token) 56 end 57 58 # ユーザーのログイン情報を破棄する 59 def forget 60 update_attribute(:remember_digest,nil) 61 end 62end 63

Drink.rb

ruby

1class Drink < ApplicationRecord 2 belongs_to :user 3 with_options presence: true do 4 validates :name 5 validates :explain 6 end 7end 8

:20201116073717_create_users.rb

ruby20201116073717_create_users.rb

1class CreateUsers < ActiveRecord::Migration[6.0] 2 def change 3 create_table :users do |t| 4 t.string :nickname 5 t.string :email 6 t.string :password_digest 7 8 t.timestamps 9 end 10 end 11end

/20201118162753_create_drinks.rb

ruby

1class CreateDrinks < ActiveRecord::Migration[6.0] 2 def change 3 create_table :drinks do |t| 4 t.string :name 5 t.integer :price 6 t.text :explain 7 t.references :user,null: false,foreign_key: true 8 t.timestamps 9 end 10 end 11end 12

routes.rb

ruby

1Rails.application.routes.draw do 2 root to: 'drinks#index' 3 get '/login', to: 'sessions#new' 4 post '/login', to: 'sessions#create' 5 delete '/logout', to: 'sessions#destroy' 6 resources :users 7 resources :drinks, only: [:index,:new,:show,:create,:destroy] 8end

退会リンクをusers/showに移動しました

エラーも起きていませんし、@userの定義もしっかりできていて、@user.nameとかやってもしっかり表示できているので、リンクの指定はあってると思います

このログを見るとリンクを踏んだ後にrootに戻ってるように見えます

補足情報(FW/ツールのバージョンなど)

ruby 2.6.5
rails 6.0.3

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

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

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

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

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

maisumakun

2020/11/23 09:02

モデルはどのようなコードですか? (モデル単体でdestroyしてロールバックがかかるということは、モデルに入ったバリデーションが影響していることが考えられます)
divclass123

2020/11/23 09:07

ありがとうございます、追加しましたのでご確認のほどよろしくお願いします
maisumakun

2020/11/23 09:09

irbでuser.destroyを行って失敗した直後にuser.errorsを確認することはできますか?
divclass123

2020/11/24 08:32

``` irb(main):003:0> user = User.first Traceback (most recent call last): 5: from /Users/soichirohara/.rbenv/versions/2.6.5/bin/irb:23:in `<main>' 4: from /Users/soichirohara/.rbenv/versions/2.6.5/bin/irb:23:in `load' 3: from /Users/soichirohara/.rbenv/versions/2.6.5/lib/ruby/gems/2.6.0/gems/irb-1.0.0/exe/irb:11:in `<top (required)>' 2: from (irb):3 1: from (irb):3:in `rescue in irb_binding' NameError (uninitialized constant User) ``` rails c 的な感じで実行したら上手くいかないので、どのようなコマンドを打つべきか教えて下されば幸いです。
maisumakun

2020/11/24 08:34

すみません、単なるirbではなくてrails cから行ってください(アドバイスが悪かったです)。
divclass123

2020/11/24 08:49

[2] pry(main)> u = User.first (0.7ms) SET NAMES utf8mb4, @@SESSION.sql_mode = CONCAT(CONCAT(@@sql_mode, ',STRICT_ALL_TABLES'), ',NO_AUTO_VALUE_ON_ZERO'), @@SESSION.sql_auto_is_null = 0, @@SESSION.wait_timeout = 2147483 User Load (0.3ms) SELECT `users`.* FROM `users` ORDER BY `users`.`id` ASC LIMIT 1 => #<User:0x00007fcf0c065aa8 id: 26, nickname: "はらそう", email: "harasou@gmail.com", created_at: Mon, 23 Nov 2020 21:33:48 UTC +00:00, updated_at: Mon, 23 Nov 2020 21:33:48 UTC +00:00, password_digest: [FILTERED], remember_digest: nil> [3] pry(main)> u.destroy (3.9ms) BEGIN Drink Load (0.3ms) SELECT `drinks`.* FROM `drinks` WHERE `drinks`.`user_id` = 26 Drink Destroy (7.2ms) DELETE FROM `drinks` WHERE `drinks`.`id` = 8 User Destroy (0.9ms) DELETE FROM `users` WHERE `users`.`id` = 26 (2.0ms) COMMIT => #<User:0x00007fcf0c065aa8 id: 26, nickname: "はらそう", email: "harasou@gmail.com", created_at: Mon, 23 Nov 2020 21:33:48 UTC +00:00, updated_at: Mon, 23 Nov 2020 21:33:48 UTC +00:00, password_digest: [FILTERED], remember_digest: nil> 質問の内容とは違い、今度はしっかり削除できてるような気がしますが、 実際に自分で作ったアプリ上から削除すると上手くいきません、、 link_toの記述が間違ってるのかな、、と思ったのですが ログでは Started DELETE “/users/27” for ::1 at 2020-11-24 17:38:11 +0900 Processing by UsersController#destroy as HTML Parameters: {“authenticity_token”=>“6XlOECeU2iBZQO559AgCQDtxvC0AgRzJQcgyfFuDfrL8t8xQvTxCN9Hz4MowyrDFhnqM55Ob1VfpjerBDPqFDg==“, “id”=>“27"} User Load (0.3ms) SELECT users.* FROM users WHERE users.id = 27 LIMIT 1 ↳ app/helpers/sessions_helper.rb:53:in `current_user’ Redirected to http://localhost:3000/ Filter chain halted as :correct_user rendered or redirected Completed 302 Found in 2ms (ActiveRecord: 0.3ms | Allocations: 978) このようにしっかりdestroyに飛ばせてるような気がします、、、
maisumakun

2020/11/24 09:01

Rails内ではdrinkのdestroyに失敗しているようですが、(Userではなく)そちらではどうでしょうか?
divclass123

2020/11/24 10:30

4] pry(main)> drink = Drink.first Drink Load (0.6ms) SELECT `drinks`.* FROM `drinks` ORDER BY `drinks`.`id` ASC LIMIT 1 => #<Drink:0x00007fcf02f82a90 id: 9, name: "そうちゃんの投稿", price: 0, explain: "aaaa", user_id: 1, created_at: Tue, 24 Nov 2020 10:29:37 UTC +00:00, updated_at: Tue, 24 Nov 2020 10:29:37 UTC +00:00> [5] pry(main)> drink.destroy (0.4ms) BEGIN Drink Destroy (0.6ms) DELETE FROM `drinks` WHERE `drinks`.`id` = 9 (1.8ms) COMMIT => #<Drink:0x00007fcf02f82a90 id: 9, name: "そうちゃんの投稿", price: 0, explain: "aaaa", user_id: 1, created_at: Tue, 24 Nov 2020 10:29:37 UTC +00:00, updated_at: Tue, 24 Nov 2020 10:29:37 UTC +00:00> こーゆーことでよろしいのでしょうか、、?
maisumakun

2020/11/24 10:53

問題なく削除できていますね…ちょっとわからないです。
divclass123

2020/11/25 19:20

ですよね、、、、いえいえ!ありがとうございます!
tomtomtomtom

2020/11/26 19:03

migrationをお見せいただくことは可能でしょうか? userとdrinkです。
divclass123

2020/11/27 00:32

追加しました、よろしくお願いします!
tomtomtomtom

2020/11/27 07:26

なるほど ちょっと予測していたmigrationとは違い、間違いはないようでした。 そこで、divさんのこれまでの返答を更に深く読んでいると、 「Filter chain halted as :correct_user rendered or redirected  Completed 302 Found」 という非常に興味ぶかい記述、、、 非常にお手間をおかけして誠に申し訳有りませんが、 routes.rbをお見せいただくことは可能でしょうか?
divclass123

2020/11/28 02:19

ログの意味がよく分からないので非常に助かります、、、! いえいえとんでもないです、情報を追加したのでよろしくお願いします!
tomtomtomtom

2020/11/28 06:55

ちょっと調べてみました。 間違っているかもしれませんが、 resources :users get '/login', to: 'sessions#new' post '/login', to: 'sessions#create' delete '/logout', to: 'sessions#destroy' root to: 'drinks#index' resources :drinks, only: [:index,:new,:show,:create,:destroy] ↑これでいかがでしょうか?
divclass123

2020/11/28 11:53

解決できました、、、!原因はbefore_actionで何故かdestroyをフィルタリングしてたことが原因でした、、、、
tomtomtomtom

2020/11/28 16:42

ご解決おめでとうございます^^ 力になれず申し訳有りませんでした。
divclass123

2020/11/30 08:25

いえいえとんでも無いです、助けて頂いてありがとうございました、、! 質問欄にbefore_actionを記述しておくべきでした。
guest

回答1

0

自己解決

ruby

1 before_action :logged_in_user, only: [:index,:edit,:update,:destroy] 2 before_action :correct_user, only: [:edit, :update,:destroy]

ruby

1 def correct_user 2 redirect_to(root_url) unless current_user?(@user) 3 end

ruby

1 def logged_in_user 2 unless logged_in? 3 store_location 4 # ユーザーがいきたがってたページを記憶 5 flash[:danger] = "Please log in" 6 redirect_to login_url 7 end 8 end

<strong>原因はbefore_actionにdestroyを設定してた</strong>
:destroyを外してあげればok

投稿2020/11/28 11:56

divclass123

総合スコア35

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

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

あなたの回答

tips

太字

斜体

打ち消し線

見出し

引用テキストの挿入

コードの挿入

リンクの挿入

リストの挿入

番号リストの挿入

表の挿入

水平線の挿入

プレビュー

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

ただいまの回答率
85.48%

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

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

質問する

関連した質問