diff --git a/app/controllers/concerns/findable_foi_request.rb b/app/controllers/concerns/findable_foi_request.rb index a5a086ca..cc98cef6 100644 --- a/app/controllers/concerns/findable_foi_request.rb +++ b/app/controllers/concerns/findable_foi_request.rb @@ -9,20 +9,32 @@ module FindableFoiRequest extend ActiveSupport::Concern included do - before_action :set_foi_request, :redirect_if_missing_request - private - def set_foi_request - @foi_request = FoiRequest. - includes(:contact). - references(:contact). - find_by(id: params.require(:request_id)) + def find_foi_request + @foi_request = foi_request_from_session(scope: FoiRequest.unqueued) + redirect_if_missing_request + end + + def find_queued_foi_request + @foi_request = foi_request_from_session(scope: FoiRequest.queued) + redirect_if_missing_request + end + + def foi_request_from_session(scope: FoiRequest) + scope. + includes(:contact). + references(:contact). + find_by(id: session[:request_id]) end def redirect_if_missing_request return if @foi_request redirect_to new_foi_request_path end + + def store_foi_request_in_session + session[:request_id] = @foi_request.id + end end end diff --git a/app/controllers/foi/contacts_controller.rb b/app/controllers/foi/contacts_controller.rb index 8d7b56d4..5d5d4450 100644 --- a/app/controllers/foi/contacts_controller.rb +++ b/app/controllers/foi/contacts_controller.rb @@ -8,6 +8,7 @@ module Foi class ContactsController < ApplicationController include FindableFoiRequest + before_action :find_foi_request before_action :redirect_if_exisiting_contact, only: %i[new create] before_action :new_contact, only: %i[new create] before_action :find_contact, only: %i[edit update] @@ -16,7 +17,7 @@ def new; end def create if @contact.update(contact_params) - redirect_to foi_request_preview_path(@foi_request) + redirect_to preview_foi_request_path else render :new end @@ -26,7 +27,7 @@ def edit; end def update if @contact.update(contact_params) - redirect_to foi_request_preview_path(@foi_request) + redirect_to preview_foi_request_path else render :edit end @@ -36,7 +37,7 @@ def update def redirect_if_exisiting_contact return unless @foi_request.contact - redirect_to edit_foi_request_contact_path(@foi_request) + redirect_to edit_foi_request_contact_path end def new_contact diff --git a/app/controllers/foi/requests_controller.rb b/app/controllers/foi/requests_controller.rb index 5c16ced0..658683d8 100644 --- a/app/controllers/foi/requests_controller.rb +++ b/app/controllers/foi/requests_controller.rb @@ -5,6 +5,8 @@ module Foi # This controller is responsible for creating and updating of FOI requests. # class RequestsController < ApplicationController + include FindableFoiRequest + before_action :new_foi_request, only: %i[new create] before_action :find_foi_request, only: %i[edit update] @@ -14,7 +16,8 @@ def new; end def create if @foi_request.update(foi_request_params) - redirect_to foi_request_suggestions_path(@foi_request) + store_foi_request_in_session + redirect_to foi_request_suggestions_path else render :new end @@ -24,7 +27,7 @@ def edit; end def update if @foi_request.update(foi_request_params) - redirect_to foi_request_suggestions_path(@foi_request) + redirect_to foi_request_suggestions_path else render :edit end @@ -36,10 +39,6 @@ def new_foi_request @foi_request = FoiRequest.new end - def find_foi_request - @foi_request = FoiRequest.find(params.require(:id)) - end - def foi_request_params params.require(:foi_request).permit(:body) end diff --git a/app/controllers/foi/submissions_controller.rb b/app/controllers/foi/submissions_controller.rb index 395ce3a1..a439b5c4 100644 --- a/app/controllers/foi/submissions_controller.rb +++ b/app/controllers/foi/submissions_controller.rb @@ -8,12 +8,20 @@ module Foi class SubmissionsController < ApplicationController include FindableFoiRequest + before_action :find_foi_request, only: %i[new create] + before_action :find_queued_foi_request, only: %i[show] before_action :redirect_if_missing_contact + before_action :new_submission, only: %i[new create] + before_action :find_submission, only: %i[show] def new; end def create - redirect_to foi_request_sent_path(@foi_request) + if @submission.queue + redirect_to sent_foi_request_path + else + render :new + end end def show; end @@ -22,7 +30,15 @@ def show; end def redirect_if_missing_contact return if @foi_request.contact - redirect_to new_foi_request_contact_path(@foi_request) + redirect_to new_foi_request_contact_path + end + + def new_submission + @submission = @foi_request.build_submission + end + + def find_submission + @submission = @foi_request.submission end end end diff --git a/app/controllers/foi/suggestions_controller.rb b/app/controllers/foi/suggestions_controller.rb index ed40ea70..d1250884 100644 --- a/app/controllers/foi/suggestions_controller.rb +++ b/app/controllers/foi/suggestions_controller.rb @@ -8,6 +8,8 @@ module Foi class SuggestionsController < ApplicationController include FindableFoiRequest + before_action :find_foi_request + def index; end end end diff --git a/app/models/foi_request.rb b/app/models/foi_request.rb index dcae2127..4ab4a6b3 100644 --- a/app/models/foi_request.rb +++ b/app/models/foi_request.rb @@ -8,4 +8,14 @@ class FoiRequest < ApplicationRecord belongs_to :submission, optional: true, dependent: :destroy validates :body, presence: true + + scope :unqueued, lambda { + left_joins(:submission). + where(submissions: { state: [nil, Submission::UNQUEUED] }) + } + + scope :queued, lambda { + left_joins(:submission). + where.not(submissions: { state: [nil, Submission::UNQUEUED] }) + } end diff --git a/app/models/submission.rb b/app/models/submission.rb index cd1a4ba7..9a990be5 100644 --- a/app/models/submission.rb +++ b/app/models/submission.rb @@ -5,7 +5,14 @@ # software. # class Submission < ApplicationRecord + UNQUEUED = 'unqueued' + QUEUED = 'queued' + has_one :foi_request, dependent: :destroy validates :state, presence: true + + def queue + update(state: QUEUED) + end end diff --git a/app/views/foi/submissions/new.html.erb b/app/views/foi/submissions/new.html.erb index 047fdb93..6a5969a4 100644 --- a/app/views/foi/submissions/new.html.erb +++ b/app/views/foi/submissions/new.html.erb @@ -40,8 +40,8 @@
- <%= link_to 'Continue with request', new_foi_request_contact_path(@foi_request), class: 'button' %> + <%= link_to 'Continue with request', new_foi_request_contact_path, class: 'button' %>
diff --git a/config/routes.rb b/config/routes.rb index 50263094..052aa009 100644 --- a/config/routes.rb +++ b/config/routes.rb @@ -1,17 +1,20 @@ # frozen_string_literal: true Rails.application.routes.draw do - root to: redirect('foi/requests') + root to: redirect('foi') namespace :foi do - root to: redirect('foi/requests') - resources :requests, except: %i[show destroy] do + root to: 'requests#index' + resource :request, except: %i[show destroy] do + root to: redirect('foi/request/new') resources :suggestions, only: %i[index] - get 'contact', to: redirect('foi/requests/%{request_id}/contact/new') + get 'contact', to: redirect('foi/request/contact/new') resource :contact, except: %i[show destroy] get 'preview', to: 'submissions#new', as: 'preview' post 'send', to: 'submissions#create', as: 'send' get 'sent', to: 'submissions#show', as: 'sent' end end + + resolve('FoiRequest') { %i[foi request] } end diff --git a/spec/controllers/concerns/findable_foi_request_spec.rb b/spec/controllers/concerns/findable_foi_request_spec.rb index 373033d8..21d03143 100644 --- a/spec/controllers/concerns/findable_foi_request_spec.rb +++ b/spec/controllers/concerns/findable_foi_request_spec.rb @@ -10,19 +10,21 @@ controller(ApplicationController) do include FindableFoiRequest + before_action :find_foi_request + def index - redirect_to edit_foi_request_path(@foi_request) + redirect_to edit_foi_request_path end end describe 'GET #index' do - subject { get :index, params: { request_id: '1' } } + subject { get :index, session: { request_id: '1' } } context 'with foi_request' do it 'finds FOI request and sets instance variable' do expect(foi_request_scope).to receive(:find_by). with(id: '1').and_return(foi_request) - is_expected.to redirect_to(edit_foi_request_path(foi_request)) + is_expected.to redirect_to(edit_foi_request_path) end end diff --git a/spec/controllers/foi/contacts_controller_spec.rb b/spec/controllers/foi/contacts_controller_spec.rb index b53e6680..361a59f9 100644 --- a/spec/controllers/foi/contacts_controller_spec.rb +++ b/spec/controllers/foi/contacts_controller_spec.rb @@ -16,14 +16,14 @@ end describe 'GET #new' do - subject { get :new, params: { request_id: '1' } } + subject { get :new, session: { request_id: '1' } } before { allow(foi_request).to receive(:contact).and_return(nil) } context 'existing contact' do before { allow(foi_request).to receive(:contact).and_return(double) } it 'redirects to edit contact' do - is_expected.to redirect_to(edit_foi_request_contact_path(foi_request)) + is_expected.to redirect_to(edit_foi_request_contact_path) end end @@ -41,9 +41,7 @@ end context 'existing contact' do - subject do - post :create, params: { request_id: '1' } - end + subject { post :create, session: { request_id: '1' } } before { allow(foi_request).to receive(:contact).and_return(double) } it 'does not receive attributes' do @@ -52,13 +50,14 @@ end it 'redirects to edit contact' do - is_expected.to redirect_to(edit_foi_request_contact_path(foi_request)) + is_expected.to redirect_to(edit_foi_request_contact_path) end end context 'valid parameters' do subject do - post :create, params: { request_id: '1', contact: valid_params } + post :create, params: { contact: valid_params }, + session: { request_id: '1' } end before { allow(contact).to receive(:update).and_return(true) } @@ -69,13 +68,14 @@ end it 'redirects to foi_request' do - is_expected.to redirect_to(foi_request_preview_path(foi_request)) + is_expected.to redirect_to(preview_foi_request_path) end end context 'invalid parameters' do subject do - post :create, params: { request_id: '1', contact: invalid_params } + post :create, params: { contact: invalid_params }, + session: { request_id: '1' } end before { allow(contact).to receive(:update).and_return(false) } @@ -86,7 +86,7 @@ end describe 'GET #edit' do - subject { get :edit, params: { request_id: '1' } } + subject { get :edit, session: { request_id: '1' } } it 'returns http success' do is_expected.to have_http_status(200) @@ -98,7 +98,8 @@ context 'valid parameters' do subject do - put :update, params: { request_id: '1', contact: valid_params } + put :update, params: { contact: valid_params }, + session: { request_id: '1' } end before { allow(contact).to receive(:update).and_return(true) } @@ -109,13 +110,14 @@ end it 'redirects to foi_request' do - is_expected.to redirect_to(foi_request_preview_path(foi_request)) + is_expected.to redirect_to(preview_foi_request_path) end end context 'invalid parameters' do subject do - put :update, params: { request_id: '1', contact: invalid_params } + put :update, params: { contact: invalid_params }, + session: { request_id: '1' } end before { allow(contact).to receive(:update).and_return(false) } diff --git a/spec/controllers/foi/requests_controller_spec.rb b/spec/controllers/foi/requests_controller_spec.rb index 6b5abd17..93654091 100644 --- a/spec/controllers/foi/requests_controller_spec.rb +++ b/spec/controllers/foi/requests_controller_spec.rb @@ -3,6 +3,8 @@ require 'rails_helper' RSpec.describe Foi::RequestsController, type: :controller do + include_context 'FOI Request Scope' + let(:foi_request) { build_stubbed(:foi_request) } let(:valid_params) { { body: 'A request body' } } let(:invalid_params) { { invalid: true } } @@ -39,8 +41,12 @@ subject end + it 'stores request ID in the session' do + expect { subject }.to(change { session[:request_id] }) + end + it 'redirects to suggestions' do - is_expected.to redirect_to(foi_request_suggestions_path(foi_request)) + is_expected.to redirect_to(foi_request_suggestions_path) end end @@ -59,7 +65,7 @@ end describe 'GET #edit' do - subject { get :edit, params: { id: '1' } } + subject { get :edit, session: { request_id: '1' } } before do allow(FoiRequest).to receive(:find).with('1').and_return(foi_request) @@ -72,11 +78,15 @@ describe 'PUT #update' do before do - allow(FoiRequest).to receive(:find).with('1').and_return(foi_request) + allow(foi_request_scope).to receive(:find_by). + with(id: '1').and_return(foi_request) end context 'valid parameters' do - subject { put :update, params: { id: '1', foi_request: valid_params } } + subject do + put :update, params: { foi_request: valid_params }, + session: { request_id: '1' } + end before { allow(foi_request).to receive(:update).and_return(true) } it 'receives valid attributes' do @@ -86,12 +96,15 @@ end it 'redirects to suggestions' do - is_expected.to redirect_to(foi_request_suggestions_path(foi_request)) + is_expected.to redirect_to(foi_request_suggestions_path) end end context 'invalid parameters' do - subject { put :update, params: { id: '1', foi_request: invalid_params } } + subject do + put :update, params: { foi_request: invalid_params }, + session: { request_id: '1' } + end before { allow(foi_request).to receive(:update).and_return(false) } it 'returns http success' do diff --git a/spec/controllers/foi/submissions_controller_spec.rb b/spec/controllers/foi/submissions_controller_spec.rb index f2180383..9cafdfda 100644 --- a/spec/controllers/foi/submissions_controller_spec.rb +++ b/spec/controllers/foi/submissions_controller_spec.rb @@ -6,6 +6,7 @@ include_context 'FOI Request Scope' let(:foi_request) { build_stubbed(:foi_request) } + let(:submission) { build_stubbed(:submission) } before do allow(foi_request_scope).to receive(:find_by). @@ -17,13 +18,13 @@ let(:foi_request) { build_stubbed(:foi_request, contact: nil) } it 'redirects to new foi_request contact' do - is_expected.to redirect_to(new_foi_request_contact_path(foi_request)) + is_expected.to redirect_to(new_foi_request_contact_path) end end end describe 'GET #new' do - subject { get :new, params: { request_id: '1' } } + subject { get :new, session: { request_id: '1' } } include_examples 'redirect if missing contact' @@ -33,17 +34,37 @@ end describe 'POST #create' do - subject { post :create, params: { request_id: '1' } } + subject { post :create, session: { request_id: '1' } } + before do + allow(foi_request).to receive(:build_submission).and_return(submission) + end include_examples 'redirect if missing contact' - it 'redirects to foi_request sent' do - is_expected.to redirect_to(foi_request_sent_path(foi_request)) + context 'queueable' do + before { allow(submission).to receive(:queue).and_return(true) } + + it 'must queue submission' do + expect(submission).to receive(:queue) + subject + end + + it 'redirects to foi_request sent' do + is_expected.to redirect_to(sent_foi_request_path) + end + end + + context 'unqueueable' do + before { allow(submission).to receive(:queue).and_return(false) } + + it 'returns http success' do + is_expected.to have_http_status(200) + end end end describe 'GET #show' do - subject { get :show, params: { request_id: '1' } } + subject { get :show, session: { request_id: '1' } } include_examples 'redirect if missing contact' diff --git a/spec/controllers/foi/suggestions_controller_spec.rb b/spec/controllers/foi/suggestions_controller_spec.rb index 44780de7..030eab10 100644 --- a/spec/controllers/foi/suggestions_controller_spec.rb +++ b/spec/controllers/foi/suggestions_controller_spec.rb @@ -13,7 +13,7 @@ end describe 'GET #index' do - subject { get :index, params: { request_id: '1' } } + subject { get :index, session: { request_id: '1' } } it 'returns http success' do is_expected.to have_http_status(200) diff --git a/spec/factories/foi_requests.rb b/spec/factories/foi_requests.rb index fee2b5c5..82d1bd49 100644 --- a/spec/factories/foi_requests.rb +++ b/spec/factories/foi_requests.rb @@ -4,6 +4,13 @@ factory :foi_request do body 'How much did you spend on cycling infrastructure last year?' contact - submission + + trait :unqueued do + association :submission, :unqueued + end + + trait :queued do + association :submission, :queued + end end end diff --git a/spec/factories/submissions.rb b/spec/factories/submissions.rb index 739a047e..a9f1ea44 100644 --- a/spec/factories/submissions.rb +++ b/spec/factories/submissions.rb @@ -2,6 +2,12 @@ FactoryBot.define do factory :submission do - state 'unsent' + trait :unqueued do + state Submission::UNQUEUED + end + + trait :queued do + state Submission::QUEUED + end end end diff --git a/spec/models/foi_request_spec.rb b/spec/models/foi_request_spec.rb index 496c26d9..5923e356 100644 --- a/spec/models/foi_request_spec.rb +++ b/spec/models/foi_request_spec.rb @@ -20,7 +20,7 @@ end it 'removes Submission on destroy' do - request = create(:foi_request) + request = create(:foi_request, :unqueued) expect { request.destroy }.to change { Submission.count }.by(-1) end end @@ -32,4 +32,20 @@ expect(request.errors[:body]).to_not be_empty end end + + describe 'scopes' do + let!(:pending) { create(:foi_request) } + let!(:unqueued) { create(:foi_request, :unqueued) } + let!(:queued) { create(:foi_request, :queued) } + + describe '.unqueued' do + subject { FoiRequest.unqueued } + it { is_expected.to match [pending, unqueued] } + end + + describe '.queued' do + subject { FoiRequest.queued } + it { is_expected.to match [queued] } + end + end end diff --git a/spec/models/submission_spec.rb b/spec/models/submission_spec.rb index 2cb291d9..2bc1c6fc 100644 --- a/spec/models/submission_spec.rb +++ b/spec/models/submission_spec.rb @@ -11,7 +11,7 @@ end it 'removes FOI request on destroy' do - submission = create(:foi_request).submission + submission = create(:foi_request, :unqueued).submission expect { submission.destroy }.to change { FoiRequest.count }.by(-1) end end @@ -23,4 +23,18 @@ expect(submission.errors[:state]).to_not be_empty end end + + describe '#queue' do + let(:submission) { build(:submission) } + + it 'changes the state' do + expect { submission.queue }.to change(submission, :state). + to(Submission::QUEUED) + end + + it 'persists the change' do + expect { submission.queue }.to change(submission, :persisted?). + to(true) + end + end end diff --git a/spec/requests/foi_spec.rb b/spec/requests/foi_spec.rb index fe8cbf0e..c6286121 100644 --- a/spec/requests/foi_spec.rb +++ b/spec/requests/foi_spec.rb @@ -4,32 +4,23 @@ RSpec.describe 'foi namespace', type: :request do describe 'GET /' do - it 'redirects to requests index' do + it 'redirects to foi namespace' do get '/' - expect(response).to redirect_to('/foi/requests') + expect(response).to redirect_to('/foi') end end - describe 'GET /foi' do - it 'redirects to requests index' do - get '/foi' - expect(response).to redirect_to('/foi/requests') + describe 'GET /foi/request' do + it 'redirects to new request' do + get '/foi/request' + expect(response).to redirect_to('/foi/request/new') end end - describe 'GET /foi/request/:id/contact' do - include_context 'FOI Request Scope' - - let(:foi_request) { build_stubbed(:foi_request, contact: nil) } - - before do - allow(foi_request_scope).to receive(:find_by). - with(id: '1').and_return(foi_request) - end - - it 'redirects to requests index' do - get '/foi/requests/1/contact' - expect(response).to redirect_to('/foi/requests/1/contact/new') + describe 'GET /foi/request/contact' do + it 'redirects to new contact' do + get '/foi/request/contact' + expect(response).to redirect_to('/foi/request/contact/new') end end end diff --git a/spec/support/context.rb b/spec/support/context.rb index cca1de12..4e896094 100644 --- a/spec/support/context.rb +++ b/spec/support/context.rb @@ -9,7 +9,12 @@ let(:foi_request_scope) { double(:foi_request_scope) } before do - allow(FoiRequest).to receive(:includes). + allow(FoiRequest).to receive(:unqueued). + and_return(foi_request_scope) + allow(FoiRequest).to receive(:queued). + and_return(foi_request_scope) + + allow(foi_request_scope).to receive(:includes). with(:contact).and_return(foi_request_scope) allow(foi_request_scope).to receive(:references). with(:contact).and_return(foi_request_scope)