##はじめに
ポートフォリオの機能を一通り実装し終えたので、Everyday Railsで勉強をしながらRspecでテストを書き始めました。
モデルスペックを書き終え、コントローラスペックを書いている際に「attributes_for」に出会い、ちょっと詰まったので記事にします。
##attributes_forとは
Everyday Railsによると、「プロジェクトファクトリからテスト用の属性値をハッシュとして作成します。」、だそうです。
最初の感想としては、「なんのために???buildでよくない???」でした。
##まずは見てみよう
buildとattrubutes_forの違いを以下に示します。
まずはFactoryの中身です。
FactoryBot.define do
factory :user do
name "test"
sequence(:email) { |n| "test#{n}@test.com"}
password "password"
end
end
FactoryBot.define do
factory :post do
content 'test content'
association :user
end
end
これらを用いたbuildとattributes_forで取得するデータの違いが以下の通りです。
> FactoryBot.build(:post)
=> #<Post id: nil, content: "test content", user_id: 8, created_at: nil, updated_at: nil>
> FactoryBot.attributes_for(:post)
=> {:name=>"test", :email=>"test2@test.com", :password=>"password"}
buildはモデルオブジェクト、attributes_forはハッシュとなっていますね。(間違えてたら教えてください)
##つまり
パラメータとして値を渡す場合、ハッシュを使って渡すことができます。複数のパラメータを送信する場合に、個々にパラメータ名を付けるのではなく、キーと値を組み合わせたハッシュとして渡せます。
これは実際に見てもらったほうがわかりやすいと思います。
#省略
describe "#create" do
context "ログインユーザーとして" do
before do
@user = FactoryBot.create(:user)
end
it "投稿ができる" do
post_params = FactoryBot.attributes_for(:post)
sign_in @user
expect{
post :create, params: { post: post_params}
}.to change(@user.posts, :count).by(1)
end
end
end
このプログラムの、post :create, params: { post: post_params}に注目してください。
これは、
post :create, params: { post: {:name=>"test", :email=>"test2@test.com", :password=>"password"} }
このプログラムと同義となります。
つまり、POSTメソッドで渡すparamsにpostキーを渡し、そのpostキーのValueをattributes_forの返り値であるハッシュを渡すことで、このように簡潔に書くことができます。(説明下手ですみません...)
上記より、buildではなくattributes_forを使用している意味がわかりました。
##最後に
私はまだ業界未経験で、なおかつRspecを書き始めて2日目です。
間違えている部分などありましたら、教えてもらえると非常に助かります。
以上です。