前提・実現したいこと
accepts_nested_attributes_for を使って親子関係にある2つのモデルがある。
(親:Post, 子:Picture)
request_spec で create する際、Post も Picture も数が増えるというテストを書いて通したい。
なお、テストの書き方はこちらのQiitaの記事を参考にしました。
発生している問題・エラーメッセージ
terminal
1I, [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">]}]}} 2D, [2020-06-16T04:23:23.070685 #976] DEBUG -- : Unpermitted parameter: :name
name カラムに許可されていないパラメータを含んでいるからエラーという意味???
該当のソースコード
Model
rb
1# app/models/post.rb 2class Post < ApplicationRecord 3 has_many :pictures, dependent: :destroy 4 accepts_nested_attributes_for :pictures, allow_destroy: true 5end
rb
1# app/models/picture.rb 2class Picture < ApplicationRecord 3 belongs_to :post 4 mount_uploader :name, PictureUploader 5 validates :name, presence: true 6end
Post (記事)は複数の Picture を持つことができる。
また、 Post が削除されるとそれに紐づく Picture も削除される。
コントローラー
rb
1# app/controllers/admins/posts_controller.rb 2class Admins::PostsController < ApplicationController 3 before_action :admin_user 4 PICTURE_COUNT = 3 5 6 def index 7 @posts = Post.all 8 end 9 10 def new 11 @post = current_admin.posts.build 12 PICTURE_COUNT.times { @post.pictures.build } 13 end 14 15 def create 16 @post = current_admin.posts.build(post_params) 17 if @post.save 18 flash[:notice] = "記事を投稿しました!" 19 redirect_to admins_dashboard_url 20 else 21 render action: :new 22 end 23 end 24 25 # --- 省略 --- 26 27 private 28 29 def post_params 30 params.require(:post).permit(:title, :content, :status, pictures_attributes: [:name]) 31 end 32end
current_admin は、 current_user と同じと考えてもらって良いです。
FactoryBot
# spec/factories/posts.rb FactoryBot.define do factory :post do title { "MyTitle" } content { "MyContent" } association :admin end end
rb
1# spec/factories/pictures.rb 2FactoryBot.define do 3 factory :picture do 4 name { [Rack::Test::UploadedFile.new(Rails.root.join('spec/support/testfile.png'), 'spec/support/testfile.png')] } 5 association :post 6 end 7end
RSpec(失敗)
rb
1# spec/requests/admins/posts_request_spec.rb 2 3context "with valid params" do 4 it "投稿・画像が登録されること" do 5 params = { pictures_attributes: [ attributes_for(:picture) ] } 6 expect do 7 post admins_posts_url, params: { post: attributes_for(:post).merge(params) } 8 end.to change(Post, :count).by(1).and change(Picture, :count).by(1) 9 end 10end
試したこと
1 binding.pry で Post の数と Picture の数を確認しましたが、最初の binding.pry と Post create したときの binding.pry では数が変わりませんでした。
rb
1context "with valid params" do 2 it "投稿・画像が登録されること" do 3 binding.pry 4 params = { pictures_attributes: [ attributes_for(:picture) ] } 5 post admins_posts_url, params: { post: attributes_for(:post).merge(params) } 6 binding.pry 7 # expect do 8 # post admins_posts_url, params: { post: attributes_for(:post).merge(params) } 9 # end.to change(Post, :count).by(1).and change(Picture, :count).by(1) 10 end 11end
2 paramsは取得できているか。上記の2回目の binding.pry の際、paramsの値を確認。
terminal
1{:pictures_attributes=> 2 [{:name=> 3 [#<Rack::Test::UploadedFile:0x000055eb0bb81d60 4 @content_type="spec/support/testfile.png", 5 @original_filename="testfile.png", 6 @tempfile=#<File:/tmp/testfile20200616-785-43srvt.png>>]}]}
あなたの回答
tips
プレビュー