はじめに
Rails5.0での投稿機能実装ではまったのでメモ
環境
macOS Catalina
Ruby 2.5.1
Rails 5.0.7.2
PostgreSQL
困り
form_forでDBにデータを登録しようと思ったが、エラー出てないのにデータ保存されていなかった
対処した方法
- GUIアプリで確認
 - 保存されない原因を確認①(pry-rails)
 - ハッシュの二重構造を解消
 - 保存されない原因を確認②(メソッドの後ろに"!")
 - バリデーションによるエラーを解消
 
1. GUIアプリで確認
- PostgreSQLを使用しているので、Posticoをインストール
 - GUIアプリでDBが見れるようになったら、もう一度投稿してみる
 - GUIアプリ上ではデータが保存されていないはず
 
▼インストール方法とDBへの接続方法
PostgreSQL:PostgreSQLのデータをGUIでいじる(macOS/Postico)
MySQL:Sequel Proを使ってデータベースを視覚化しよう
▼DB名の調べ方
ターミナルで「psql -l」を実行
実行結果の「app-name_development」が対象のDB名
$ 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をインストール
 
group :development, :test do
  gem 'pry-rails'
end
$ bundle install
- 
サーバー再起動(Ctrl + C、rails s)
 - 
データを保存するメソッドに binding.pry
 
def create
  binding.pry #データを保存するメソッドの中に
  Post.create(post_params)
end
private
def post_params
  params.permit(:content, :image)
end
- もう一度投稿してみる
 - 投稿画面は読み込み中になるので、ターミナルでparamsを確認
 
    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. ハッシュの二重構造を解消
def create
  Post.create(post_params) #binding.pry は削除
end
private
def post_params
  params.require(:post).permit(:content, :image)
  #requireメソッドを使って二重構造となっているハッシュを取得
end
- もう一度投稿する
 - Posticoで保存されているか確認 ⇒ 保存されていれば完了!
 
4. 保存されない原因を確認②(メソッドの後ろに"!")
- 保存されない場合は別の方法で原因を確認
 - 保存するメソッドの後ろに!をつける
 
def create
  Post.create!(post_params) #binding.pry は削除 #createの後ろに"!"
end
⇒アソシエーションが組まれている際に、該当の外部キーが入っておらず、バリデーションで弾かれている
5. バリデーションによるエラーを解消
- optional: trueを記載
 
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
