accepts_nested_attributes_for がモデルにあるときのRspecを通したい
- 評価
- クリップ 0
- VIEW 629
前提・実現したいこと
accepts_nested_attributes_for を使って親子関係にある2つのモデルがある。
(親:Post, 子:Picture)
request_spec で create する際、Post も Picture も数が増えるというテストを書いて通したい。
なお、テストの書き方はこちらのQiitaの記事を参考にしました。
発生している問題・エラーメッセージ
I, [2020-06-16T04:23:23.051589 #976] INFO -- : Parameters: {"post"=>{"title"=>"MyTitle", "content"=>"MyContent", "pictures_attributes"=>[{"name"=>[#<ActionDispatch::Http::UploadedFile:0x0000558e67b27a78 @tempfile=#<Tempfile:/tmp/RackMultipart20200616-976-olzaw.png>, @original_filename="testfile.png", @content_type="spec/support/testfile.png", @headers="Content-Disposition: form-data; name=\"post[pictures_attributes][][name][]\"; filename=\"testfile.png\"\r\nContent-Type: spec/support/testfile.png\r\nContent-Length: 15605\r\n">]}]}}
D, [2020-06-16T04:23:23.070685 #976] DEBUG -- : Unpermitted parameter: :name
name カラムに許可されていないパラメータを含んでいるからエラーという意味???
該当のソースコード
Model
# app/models/post.rb
class Post < ApplicationRecord
has_many :pictures, dependent: :destroy
accepts_nested_attributes_for :pictures, allow_destroy: true
end
# app/models/picture.rb
class Picture < ApplicationRecord
belongs_to :post
mount_uploader :name, PictureUploader
validates :name, presence: true
end
Post (記事)は複数の Picture を持つことができる。
また、 Post が削除されるとそれに紐づく Picture も削除される。
コントローラー
# app/controllers/admins/posts_controller.rb
class Admins::PostsController < ApplicationController
before_action :admin_user
PICTURE_COUNT = 3
def index
@posts = Post.all
end
def new
@post = current_admin.posts.build
PICTURE_COUNT.times { @post.pictures.build }
end
def create
@post = current_admin.posts.build(post_params)
if @post.save
flash[:notice] = "記事を投稿しました!"
redirect_to admins_dashboard_url
else
render action: :new
end
end
# --- 省略 ---
private
def post_params
params.require(:post).permit(:title, :content, :status, pictures_attributes: [:name])
end
end
current_admin は、 current_user と同じと考えてもらって良いです。
FactoryBot
# spec/factories/posts.rb
FactoryBot.define do
factory :post do
title { "MyTitle" }
content { "MyContent" }
association :admin
end
end
# spec/factories/pictures.rb
FactoryBot.define do
factory :picture do
name { [Rack::Test::UploadedFile.new(Rails.root.join('spec/support/testfile.png'), 'spec/support/testfile.png')] }
association :post
end
end
RSpec(失敗)
# spec/requests/admins/posts_request_spec.rb
context "with valid params" do
it "投稿・画像が登録されること" do
params = { pictures_attributes: [ attributes_for(:picture) ] }
expect do
post admins_posts_url, params: { post: attributes_for(:post).merge(params) }
end.to change(Post, :count).by(1).and change(Picture, :count).by(1)
end
end
試したこと
1 binding.pry で Post の数と Picture の数を確認しましたが、最初の binding.pry と Post create したときの binding.pry では数が変わりませんでした。
context "with valid params" do
it "投稿・画像が登録されること" do
binding.pry
params = { pictures_attributes: [ attributes_for(:picture) ] }
post admins_posts_url, params: { post: attributes_for(:post).merge(params) }
binding.pry
# expect do
# post admins_posts_url, params: { post: attributes_for(:post).merge(params) }
# end.to change(Post, :count).by(1).and change(Picture, :count).by(1)
end
end
2 paramsは取得できているか。上記の2回目の binding.pry の際、paramsの値を確認。
{:pictures_attributes=>
[{:name=>
[#<Rack::Test::UploadedFile:0x000055eb0bb81d60
@content_type="spec/support/testfile.png",
@original_filename="testfile.png",
@tempfile=#<File:/tmp/testfile20200616-785-43srvt.png>>]}]}
-
気になる質問をクリップする
クリップした質問は、後からいつでもマイページで確認できます。
またクリップした質問に回答があった際、通知やメールを受け取ることができます。
クリップを取り消します
-
良い質問の評価を上げる
以下のような質問は評価を上げましょう
- 質問内容が明確
- 自分も答えを知りたい
- 質問者以外のユーザにも役立つ
評価が高い質問は、TOPページの「注目」タブのフィードに表示されやすくなります。
質問の評価を上げたことを取り消します
-
評価を下げられる数の上限に達しました
評価を下げることができません
- 1日5回まで評価を下げられます
- 1日に1ユーザに対して2回まで評価を下げられます
質問の評価を下げる
teratailでは下記のような質問を「具体的に困っていることがない質問」、「サイトポリシーに違反する質問」と定義し、推奨していません。
- プログラミングに関係のない質問
- やってほしいことだけを記載した丸投げの質問
- 問題・課題が含まれていない質問
- 意図的に内容が抹消された質問
- 過去に投稿した質問と同じ内容の質問
- 広告と受け取られるような投稿
評価が下がると、TOPページの「アクティブ」「注目」タブのフィードに表示されにくくなります。
質問の評価を下げたことを取り消します
この機能は開放されていません
評価を下げる条件を満たしてません
質問の評価を下げる機能の利用条件
この機能を利用するためには、以下の事項を行う必要があります。
- 質問回答など一定の行動
-
メールアドレスの認証
メールアドレスの認証
-
質問評価に関するヘルプページの閲覧
質問評価に関するヘルプページの閲覧
まだ回答がついていません
15分調べてもわからないことは、teratailで質問しよう!
- ただいまの回答率 88.35%
- 質問をまとめることで、思考を整理して素早く解決
- テンプレート機能で、簡単に質問をまとめられる
質問への追記・修正の依頼
Mugheart
2020/06/16 11:48
提示されている「エラーメッセージ」はエラーメセージではなく、単にテストに失敗した結果なので、そこから得られる情報は少なく、その原因を回答者が探すとなると憶測で考えなければいけない部分が多いため負担が大きいです。
まずは、なぜレコードが登録されていないのかの原因を明らかにしてください。
方法としては、ログを確認してみたり、例外を出力してみたり、binding.pry の中で実際に同じパラメータで登録を試してみたり...。
原因がわかれば解決方法も自ずとわかるとは思いますが...。
mikannOishiii
2020/06/16 14:32
ご指摘ありがとうございます。その通りですね…思考停止していました。
エラーログを追加したのでご確認いただけると嬉しいです。
Mugheart
2020/06/16 15:59
spec/factories/pictures.rb
Picture name の値が配列なのは意図的ですか?正しい値ですか?
mikannOishiii
2020/06/16 16:22
意図的…ではないです!!
配列じゃなくしたら、通りました…!!凡ミスですすいません…!!!!