Skip to content

Commit ac6fc73

Browse files
authored
Merge pull request #2030 from govuk-forms/firebreak-build-journey-using-form-document-resource
Only consume StepResources when building the Journey
2 parents ebbaa34 + 9369a65 commit ac6fc73

29 files changed

Lines changed: 217 additions & 201 deletions
Lines changed: 31 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
module Forms
22
class BaseController < ApplicationController
3-
prepend_before_action :set_form
3+
prepend_before_action :prepare_context
44
around_action :set_locale
55

66
def redirect_to_friendly_url_start
@@ -15,7 +15,6 @@ def redirect_to_friendly_url_start
1515
end
1616

1717
def error_repeat_submission
18-
@current_context = Flow::Context.new(form: @form, store: session)
1918
render template: "errors/repeat_submission", locals: { form: @form }
2019
end
2120

@@ -27,9 +26,7 @@ def set_request_logging_attributes
2726

2827
private
2928

30-
def current_context
31-
@current_context ||= Flow::Context.new(form: @form, store: session)
32-
end
29+
attr_reader :current_context
3330

3431
def mode
3532
@mode ||= Mode.new(params[:mode])
@@ -43,29 +40,39 @@ def set_available_languages
4340
@available_languages = current_context.form.available_languages if current_context.form.multilingual?
4441
end
4542

46-
def set_form
47-
form_id = params.require(:form_id)
48-
@form = Api::V2::FormDocumentRepository.find_with_mode(form_id:, mode:, language: locale)
49-
50-
if @form.blank?
51-
I18n.with_locale(locale) do
52-
if locale == "cy"
53-
archived_welsh_version = Api::V2::FormDocumentRepository.find(form_id:, tag: :archived, language: :cy)
54-
live_english_version = Api::V2::FormDocumentRepository.find(form_id:, tag: :live, language: :en)
55-
56-
if archived_welsh_version.present? && live_english_version.present?
57-
return render template: "forms/archived_welsh/show",
58-
locals: { form: live_english_version },
59-
status: :not_found
60-
end
61-
end
43+
def prepare_context
44+
form_document = Api::V2::FormDocumentRepository.find_with_mode(form_id:, mode:, language: locale)
45+
46+
return handle_form_not_found if form_document.blank?
47+
48+
@form = Form.new(form_document)
49+
raise ActiveResource::ResourceNotFound, "Form has no steps" unless @form.start_page
50+
51+
@current_context = Flow::Context.new(form: @form, form_document:, store: session)
52+
end
6253

63-
archived_form = Api::V2::FormDocumentRepository.find(form_id:, tag: :archived)
64-
return render template: "forms/archived/show", locals: { form_name: archived_form.name }, status: :not_found if archived_form.present?
54+
def handle_form_not_found
55+
I18n.with_locale(locale) do
56+
if locale == "cy"
57+
archived_welsh_form_document = Api::V2::FormDocumentRepository.find(form_id:, tag: :archived, language: :cy)
58+
live_english_form_document = Api::V2::FormDocumentRepository.find(form_id:, tag: :live, language: :en)
59+
60+
if archived_welsh_form_document.present? && live_english_form_document.present?
61+
return render template: "forms/archived_welsh/show",
62+
locals: { form: Form.new(live_english_form_document) },
63+
status: :not_found
64+
end
6565
end
66+
67+
archived_form_document = Api::V2::FormDocumentRepository.find(form_id:, tag: :archived)
68+
return render template: "forms/archived/show", locals: { form_name: archived_form_document.name }, status: :not_found if archived_form_document.present?
6669
end
6770

68-
raise ActiveResource::ResourceNotFound, "Not Found" unless @form.present? && @form.start_page
71+
raise ActiveResource::ResourceNotFound, "Not Found"
72+
end
73+
74+
def form_id
75+
params.require(:form_id)
6976
end
7077
end
7178
end

app/controllers/forms/step_controller.rb

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,7 +51,7 @@ def save
5151
def prepare_step
5252
step_slug = params.require(:step_slug)
5353
begin
54-
@step = current_context.find_or_create(step_slug)
54+
@step = current_context.step_by_id(step_slug)
5555
rescue Flow::StepFactory::StepNotFoundError
5656
return redirect_to form_step_path(@form.id, @form.form_slug, current_context.next_step_slug)
5757
end
@@ -185,7 +185,7 @@ def check_goto_page_routing_error
185185
EventLogger.log_page_event(event_name, @step.question.question_text, nil)
186186

187187
routes_page_id = first_condition_with_error.check_page_id
188-
routes_page = @current_context.find_or_create(routes_page_id)
188+
routes_page = @current_context.step_by_id(routes_page_id)
189189

190190
render template: "errors/goto_page_routing_error", locals: {
191191
error_name: first_goto_error_name,

app/lib/flow/context.rb

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -2,15 +2,15 @@ module Flow
22
class Context
33
attr_reader :form, :journey
44

5-
def initialize(form:, store:)
5+
def initialize(form:, form_document:, store:)
66
@form = form
77
@answer_store = Store::SessionAnswerStore.new(store, form.id)
88
@confirmation_details_store = Store::ConfirmationDetailsStore.new(store, form.id)
9-
@journey = Journey.new(answer_store: @answer_store, form:)
9+
@journey = Journey.new(answer_store: @answer_store, form_document:)
1010
end
1111

1212
delegate :support_details, to: :form
13-
delegate :find_or_create, :previous_step, :next_step_slug, :next_step, :can_visit?, :completed_steps, :all_steps, to: :journey
13+
delegate :step_by_id, :previous_step, :next_step_slug, :next_step, :can_visit?, :completed_steps, :all_steps, to: :journey
1414
delegate :clear_stored_answer, :clear, :form_submitted?, :answers, :locales_used, to: :answer_store
1515
delegate :save_submission_details, :get_submission_reference, :requested_email_confirmation?, :clear_submission_details, :save_copy_of_answers_preference, :wants_copy_of_answers?, to: :confirmation_details_store
1616

app/lib/flow/errors.rb

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
# frozen_string_literal: true
2+
3+
module Flow
4+
module Errors
5+
class StepNotFoundError < StandardError
6+
def initialize(msg = "Step not found.")
7+
super
8+
end
9+
end
10+
end
11+
end

app/lib/flow/journey.rb

Lines changed: 19 additions & 11 deletions
Original file line numberDiff line numberDiff line change
@@ -17,20 +17,23 @@ module Flow
1717
# array will be empty.
1818

1919
class Journey
20-
attr_reader :completed_steps
20+
include Flow::Errors
2121

22-
def initialize(answer_store:, form:)
22+
attr_reader :completed_steps, :all_steps
23+
24+
def initialize(answer_store:, form_document:)
2325
@answer_store = answer_store
24-
@form = form
25-
@step_factory = StepFactory.new(form:)
26+
@form_document = form_document
27+
@step_factory = StepFactory.new(form_document:)
28+
# generate completed_steps first to load answers only for steps that will be visited taking routing into account
2629
@completed_steps = generate_completed_steps
30+
@all_steps = generate_all_steps
2731

2832
populate_file_suffixes
2933
end
3034

31-
def find_or_create(step_slug)
32-
step = completed_steps.find { |s| s.id == step_slug }
33-
step || @step_factory.create_step(step_slug)
35+
def step_by_id(id)
36+
@all_steps.find { |s| s.id.to_s == id.to_s } || raise(StepNotFoundError, "Can't find step #{id}")
3437
end
3538

3639
def previous_step(step_slug)
@@ -52,10 +55,6 @@ def can_visit?(step_slug)
5255
(completed_steps.map(&:id).include? step_slug) || step_slug == next_step_slug
5356
end
5457

55-
def all_steps
56-
@form.form_document_steps.map { |form_document_step| find_or_create(form_document_step.id.to_s) }
57-
end
58-
5958
def completed_file_upload_questions
6059
completed_steps
6160
.select { |step| step.question.is_a?(Question::File) && step.question.file_uploaded? }
@@ -125,5 +124,14 @@ def safe_load_from_store(step)
125124
original_step
126125
end
127126
end
127+
128+
def generate_all_steps
129+
@form_document.steps.map { |form_document_step| find_or_create(form_document_step.id.to_s) }
130+
end
131+
132+
def find_or_create(step_slug)
133+
step = completed_steps.find { |s| s.id == step_slug }
134+
step || @step_factory.create_step(step_slug)
135+
end
128136
end
129137
end

app/lib/flow/step_factory.rb

Lines changed: 6 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -1,26 +1,22 @@
11
module Flow
22
class StepFactory
3-
START_PAGE = "_start".freeze
3+
include Flow::Errors
44

5-
class StepNotFoundError < StandardError
6-
def initialize(msg = "Step not found.")
7-
super
8-
end
9-
end
5+
START_PAGE = "_start".freeze
106

11-
def initialize(form:)
12-
@form = form
7+
def initialize(form_document:)
8+
@form_document = form_document
139
end
1410

1511
def create_step(step_slug_or_start)
1612
# Normalize the id or constant passed in
17-
step_slug = step_slug_or_start.to_s == START_PAGE ? @form.start_page : step_slug_or_start
13+
step_slug = step_slug_or_start.to_s == START_PAGE ? @form_document.start_page : step_slug_or_start
1814
step_slug = step_slug.to_s
1915

2016
return CheckYourAnswersStep.new if step_slug == CheckYourAnswersStep::CHECK_YOUR_ANSWERS_STEP_SLUG
2117

2218
# for now, we use the step id as slug
23-
form_document_step = @form.form_document_steps.find { |s| s.id.to_s == step_slug }
19+
form_document_step = @form_document.steps.find { |s| s.id.to_s == step_slug }
2420
raise StepNotFoundError, "Can't find step #{step_slug}" if form_document_step.nil?
2521

2622
question = QuestionRegister.from_form_document_step(form_document_step)

app/models/form.rb

Lines changed: 3 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,10 @@
11
class Form
2-
attr_reader :document_json
32
private attr_reader :form_document
43

5-
def initialize(form_document, form_document_json = nil)
4+
def initialize(form_document)
65
@form_document = form_document
7-
@document_json = form_document_json
86
end
97

10-
delegate :steps, to: :form_document, prefix: true
118
delegate :declaration_text,
129
:form_id,
1310
:form_slug,
@@ -31,8 +28,8 @@ def initialize(form_document, form_document_json = nil)
3128

3229
alias_method :id, :form_id
3330

34-
def step_by_id(step_id)
35-
form_document_steps.find { |s| s.id == step_id }
31+
def document_json
32+
form_document.as_json
3633
end
3734

3835
def payment_url_with_reference(reference)

app/models/submission.rb

Lines changed: 6 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -25,7 +25,7 @@ class Submission < ApplicationRecord
2525
encrypts :answers
2626

2727
def journey
28-
@journey ||= Flow::Journey.new(answer_store:, form:)
28+
@journey ||= Flow::Journey.new(answer_store:, form_document: form_document_resource)
2929
end
3030

3131
def form
@@ -60,7 +60,10 @@ def answer_store
6060
end
6161

6262
def form_from_document
63-
form_document_resource = Api::V2::FormDocumentResource.new(form_document, true)
64-
Form.new(form_document_resource, form_document)
63+
Form.new(form_document_resource)
64+
end
65+
66+
def form_document_resource
67+
@form_document_resource ||= Api::V2::FormDocumentResource.new(form_document, true)
6568
end
6669
end

app/services/api/v2/form_document_repository.rb

Lines changed: 1 addition & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -5,8 +5,7 @@ def find(form_id:, tag:, language: :en)
55

66
begin
77
form_document_json = Api::V2::FormDocumentResource.get(form_id, tag, **options_for_language(language))
8-
form_document = Api::V2::FormDocumentResource.new(form_document_json)
9-
Form.new(form_document, form_document_json)
8+
Api::V2::FormDocumentResource.new(form_document_json)
109
rescue ActiveResource::ResourceNotFound
1110
nil
1211
end

app/services/form_submission_service.rb

Lines changed: 4 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -51,9 +51,11 @@ def ensure_form_english
5151
end
5252

5353
def fetch_english_language_form
54-
@form = Api::V2::FormDocumentRepository.find_with_mode(form_id: form.id, mode:)
54+
english_form_document = Api::V2::FormDocumentRepository.find_with_mode(form_id: form.id, mode:)
5555

56-
raise ActiveResource::ResourceNotFound.new(404, "Not Found") if @form.nil?
56+
raise ActiveResource::ResourceNotFound.new(404, "Not Found") if english_form_document.nil?
57+
58+
@form = Form.new(english_form_document)
5759
end
5860

5961
def validate_submission

0 commit comments

Comments
 (0)