やりたいこと
RSpecのテストの中で使える、多対多の関係を一括生成する
今回は
【 user -- group_user(中間テーブル) -- group 】
という関係を、userから一括生成します。
使っているgem
gem 'rspec-rails'
gem 'factory_girl_rails'
gem 'faker'
FakerとFactoryGirlを使ってデータを作成します。
その作成するときの方法でアソシエーションを組む感じです。
実装
コードはこんな感じです。
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
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
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が設定した値になるかどうかをテストします。
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なことを確かめている。)
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を生成したい。
class Message < ApplicationRecord
belongs_to :user
belongs_to :group
end
先にtemp_group = create(:group)
などとして
それを引数としてmessage, group_userに渡してやればできました。
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円のロボット。
これを付けてから目覚ましなしで起きられる率が上がった。
・衛藤美彩 写真集
「綺麗なお姉さん」が好きな人、ちょっと眺めてるだけで幸せになれますよ。