24
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

More than 3 years have passed since last update.

[Rails] DBにデータが登録されない時の対処方法

Posted at

##はじめに
Rails5.0での投稿機能実装ではまったのでメモ

##環境
macOS Catalina
Ruby 2.5.1
Rails 5.0.7.2
PostgreSQL

##困り
form_forでDBにデータを登録しようと思ったが、エラー出てないのにデータ保存されていなかった

##対処した方法

  1. GUIアプリで確認
  2. 保存されない原因を確認①(pry-rails)
  3. ハッシュの二重構造を解消
  4. 保存されない原因を確認②(メソッドの後ろに"!")
  5. バリデーションによるエラーを解消

###1. GUIアプリで確認

  • PostgreSQLを使用しているので、Posticoをインストール
  • GUIアプリでDBが見れるようになったら、もう一度投稿してみる
  • GUIアプリ上ではデータが保存されていないはず

▼インストール方法とDBへの接続方法
PostgreSQL:PostgreSQLのデータをGUIでいじる(macOS/Postico)
MySQL:Sequel Proを使ってデータベースを視覚化しよう

▼DB名の調べ方
ターミナルで「psql -l」を実行
実行結果の「app-name_development」が対象のDB名

terminal
$ psql -l #PostgreSQLのDBを一覧で表示する

#実行結果
                                 List of databases
          Name           | Owner  | Encoding | Collate | Ctype | Access privileges 
-------------------------+--------+----------+---------+-------+-------------------
 app-name_development    | user   | UTF8     | C       | C     | 
 app-name_test           | user   | UTF8     | C       | C     | 
 postgres                | user   | UTF8     | C       | C     | 
 template0               | user   | UTF8     | C       | C     | =c/user        +
                         |        |          |         |       | user=CTc/user
 template1               | user   | UTF8     | C       | C     | =c/user        +
                         |        |          |         |       | user=CTc/user
(5 rows)

###2. 保存されない原因を確認①(pry-rails)

  • pry-railsをインストール
Gemfile
group :development, :test do
  gem 'pry-rails'
end
terminal
$ bundle install
  • サーバー再起動(Ctrl + C、rails s)

  • データを保存するメソッドに binding.pry

post_controller.rb
def create
  binding.pry #データを保存するメソッドの中に
  Post.create(post_params)
end

private
def post_params
  params.permit(:content, :image)
end
  • もう一度投稿してみる
  • 投稿画面は読み込み中になるので、ターミナルでparamsを確認
terminal
    3: def create
 => 4:   binding.pry
    5:   Post.create(post_params)
    6: end

#params と入力
[1] pry(#<PostsController>)> params
=> <ActionController::Parameters {"utf8"=>"✓", "authenticity_token"=>"zDzgsL3bOIk0QSPOFk7eSOxvqVk18RQ0PW14dC3A7JtsLB9X2pLwvJ41V/f9WeqBDRo4Uz2PKtJDvcT4WpSCRg==", "post"=><ActionController::Parameters {"content"=>"ポストの内容テストテストテスト", "image"=>"test.jpeg"} permitted: false>, "commit"=>"投稿", "controller"=>"posts", "action"=>"create"} permitted: false>

#post_params と入力
[2] pry(#<PostsController>)> post_params
Unpermitted parameters: :utf8, :authenticity_token, :post, :commit
=> <ActionController::Parameters {} permitted: true> #ハッシュの中身が空なので登録できていない

ハッシュである'{}'の中身が空になっているため、
params.permit(:content, :image)では、paramsから該当するキーを取得できていないのが原因

###3. ハッシュの二重構造を解消

post_controller.rb
def create
  Post.create(post_params) #binding.pry は削除
end

private
def post_params
  params.require(:post).permit(:content, :image)
  #requireメソッドを使って二重構造となっているハッシュを取得
end
  • もう一度投稿する
  • Posticoで保存されているか確認 ⇒ 保存されていれば完了!

###4. 保存されない原因を確認②(メソッドの後ろに"!")

  • 保存されない場合は別の方法で原因を確認
  • 保存するメソッドの後ろに!をつける
post_controller.rb
def create
  Post.create!(post_params) #binding.pry は削除 #createの後ろに"!"
end
  • この状態でもう一度投稿すると画像のようなエラーが出るはず(コードは異なります)
    validation-failed-user-must-exist.png

⇒アソシエーションが組まれている際に、該当の外部キーが入っておらず、バリデーションで弾かれている

###5. バリデーションによるエラーを解消

  • optional: trueを記載
post.rb
class Post < ApplicationRecord
 belongs_to :user, optional: true #optional: ture を記載
end
  • optional: trueとは、belongs_toの外部キーのnilを許可するというもの

Railsのbelongs_toに指定できるoptional: trueとは?

  • 僕の場合はこれで保存できました。

##参考記事
https://teratail.com/questions/121213
https://qiita.com/tanaka7014/items/50a1a953b3f440cbe481

24
27
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
24
27

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?