在我的Rails 5.1.6应用程序中,我在用户和事件之间创建了<div>
<p>Select vegetables</p>
<label><input type="checkbox" name="vegetables[]" value="potato"> Potato</label><br>
<label><input type="checkbox" name="vegetables[]" value="onion"> Onion</label><br>
<label><input type="checkbox" name="vegetables[]" value="tomato"> Tomato</label><br>
</div>
<div>
<p>Select seasoning</p>
<label><input type="checkbox" name="seasoning[]" value="salt"> Salt</label><br>
<label><input type="checkbox" name="seasoning[]" value="pepper"> Pepper</label><br>
<label><input type="checkbox" name="seasoning[]" value="chilli"> Chilli Flakes</label><br>
</div>
模型关联,以便用户可以参与给定事件。事件具有一个整数Attendance
属性,该属性在每次创建参与者时都会减少。出勤控制器为:
seats
我想测试before_action :logged_in_user
before_action :participants_limit, only: :create
def create
@attendance = current_user.attendances.build(attendance_params)
if @attendance.save
@event.decrement(:seats)
flash[:success] = "Congratulation! Your participation has been recorded."
redirect_back(fallback_location: root_url)
else
flash[:danger] = @event.errors.full_messages.join(', ')
redirect_back(fallback_location: root_url)
end
end
private
def attendance_params
params.require(:attendance).permit(:event_id)
end
def participants_limit
@event = Event.find(params[:attendance][:event_id])
if @event.seats == 0
flash[:danger] = 'Attention! Unfortunately this event is full!'
redirect_back(fallback_location: root_url)
end
end
控制器的创建动作,因此我创建了以下测试:
Attendance
测试在第def setup
@event = events(:event_1)
@user = users(:user_12)
end
test "should redirect create when participants limit reached" do
assert @event.participants.count == 2
assert @event.seats == 5
participants = (1..5).map do |num|
users("user_#{num}".to_sym)
end
participants.each do |user|
log_in_as(user)
post attendances_path, params: { attendance: { user_id: user.id, event_id: @event.id } }
end
assert @event.participants.count == 7
assert @event.seats == 0
log_in_as(@user)
assert_no_difference 'Attendance.count' do
post attendances_path, params: { attendance: { user_id: @user.id, event_id: @event.id } }
end
assert_redirected_to root_url
end
行失败:席位未减少,结果仍然为5:为什么?我想知道为什么递减方法不起作用,并且测试中是否缺少某些内容。
答案 0 :(得分:1)
您的@event
被缓存在内存中,控制器更改相应的数据库记录。
如果您期望@record.reload.seats
刚刚发生变化,请在测试中使用-这将从数据库中重新加载记录。
还请记住,如果两个参与者试图同时注册,您的代码很容易受到竞争条件的影响,请将整个检查更改代码块包装在event.with_lock
中以减轻这种情况。