我正在制作提醒计划程序,并使用rails scaffold为提醒创建模型和视图。到目前为止,我的控制器看起来像这样:
class RemindersController < ApplicationController
before_action :set_reminder, only: [:show, :edit, :update, :destroy]
@@reminder_hash = {}
@@scheduler = Rufus::Scheduler.singleton
def index
@reminders = Reminder.all
end
def new
@reminder = Reminder.new
end
def edit
end
def create
@reminder = Reminder.new(reminder_params)
respond_to do |format|
if @reminder.save
format.html { redirect_to reminders_url, notice: I18n.t('Reminder was successfully created.') }
format.json { render :show, status: :created, location: @reminder }
schedule_reminder @reminder.id, @reminder.reminder_day, @reminder.reminder_time
else
format.html { render :new }
format.json { render json: @reminder.errors, status: :unprocessable_entity }
end
end
end
def update
respond_to do |format|
if @reminder.update(reminder_params)
# Unschedule the job.
jobs = @@scheduler.jobs(tag: @reminder.id)
jobs.each { |job| @@scheduler.unschedule(job) }
# Reschedule the job at the new time.
schedule_reminder @reminder.id, @reminder.reminder_day, @reminder.reminder_time
format.html { redirect_to reminders_url, notice: I18n.t('Reminder was successfully updated.') }
format.json { render :show, status: :ok, location: @reminder }
else
format.html { render :edit }
format.json { render json: @reminder.errors, status: :unprocessable_entity }
end
end
end
def destroy
@reminder.destroy
respond_to do |format|
jobs = @@scheduler.jobs(tag: @reminder.id)
jobs.each { |job| @@scheduler.unschedule(job) }
format.html { redirect_to reminders_url, notice: I18n.t('Reminder was successfully destroyed.') }
format.json { head :no_content }
end
end
# Internal: Schedule reminder to be sent at appropriate time.
#
# id - The Reminder id used to uniquely identify the job associated with that reminder.
# reminder day - The day when the reminder will be sent.
# reminder time - The time when the reminder will be sent.
#
# Returns nothing.
def schedule_reminder(tag, reminder_day, reminder_time)
minute = reminder_time.strftime('%M')
hour = reminder_time.strftime('%H')
day = reminder_day[0...3].upcase
cron_string = '0 ' + minute + ' ' + hour + ' * * ' + day
@@scheduler.cron cron_string, tag: tag do
EmailController.mentor_reminder_email_sender
end
end
private
# Use callbacks to share common setup or constraints between actions.
def set_reminder
@reminder = Reminder.find(params[:id])
end
# Whitelist the paramters.
def reminder_params
params.fetch(:reminder, {}).permit(:reminder_day, :reminder_time)
end
end
规范如下:
require 'rails_helper'
RSpec.describe RemindersController, type: :controller do
let(:valid_attributes) {
{ id: 1, reminder_day: :monday, reminder_time: Time.now}
}
let(:invalid_attributes) {
{ id: nil, reminder_day: nil, reminder_time: nil}
}
let(:valid_session) { {} }
describe 'DELETE #destroy' do
it 'destroys the requested reminder' do
reminder = Reminder.create! valid_attributes
expect {
delete :destroy, {id: reminder.to_param}, valid_session
}.to change(Reminder, :count).by(-1)
end
it 'does not call reminder scheduler function' do
post :create, {reminder: valid_attributes}, valid_session
expect(controller).to_not receive(:schedule_reminder)
end
it 'redirects to the reminders list' do
reminder = Reminder.create! valid_attributes
delete :destroy, {id: reminder.to_param}, valid_session
expect(response).to redirect_to(reminders_path)
end
end
describe '#create' do
let(:reminder) { Reminder.new(id: 1, reminder_day: 1, reminder_time: Time.now) }
let(:reminders_controller) { RemindersController.new }
context 'with valid params' do
before do
allow(controller).to receive(:schedule_reminder)
end
it 'creates a new Reminder' do
expect {
post :create, {reminder: valid_attributes}, valid_session
}.to change(Reminder, :count).by(1)
end
it 'assigns a newly created reminder as @reminder' do
post :create, {reminder: valid_attributes}, valid_session
expect(assigns(:reminder)).to be_a(Reminder)
expect(assigns(:reminder)).to be_persisted
end
it 'calls schedule_reminder with correct parameters' do
expect(reminders_controller).to receive(:schedule_reminder)
.with(reminder.id, reminder.reminder_day, reminder.reminder_time)
reminders_controller.schedule_reminder(reminder.id, reminder.reminder_day, reminder.reminder_time)
end
end
context 'with invalid params' do
it 'assigns a newly created but unsaved reminder as @reminder' do
post :create, {reminder: invalid_attributes}, valid_session
expect(assigns(:reminder)).to be_a_new(Reminder)
end
it 're-renders the "new" template' do
post :create, {reminder: invalid_attributes}, valid_session
expect(response).to render_template('new')
end
it 'does not call schedule_reminder' do
expect(controller).to_not receive(:schedule_reminder)
end
end
end
describe 'PUT #update' do
context 'with valid params' do
let(:new_attributes) {
{ id: 2, reminder_day: :tuesday, reminder_time: Time.now}
}
let(:reminders_controller) { RemindersController.new }
let(:reminder) { Reminder.new(id: 1, reminder_day: 1, reminder_time: Time.now) }
it 'updates the requested reminder' do
reminder = Reminder.create! valid_attributes
put :update, { id: reminder.to_param, reminder: new_attributes}, valid_session
reminder.reload
end
it 'calls reminder scheduler function with correct parameters' do
post :create, {reminder: valid_attributes}, valid_session
expect(reminders_controller).to receive(:schedule_reminder)
.with(reminder.id, reminder.reminder_day, reminder.reminder_time)
reminders_controller.schedule_reminder(reminder.id, reminder.reminder_day, reminder.reminder_time)
end
it 'assigns the requested reminder as @reminder' do
reminder = Reminder.create! valid_attributes
put :update, { id: reminder.to_param, reminder: valid_attributes}, valid_session
expect(assigns(:reminder)).to eq(reminder)
end
it 'redirects to the reminder' do
reminder = Reminder.create! valid_attributes
put :update, { id: reminder.to_param, reminder: valid_attributes}, valid_session
expect(response).to redirect_to(reminders_path)
end
end
context 'with invalid params' do
it 'assigns the reminder as @reminder' do
reminder = Reminder.create! valid_attributes
put :update, {id: reminder.to_param, reminder: invalid_attributes}, valid_session
expect(assigns(:reminder)).to eq(reminder)
end
it 're-renders the "edit" template' do
reminder = Reminder.create! valid_attributes
put :update, {id: reminder.to_param, reminder: invalid_attributes}, valid_session
expect(response).to render_template('edit')
end
it 'does not call schedule_reminder' do
expect(controller).to_not receive(:schedule_reminder)
end
end
end
describe 'GET #index' do
it 'assigns all reminders as @reminders' do
reminder = Reminder.create! valid_attributes
get :index, {}, valid_session
expect(assigns(:reminders)).to eq([reminder])
end
end
describe 'GET #new' do
it 'assigns a new reminder as @reminder' do
get :new, {}, valid_session
expect(assigns(:reminder)).to be_a_new(Reminder)
end
end
describe 'GET #edit' do
context 'when reminder is found' do
it 'assigns the requested reminder as @reminder' do
reminder = Reminder.create! valid_attributes
get :edit, {id: reminder.to_param}, valid_session
expect(assigns(:reminder)).to eq(reminder)
end
end
context 'when reminder is not found' do
it 're-renders the "edit" template' do
reminder = Reminder.create! valid_attributes
put :update, {id: reminder.to_param, reminder: invalid_attributes}, valid_session
expect(response).to render_template('edit')
end
end
end
end
我试图用mock / double替换所有的create语句以消除数据库调用。我试过用这个替换所有的create语句:
reminder = double('Reminder', id: 1, reminder_day: :monday, reminder_time: Time.now)
和其他变化。 我取代了这个:
describe 'DELETE #destroy' do
it 'destroys the requested reminder' do
reminder = Reminder.create! valid_attributes
expect {
delete :destroy, {id: reminder.to_param}, valid_session
}.to change(Reminder, :count).by(-1)
end
it 'does not call reminder scheduler function' do
post :create, {reminder: valid_attributes}, valid_session
expect(controller).to_not receive(:schedule_reminder)
end
it 'redirects to the reminders list' do
reminder = Reminder.create! valid_attributes
delete :destroy, {id: reminder.to_param}, valid_session
expect(response).to redirect_to(reminders_path)
end
end
用这个:
describe 'DELETE #destroy' do
let(:reminder){double('Reminder', id: 1, reminder_day: :monday, reminder_time: Time.now)}
before do
allow(Reminder).to receive(:create).and_return(reminder)
end
it 'destroys the requested reminder' do
reminder = Reminder.create
expect {
delete :destroy, {id: reminder.to_param}, valid_session
}.to change(Reminder, :count).by(-1)
end
it 'does not call reminder scheduler function' do
post :create, {reminder: valid_attributes}, valid_session
expect(controller).to_not receive(:schedule_reminder)
end
it 'redirects to the reminders list' do
reminder = Reminder.create
delete :destroy, {id: reminder.to_param}, valid_session
expect(response).to redirect_to(reminders_path)
end
end
我收到这些错误:
失败/错误:期望(响应).to redirect_to(reminders_path)
预期的响应是a,但是&lt; 404&gt;
失败/错误:期望{ 预期#count已更改为-1,但已更改为0