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

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

ただいまの
回答率

88.35%

accepts_nested_attributes_for がモデルにあるときのRspecを通したい

受付中

回答 0

投稿 編集

  • 評価
  • クリップ 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ページの「アクティブ」「注目」タブのフィードに表示されにくくなります。

    質問の評価を下げたことを取り消します

    この機能は開放されていません

    評価を下げる条件を満たしてません

    評価を下げる理由を選択してください

    詳細な説明はこちら

    上記に当てはまらず、質問内容が明確になっていない質問には「情報の追加・修正依頼」機能からコメントをしてください。

    質問の評価を下げる機能の利用条件

    この機能を利用するためには、以下の事項を行う必要があります。

質問への追記・修正の依頼

  • 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

    意図的…ではないです!!
    配列じゃなくしたら、通りました…!!凡ミスですすいません…!!!!

    キャンセル

まだ回答がついていません

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

  • ただいまの回答率 88.35%
  • 質問をまとめることで、思考を整理して素早く解決
  • テンプレート機能で、簡単に質問をまとめられる

関連した質問

同じタグがついた質問を見る