LoginSignup
41
44

More than 5 years have passed since last update.

rspecのテスト環境で多対多のアソシエーションを一括生成する方法 +α

Last updated at Posted at 2017-01-22

やりたいこと

RSpecのテストの中で使える、多対多の関係を一括生成する

今回は
【 user -- group_user(中間テーブル) -- group 】
という関係を、userから一括生成します。

使っているgem

gem 'rspec-rails'
gem 'factory_girl_rails'
gem 'faker'

FakerとFactoryGirlを使ってデータを作成します。
その作成するときの方法でアソシエーションを組む感じです。

実装

コードはこんな感じです。

spec/factories/user.rb
FactoryGirl.define do
  pass = Faker::Internet.password(8)

  factory :user do
    name                  Faker::Name.name
    email                 Faker::Internet.email
    password              pass
    password_confirmation pass

    after(:create) do |user|
      create(:group_user, user: user, group: create(:group))
    end
  end
end
spec/factories/group.rb
FactoryGirl.define do
  factory :group do
    name
    created_at { Faker::Time.between(5.days.ago, 3.days.ago, :all) }
    updated_at { Faker::Time.between(2.days.ago, 1.days.ago, :all) }
  end
end
spec/factories/group_user.rb
FactoryGirl.define do
  factory :group_user do
    user
    group
  end
end

コード全体の流れ

ポイント

【中間テーブルgroup_userに引数としてuser、groupを渡すとアソシエーションできる】

userがcreateされる

after内の記述が動く

group_userが生成されそうになる

group_userのパラメータとしてgroupが生成される

user, groupが引数として入り、group_userが生成される

結果:
user, group, group_userが生成されて、
【 user -- group_user -- group 】のアソシエーションが組まれる。

実際にどう使えるか

やること

message_controllerの@groups = current_user.groupsという記述で、@groupsが設定した値になるかどうかをテストします。

message_controller.rb
class MessagesController < ApplicationController
  before_action :authenticate_user!

  def index
    @groups = current_user.groups
  end
end

コードの流れ

letの部分でuserをcreate(一括でgroup, group_userもcreate&アソシエーション)

before do でログイン(テスト内でのdeviseログインについてはこちら)

params[:group_id]を得るために、@groupを定義し、@group.idとする。
(これはrootingが/groups/:group_id/messages messages#indexとなっているため)

アソシエーションを利用しgroupsを定義(groups = user.groups)

@groupsと定義したgroupsの比較
(assigns(:groups)@groupsを意味し、.to eq groupsのgroupsは直前に定義したもの。この2つがeqなことを確かめている。)

message_controller_spec.rb
require 'rails_helper'

describe MessagesController, type: :controller do
  let(:user) { create(:user) }

  describe 'GET #index' do
    before do
      login_user user
    end

    it "assigns the requested contact to @groups" do
      @group = user.groups.first
      get :index, params: { group_id: @group.id }
      groups = user.groups
      expect(assigns(:groups)).to eq groups
    end
end

【+α】 groupとuserにbelongs_toなmessageを、さらに一括で生成する

やりたいこと

userを生成した時に、group_user、groupを一括生成、アソシエーションしつつ、
group, userとアソシエーションしたmessageを生成したい。

message.rb
class Message < ApplicationRecord
  belongs_to :user
  belongs_to :group
end

先にtemp_group = create(:group)などとして
それを引数としてmessage, group_userに渡してやればできました。

user.rb
FactoryGirl.define do
  pass = Faker::Internet.password(8)

  factory :user do
    name                  Faker::Name.name
    email                 Faker::Internet.email
    password              pass
    password_confirmation pass

    after(:create) do |user|
      temp_group = create(:group)
      # ここでgroupをcreateしてtemp_groupに入れる
      create(:message, user: user, group: temp_group)
      create(:group_user, user: user, group: temp_group)
    end
  end
end

番外編;最近買った、面白いもの

・ハンターハンター34巻(6/29)
クロロ VS ヒソカとか、どうやっても面白くなるとしか
・カーテン自動開閉ロボット
カーテンレールに付ける4000円のロボット。
これを付けてから目覚ましなしで起きられる率が上がった。
・衛藤美彩 写真集
「綺麗なお姉さん」が好きな人、ちょっと眺めてるだけで幸せになれますよ。

参考サイト様

41
44
2

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
41
44