Skip to content

Commit

Permalink
Merge pull request #90 from DFE-Digital/allow-plain-ruby-objects
Browse files Browse the repository at this point in the history
Allow the form builder to work with plain ruby objects
  • Loading branch information
peteryates committed Jan 7, 2020
2 parents f50cc5a + 7221b98 commit fcb56d1
Show file tree
Hide file tree
Showing 15 changed files with 121 additions and 9 deletions.
2 changes: 2 additions & 0 deletions .rubocop.yml
Expand Up @@ -17,3 +17,5 @@ Style/TrailingCommaInHashLiteral:
Enabled: false
Style/TrailingCommaInArrayLiteral:
Enabled: false
Naming/MethodParameterName:
Enabled: false
3 changes: 2 additions & 1 deletion lib/govuk_design_system_formbuilder/base.rb
Expand Up @@ -34,7 +34,8 @@ def field_id(link_errors: false)
end

def has_errors?
@builder.object.errors.any? &&
@builder.object.respond_to?(:errors) &&
@builder.object.errors.any? &&
@builder.object.errors.messages.dig(@attribute_name).present?
end

Expand Down
Expand Up @@ -38,6 +38,10 @@
it_behaves_like 'a field that supports setting the legend via localisation'
it_behaves_like 'a field that supports setting the hint via localisation'

it_behaves_like 'a field that accepts a plain ruby object' do
let(:described_element) { ['input', { with: { type: 'checkbox' }, count: projects.size }] }
end

describe 'check boxes' do
specify 'output should contain the correct number of check boxes' do
expect(subject).to have_tag('div', with: { 'data-module' => 'govuk-checkboxes' }) do |cb|
Expand Down
Expand Up @@ -28,6 +28,10 @@
it_behaves_like 'a field that supports setting the hint via localisation'
it_behaves_like 'a field that supports setting the legend via localisation'

it_behaves_like 'a field that accepts a plain ruby object' do
let(:described_element) { 'fieldset' }
end

context 'when no block is supplied' do
subject { builder.send(*args) }
specify { expect { subject }.to raise_error(NoMethodError, /undefined method.*call/) }
Expand Down
4 changes: 4 additions & 0 deletions spec/govuk_design_system_formbuilder/builder/date_spec.rb
Expand Up @@ -62,6 +62,10 @@
it_behaves_like 'a field that supports setting the legend via localisation'
it_behaves_like 'a field that supports setting the hint via localisation'

it_behaves_like 'a field that accepts a plain ruby object' do
let(:described_element) { ['input', { count: 3 }] }
end

specify 'should output a form group with fieldset, date group and 3 inputs and labels' do
expect(subject).to have_tag('div', with: { class: 'govuk-form-group' }) do |fg|
expect(fg).to have_tag('fieldset', with: { class: 'govuk-fieldset' }) do |fs|
Expand Down
Expand Up @@ -289,5 +289,14 @@
expect(subject).to be_nil
end
end

context 'when the object does not support errors' do
let(:object) { Guest.example }
subject { builder.send(method) }

specify 'an error should be raised' do
expect { subject }.to raise_error(NoMethodError, /errors/)
end
end
end
end
4 changes: 4 additions & 0 deletions spec/govuk_design_system_formbuilder/builder/file_spec.rb
Expand Up @@ -40,6 +40,10 @@
it_behaves_like 'a field that supports setting the label via localisation'
it_behaves_like 'a field that supports setting the hint via localisation'

it_behaves_like 'a field that accepts a plain ruby object' do
let(:described_element) { ['input', with: { type: 'file' }] }
end

describe 'additional attributes' do
subject { builder.send(method, attribute, accept: 'image/*', multiple: true) }

Expand Down
Expand Up @@ -44,6 +44,10 @@
it_behaves_like 'a field that supports setting the hint via localisation'
it_behaves_like 'a field that supports setting the legend via localisation'

it_behaves_like 'a field that accepts a plain ruby object' do
let(:described_element) { ['input', { with: { type: 'radio' }, count: colours.size }] }
end

context 'radio buttons' do
specify 'each radio button should have the correct classes' do
expect(subject).to have_tag('input', with: { class: %w(govuk-radios__input) }, count: colours.size)
Expand Down
Expand Up @@ -32,6 +32,12 @@
it_behaves_like 'a field that supports setting the hint via localisation'
it_behaves_like 'a field that supports setting the legend via localisation'

it_behaves_like 'a field that accepts a plain ruby object' do
subject { builder.send(*args) {} }

let(:described_element) { 'fieldset' }
end

context 'when a block containing radio buttons is supplied' do
specify 'output should be a form group containing a form group and fieldset' do
expect(subject).to have_tag('div', with: { class: 'govuk-form-group' }) do |fg|
Expand Down
4 changes: 4 additions & 0 deletions spec/govuk_design_system_formbuilder/builder/select_spec.rb
Expand Up @@ -30,6 +30,10 @@
it_behaves_like 'a field that supports setting the label via localisation'
it_behaves_like 'a field that supports setting the hint via localisation'

it_behaves_like 'a field that accepts a plain ruby object' do
let(:described_element) { 'select' }
end

specify 'output should be a form group containing a label and select box' do
expect(subject).to have_tag('div', with: { class: 'govuk-form-group' }) do |fg|
expect(fg).to have_tag('select')
Expand Down
Expand Up @@ -59,6 +59,10 @@
it_behaves_like 'a field that supports setting the label via localisation'
it_behaves_like 'a field that supports setting the hint via localisation'

it_behaves_like 'a field that accepts a plain ruby object' do
let(:described_element) { 'textarea' }
end

specify 'should have the correct classes' do
expect(subject).to have_tag('textarea', with: { class: 'govuk-textarea' })
end
Expand Down
47 changes: 39 additions & 8 deletions spec/support/examples.rb
@@ -1,9 +1,25 @@
class Person
class Project
include ActiveModel::Model
attr_accessor(:id, :name, :description)
end

class Being
attr_accessor(
:name,
:born_on,
:gender,
:over_18,
:favourite_colour,
:favourite_colour_reason,
:projects,
:project_responsibilities,
:cv,
:photo
)
end

class Person < Being
include ActiveModel::Model
attr_accessor(:name, :born_on, :gender, :over_18, :favourite_colour, :favourite_colour_reason)
attr_accessor(:projects, :project_responsibilities)
attr_accessor(:cv)
attr_accessor(:photo)

validates :name, presence: { message: 'Enter a name' }
validates :favourite_colour, presence: { message: 'Choose a favourite colour' }
Expand Down Expand Up @@ -35,7 +51,22 @@ def photo_must_be_jpeg
end
end

class Project
include ActiveModel::Model
attr_accessor(:id, :name, :description)
class Guest < Being
def initialize(name:, favourite_colour:, projects:, cv:, born_on:)
self.name = name
self.favourite_colour = favourite_colour
self.projects = projects
self.cv = cv
self.born_on = born_on
end

def self.example
new(
name: 'Minnie von Mouse',
favourite_colour: 'red',
projects: [4, 5, 6],
cv: 'Basic vocabulary',
born_on: Date.new(1974, 7, 1)
)
end
end
12 changes: 12 additions & 0 deletions spec/support/shared/shared_error_examples.rb
Expand Up @@ -50,4 +50,16 @@
expect(subject).not_to have_tag('span', with: { class: 'govuk-error-message' })
end
end

context 'when the object does not support errors' do
let(:object) { Guest.example }

specify 'should correctly render the form group' do
expect(subject).to have_tag('div', with: { class: 'govuk-form-group' })
end

specify 'no error should be raised' do
expect { subject }.not_to raise_error
end
end
end
19 changes: 19 additions & 0 deletions spec/support/shared/shared_plain_ruby_object_examples.rb
@@ -0,0 +1,19 @@
class Biscuit
attr_accessor :name, :weight, :calories

def initialize(name, weight, calories)
self.name = name
self.weight = weight
self.calories = calories
end
end

shared_examples 'a field that accepts a plain ruby object' do
let(:object) { Biscuit.new('Pick-up!', 28, 143) }
let(:object_name) { :biscuit }
let(:attribute) { :calories }

specify 'should render the element successfully' do
expect(subject).to have_tag(*described_element)
end
end
4 changes: 4 additions & 0 deletions spec/support/shared/shared_text_field_examples.rb
Expand Up @@ -40,6 +40,10 @@
it_behaves_like 'a field that supports setting the label via localisation'
it_behaves_like 'a field that supports setting the hint via localisation'

it_behaves_like 'a field that accepts a plain ruby object' do
let(:described_element) { 'input' }
end

context 'extra attributes' do
let(:regular_args) { { label: { text: 'What should we call you?' } } }

Expand Down

0 comments on commit fcb56d1

Please sign in to comment.