Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 2 additions & 0 deletions Gemfile
Original file line number Diff line number Diff line change
Expand Up @@ -133,3 +133,5 @@ group :test do
gem "parallel_rspec"
gem "spring-prspec"
end

gem "mobility", "~> 1.3"
5 changes: 5 additions & 0 deletions Gemfile.lock
Original file line number Diff line number Diff line change
Expand Up @@ -286,6 +286,9 @@ GEM
matrix (0.4.2)
mini_mime (1.1.5)
minitest (5.25.5)
mobility (1.3.2)
i18n (>= 0.6.10, < 2)
request_store (~> 1.0)
msgpack (1.8.0)
multi_xml (0.7.2)
bigdecimal (~> 3.1)
Expand Down Expand Up @@ -623,6 +626,7 @@ DEPENDENCIES
govuk_notify_rails
i18n-tasks (~> 1.0.15)
lograge
mobility (~> 1.3)
omniauth-auth0
omniauth-rails_csrf_protection
pagy
Expand Down Expand Up @@ -741,6 +745,7 @@ CHECKSUMS
matrix (0.4.2) sha256=71083ccbd67a14a43bfa78d3e4dc0f4b503b9cc18e5b4b1d686dc0f9ef7c4cc0
mini_mime (1.1.5) sha256=8681b7e2e4215f2a159f9400b5816d85e9d8c6c6b491e96a12797e798f8bccef
minitest (5.25.5) sha256=391b6c6cb43a4802bfb7c93af1ebe2ac66a210293f4a3fb7db36f2fc7dc2c756
mobility (1.3.2) sha256=32fbbb0e53118ef42de20daa6ac94dbb758c628874092eba311b968a1e1d757b
msgpack (1.8.0) sha256=e64ce0212000d016809f5048b48eb3a65ffb169db22238fb4b72472fecb2d732
multi_xml (0.7.2) sha256=307a96dc48613badb7b2fc174fd4e62d7c7b619bc36ea33bfd0c49f64f5787ce
mutex_m (0.3.0) sha256=cfcb04ac16b69c4813777022fdceda24e9f798e48092a2b817eb4c0a782b0751
Expand Down
6 changes: 6 additions & 0 deletions app/models/condition.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
class Condition < ApplicationRecord
include ConditionMethods
extend Mobility

belongs_to :routing_page, class_name: "Page"
belongs_to :check_page, class_name: "Page", optional: true
belongs_to :goto_page, class_name: "Page", optional: true
Expand All @@ -8,6 +10,10 @@ class Condition < ApplicationRecord

before_destroy :destroy_postconditions

translates :answer_value,
:exit_page_heading
translates :exit_page_markdown, presence: false # Without presence here, the value is nil if set to ""

def self.create_and_update_form!(...)
condition = Condition.new(...)
condition.save_and_update_form
Expand Down
21 changes: 18 additions & 3 deletions app/models/form.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,6 @@
class Form < ApplicationRecord
include FormStateMachine
extend Mobility

has_many :pages, -> { order(position: :asc) }, dependent: :destroy
has_one :form_submission_email, dependent: :destroy
Expand All @@ -10,6 +11,16 @@ class Form < ApplicationRecord
has_one :draft_form_document, -> { where tag: "draft" }, class_name: "FormDocument"
has_many :conditions, through: :pages, source: :routing_conditions

translates :name,
:privacy_policy_url,
:support_email,
:support_phone,
:support_url,
:support_url_text,
:declaration_text,
:what_happens_next_markdown,
:payment_url

enum :submission_type, {
email: "email",
email_with_csv: "email_with_csv",
Expand Down Expand Up @@ -56,9 +67,13 @@ def has_been_archived

alias_method :is_archived?, :has_been_archived

def name=(val)
super(val)
self[:form_slug] = name.parameterize
# We need to include the splat operator as second argument,
# since Mobility expects this when using locale setters like `name_cy=`
def name=(val, ...)
super

# Always set form_slug using the English name
self[:form_slug] = name_en.parameterize
end

# form_slug is always set based on name
Expand Down
11 changes: 11 additions & 0 deletions app/models/page.rb
Original file line number Diff line number Diff line change
@@ -1,4 +1,5 @@
class Page < ApplicationRecord
extend Mobility
before_destroy :destroy_secondary_skip_conditions

belongs_to :form
Expand All @@ -7,6 +8,12 @@ class Page < ApplicationRecord
has_many :goto_conditions, class_name: "Condition", foreign_key: "goto_page_id", dependent: :destroy
acts_as_list scope: :form

translates :question_text,
:hint_text,
:answer_settings,
:page_heading,
:guidance_markdown

ANSWER_TYPES = %w[name organisation_name email phone_number national_insurance_number address date selection number text file].freeze

ANSWER_TYPES_WITHOUT_SETTINGS = %w[organisation_name email phone_number national_insurance_number number].freeze
Expand All @@ -24,6 +31,10 @@ class Page < ApplicationRecord
validate :guidance_markdown_length_and_tags

attribute :answer_settings, DataStructType.new
# Open the Model class used for tanslations and make the same change to the answer_settings attribute
class Translation
attribute :answer_settings, DataStructType.new
end

def self.create_and_update_form!(...)
page = Page.new(...)
Expand Down
4 changes: 4 additions & 0 deletions config/application.rb
Original file line number Diff line number Diff line change
Expand Up @@ -71,5 +71,9 @@ class Application < Rails::Application

# Include full precision of timestamps in JSON responses
config.active_support.time_precision = 6

# Turn off locale enforcement - this allows us to use locales
# in Mobility without enabling those languages for the admin UI
I18n.enforce_available_locales = false
end
end
129 changes: 129 additions & 0 deletions config/initializers/mobility.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,129 @@
Mobility.configure do
# PLUGINS
plugins do
# Backend
#
# Sets the default backend to use in models. This can be overridden in models
# by passing +backend: ...+ to +translates+.
#
# To default to a different backend globally, replace +:key_value+ by another
# backend name.
#
backend :table

# ActiveRecord
#
# Defines ActiveRecord as ORM, and enables ActiveRecord-specific plugins.
active_record

# Accessors
#
# Define reader and writer methods for translated attributes. Remove either
# to disable globally, or pass +reader: false+ or +writer: false+ to
# +translates+ in any translated model.
#
reader
writer

# Backend Reader
#
# Defines reader to access the backend for any attribute, of the form
# +<attribute>_backend+.
#
backend_reader
#
# Or pass an interpolation string to define a different pattern:
# backend_reader "%s_translations"

# Query
#
# Defines a scope on the model class which allows querying on
# translated attributes. The default scope is named +i18n+, pass a different
# name as default to change the global default, or to +translates+ in any
# model to change it for that model alone.
#
query

# Cache
#
# Comment out to disable caching reads and writes.
#
cache

# Dirty
#
# Uncomment this line to include and enable globally:
# dirty
#
# Or uncomment this line to include but disable by default, and only enable
# per model by passing +dirty: true+ to +translates+.
# dirty false

# Column Fallback
#
# Uncomment line below to fallback to original column. You can pass
# +column_fallback: true+ to +translates+ to return original column on
# default locale, or pass +column_fallback: [:en, :de]+ to +translates+
# to return original column for those locales or pass
# +column_fallback: ->(locale) { ... }+ to +translates to evaluate which
# locales to return original column for.
# column_fallback
#
# Or uncomment this line to enable column fallback with a global default.
column_fallback true

# Fallbacks
#
# Uncomment line below to enable fallbacks, using +I18n.fallbacks+.
# fallbacks
#
# Or uncomment this line to enable fallbacks with a global default.
fallbacks(cy: :en)

# Presence
#
# Converts blank strings to nil on reads and writes. Comment out to
# disable.
#
presence

# Default
#
# Set a default translation per attributes. When enabled, passing +default:
# 'foo'+ sets a default translation string to show in case no translation is
# present. Can also be passed a proc.
#
# default 'foo'

# Fallthrough Accessors
#
# Uses method_missing to define locale-specific accessor methods like
# +title_en+, +title_en=+, +title_fr+, +title_fr=+ for each translated
# attribute. If you know what set of locales you want to support, it's
# generally better to use Locale Accessors (or both together) since
# +method_missing+ is very slow. (You can use both fallthrough and locale
# accessor plugins together without conflict.)
#
# fallthrough_accessors

# Locale Accessors
#
# Uses +def+ to define accessor methods for a set of locales. By default uses
# +I18n.available_locales+, but you can pass the set of locales with
# +translates+ and/or set a global default here.
#
# locale_accessors
#
# Or define specific defaults by uncommenting line below
locale_accessors %i[en cy]

# Attribute Methods
#
# Adds translated attributes to +attributes+ hash, and defines methods
# +translated_attributes+ and +untranslated_attributes+ which return hashes
# with translated and untranslated attributes, respectively. Be aware that
# this plugin can create conflicts with other gems.
#
# attribute_methods
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
class CreateFormTranslationsForMobilityTableBackend < ActiveRecord::Migration[8.0]
def change
create_table :form_translations do |t|
# Translated attribute(s)
t.text :name
t.text :privacy_policy_url
t.text :support_email
t.text :support_phone
t.text :support_url
t.text :support_url_text
t.text :declaration_text
t.text :what_happens_next_markdown
t.string :payment_url

t.string :locale, null: false
t.references :form, null: false, foreign_key: true, index: false

t.timestamps null: false
end

add_index :form_translations, :locale, name: :index_form_translations_on_locale
add_index :form_translations, %i[form_id locale], name: :index_form_translations_on_form_id_and_locale, unique: true
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,20 @@
class CreatePageTranslationsForMobilityTableBackend < ActiveRecord::Migration[8.0]
def change
create_table :page_translations do |t|
# Translated attribute(s)
t.text :question_text
t.text :hint_text
t.jsonb :answer_settings
t.text :page_heading
t.text :guidance_markdown

t.string :locale, null: false
t.references :page, null: false, foreign_key: true, index: false

t.timestamps null: false
end

add_index :page_translations, :locale, name: :index_page_translations_on_locale
add_index :page_translations, %i[page_id locale], name: :index_page_translations_on_page_id_and_locale, unique: true
end
end
Original file line number Diff line number Diff line change
@@ -0,0 +1,18 @@
class CreateConditionTranslationsForMobilityTableBackend < ActiveRecord::Migration[8.0]
def change
create_table :condition_translations do |t|
# Translated attribute(s)
t.string :answer_value
t.text :exit_page_markdown
t.text :exit_page_heading

t.string :locale, null: false
t.references :condition, null: false, foreign_key: true, index: false

t.timestamps null: false
end

add_index :condition_translations, :locale, name: :index_condition_translations_on_locale
add_index :condition_translations, %i[condition_id locale], name: :index_condition_translations_on_condition_id_and_locale, unique: true
end
end
Loading