crown_marketplace_utils 0.1.0.beta.2 → 0.1.0.beta.3

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: b6c289917a94a2f6ee322e356590757f9963509f1a6fa7951783a780e84d5fcf
4
- data.tar.gz: 63639f4f2cf082ed69432dccdd0e41ced94dc909ec397d81550169229cf6ae06
3
+ metadata.gz: 9bded690841ee7e1cbd50580542cbebe6ec6f1522dfa1ee4ef3da56028ada558
4
+ data.tar.gz: 6cddd1647d22f33db11fc6120bd2f789b908d686b0c16e5d344a7ccbf188b3c7
5
5
  SHA512:
6
- metadata.gz: d5505418729cabf9849322dbbc8255c274063dca392c1cc5e3e9125db366811236efd120821b701f691fe32f28a94b19520f7a0425afb7d0bf6bc2c190025fe7
7
- data.tar.gz: e243d5969928fbf7924d4b81206e77a5cfc6ce5e066aac4f7022f7495c8acc255ca0178ac43485ca4b2d7af285018b91925367f4655ab66069e49418c09a0d0f
6
+ metadata.gz: 051dee5a663d6355aba6d171307b7ea9965413e15c7926efa164c4ff651b9f25fa8946c66cbaa2f0be4491facfbb8dbbf366363d33d348deb8eaa5ae431aa8db
7
+ data.tar.gz: 7d201bfd9d0a383bf3e5bf71402f428f6eda75bd88d17c669a1f1d0649ad5029d2400ed5626b26b9bf3ffffdadbf3ddeba9b6a65fdb8c09edc26cc0683952b5e
data/.rubocop.yml CHANGED
@@ -115,3 +115,10 @@ RSpec/NestedGroups:
115
115
  RSpec/ExampleLength:
116
116
  Exclude:
117
117
  - 'spec/crown_marketplace_utils/gov_uk_helper/**/*'
118
+
119
+ Rails/DynamicFindBy:
120
+ Whitelist:
121
+ - find_by_id
122
+
123
+ RSpec/MultipleExpectations:
124
+ Max: 3
data/Gemfile CHANGED
@@ -4,7 +4,3 @@ source 'https://rubygems.org'
4
4
 
5
5
  # Specify your gem's dependencies in crown_marketplace_utils.gemspec
6
6
  gemspec
7
-
8
- gem 'rake', '~> 13.0'
9
-
10
- gem 'rspec', '~> 3.0'
data/Gemfile.lock CHANGED
@@ -1,7 +1,7 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- crown_marketplace_utils (0.1.0.beta.2)
4
+ crown_marketplace_utils (0.1.0.beta.3)
5
5
  actionview (>= 6.0)
6
6
 
7
7
  GEM
@@ -72,8 +72,19 @@ GEM
72
72
  i18n (>= 1.6, < 2)
73
73
  minitest (>= 5.1)
74
74
  tzinfo (~> 2.0)
75
+ addressable (2.8.1)
76
+ public_suffix (>= 2.0.2, < 6.0)
75
77
  ast (2.4.2)
76
78
  builder (3.2.4)
79
+ capybara (3.38.0)
80
+ addressable
81
+ matrix
82
+ mini_mime (>= 0.1.3)
83
+ nokogiri (~> 1.8)
84
+ rack (>= 1.6.0)
85
+ rack-test (>= 0.6.3)
86
+ regexp_parser (>= 1.5, < 3.0)
87
+ xpath (~> 3.2)
77
88
  concurrent-ruby (1.1.10)
78
89
  crass (1.0.6)
79
90
  diff-lcs (1.5.0)
@@ -89,6 +100,7 @@ GEM
89
100
  mail (2.7.1)
90
101
  mini_mime (>= 0.1.1)
91
102
  marcel (1.0.2)
103
+ matrix (0.4.2)
92
104
  method_source (1.0.0)
93
105
  mini_mime (1.1.2)
94
106
  minitest (5.16.3)
@@ -101,13 +113,14 @@ GEM
101
113
  net-smtp (0.3.2)
102
114
  net-protocol
103
115
  nio4r (2.5.8)
104
- nokogiri (1.13.8-x86_64-darwin)
116
+ nokogiri (1.13.9-x86_64-darwin)
105
117
  racc (~> 1.4)
106
- nokogiri (1.13.8-x86_64-linux)
118
+ nokogiri (1.13.9-x86_64-linux)
107
119
  racc (~> 1.4)
108
120
  parallel (1.22.1)
109
121
  parser (3.1.2.1)
110
122
  ast (~> 2.4.1)
123
+ public_suffix (5.0.0)
111
124
  racc (1.6.0)
112
125
  rack (2.2.4)
113
126
  rack-test (2.0.2)
@@ -140,40 +153,40 @@ GEM
140
153
  zeitwerk (~> 2.5)
141
154
  rainbow (3.1.1)
142
155
  rake (13.0.6)
143
- regexp_parser (2.6.0)
156
+ regexp_parser (2.6.1)
144
157
  rexml (3.2.5)
145
- rspec (3.11.0)
146
- rspec-core (~> 3.11.0)
147
- rspec-expectations (~> 3.11.0)
148
- rspec-mocks (~> 3.11.0)
149
- rspec-core (3.11.0)
150
- rspec-support (~> 3.11.0)
151
- rspec-expectations (3.11.1)
158
+ rspec (3.12.0)
159
+ rspec-core (~> 3.12.0)
160
+ rspec-expectations (~> 3.12.0)
161
+ rspec-mocks (~> 3.12.0)
162
+ rspec-core (3.12.0)
163
+ rspec-support (~> 3.12.0)
164
+ rspec-expectations (3.12.0)
152
165
  diff-lcs (>= 1.2.0, < 2.0)
153
- rspec-support (~> 3.11.0)
154
- rspec-mocks (3.11.1)
166
+ rspec-support (~> 3.12.0)
167
+ rspec-mocks (3.12.0)
155
168
  diff-lcs (>= 1.2.0, < 2.0)
156
- rspec-support (~> 3.11.0)
157
- rspec-support (3.11.1)
158
- rubocop (1.36.0)
169
+ rspec-support (~> 3.12.0)
170
+ rspec-support (3.12.0)
171
+ rubocop (1.39.0)
159
172
  json (~> 2.3)
160
173
  parallel (~> 1.10)
161
174
  parser (>= 3.1.2.1)
162
175
  rainbow (>= 2.2.2, < 4.0)
163
176
  regexp_parser (>= 1.8, < 3.0)
164
177
  rexml (>= 3.2.5, < 4.0)
165
- rubocop-ast (>= 1.20.1, < 2.0)
178
+ rubocop-ast (>= 1.23.0, < 2.0)
166
179
  ruby-progressbar (~> 1.7)
167
180
  unicode-display_width (>= 1.4.0, < 3.0)
168
- rubocop-ast (1.21.0)
181
+ rubocop-ast (1.23.0)
169
182
  parser (>= 3.1.1.0)
170
- rubocop-rails (2.16.1)
183
+ rubocop-rails (2.17.3)
171
184
  activesupport (>= 4.2.0)
172
185
  rack (>= 1.1)
173
186
  rubocop (>= 1.33.0, < 2.0)
174
187
  rubocop-rake (0.6.0)
175
188
  rubocop (~> 1.0)
176
- rubocop-rspec (2.13.2)
189
+ rubocop-rspec (2.15.0)
177
190
  rubocop (~> 1.33)
178
191
  ruby-progressbar (1.11.0)
179
192
  thor (1.2.1)
@@ -185,6 +198,8 @@ GEM
185
198
  websocket-driver (0.7.5)
186
199
  websocket-extensions (>= 0.1.0)
187
200
  websocket-extensions (0.1.5)
201
+ xpath (3.2.0)
202
+ nokogiri (~> 1.8)
188
203
  yard (0.9.28)
189
204
  webrick (~> 1.7.0)
190
205
  zeitwerk (2.6.1)
@@ -194,16 +209,16 @@ PLATFORMS
194
209
  x86_64-linux
195
210
 
196
211
  DEPENDENCIES
197
- bundler
212
+ bundler (~> 2.3)
213
+ capybara (~> 3.38.0)
198
214
  crown_marketplace_utils!
199
- rails
200
- rake (~> 13.0)
201
- rspec (~> 3.0)
202
- rubocop
203
- rubocop-rails
204
- rubocop-rake
205
- rubocop-rspec
206
- yard
215
+ rails (>= 6.0)
216
+ rspec (~> 3.12)
217
+ rubocop (~> 1.36)
218
+ rubocop-rails (~> 2.16)
219
+ rubocop-rake (~> 0.6)
220
+ rubocop-rspec (~> 2.13)
221
+ yard (~> 0.9)
207
222
 
208
223
  BUNDLED WITH
209
224
  2.3.12
data/README.md CHANGED
@@ -20,9 +20,23 @@ If bundler is not being used to manage dependencies, install the gem by executin
20
20
 
21
21
  ## Usage
22
22
 
23
- To use this gem, simply at it to your Gemfile (as described above) and you will have access to the methods in the GovUkHelper once you restart your server.
23
+ To use this gem, simply add it to your Gemfile (as described above).
24
+
25
+ ### GOV.UK Helper
26
+
27
+ To include the helper methods from the `GovUkHelper` module, you can include it in your `app/helpers/application_helper.rb` like so:
28
+
29
+ ```ruby
30
+ module ApplicationHelper
31
+ include CrownMarketplaceUtils::GovUkHelper
32
+ end
33
+ ```
34
+
35
+ This will give you access to a variety of [GDS components](https://design-system.service.gov.uk/components) to use in your application views.
36
+ These are based on the components found in [GOV.UK Frontend v4.3.1](https://github.com/alphagov/govuk-frontend/releases/tag/v4.3.1).
24
37
 
25
38
  Documentation for the helper methods can be found at [LINK TO RDOCS](#)
39
+
26
40
  ## Development
27
41
 
28
42
  After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
@@ -34,24 +48,33 @@ To install this gem onto your local machine, run `bundle exec rake install`. To
34
48
  At the moment this Gem only contains view helpers. It would be good in the future to add other kinds of modules to this gem so that they can be shared and managed in one place.
35
49
 
36
50
  ### Helpers to create
37
- - Accordion
38
51
  - ~~Breadcrumbs~~
39
52
  - ~~Button~~
40
- - Checkboxes
41
- - CharacterCount
53
+ - ~~Checkboxes~~
54
+ - ~~CharacterCount~~
42
55
  - DateInput
43
56
  - ~~Details~~
44
57
  - ~~ErrorMessage~~
45
- - Fieldset
58
+ - ~~Fieldset~~
46
59
  - ~~FormGroup~~
47
- - Header
60
+ - ~~Header~~
48
61
  - ~~Hint~~
49
- - NotificationBanner
50
- - Pagination
51
- - Radios
52
- - Select
53
- - StepByStepNavigation
54
- - TextInput
62
+ - ~~Label~~
63
+ - ~~NotificationBanner~~
64
+ - ~~Pagination~~
65
+ - ~~Radios~~
66
+ - ~~Select~~
67
+ - ~~StepByStepNavigation~~
68
+ - ~~TextArea~~
69
+ - ~~TextInput~~
70
+ - ~~Tag~~
71
+
72
+ ### CCS Helpers to look at after first release
73
+ - Accordion
74
+ - CCS Panel
75
+ - CCS Header
76
+ - Conditioanl Checkboxes
77
+ - Conditioanl Radios
55
78
 
56
79
  ## Contributing
57
80
 
@@ -35,14 +35,15 @@ Gem::Specification.new do |spec|
35
35
  # spec.add_dependency "example-gem", "~> 1.0"
36
36
  spec.add_dependency 'actionview', '>= 6.0'
37
37
 
38
- spec.add_development_dependency 'bundler'
39
- spec.add_development_dependency 'rails'
40
- spec.add_development_dependency 'rspec', '~> 3.2'
41
- spec.add_development_dependency 'rubocop'
42
- spec.add_development_dependency 'rubocop-rails'
43
- spec.add_development_dependency 'rubocop-rake'
44
- spec.add_development_dependency 'rubocop-rspec'
45
- spec.add_development_dependency 'yard'
38
+ spec.add_development_dependency 'bundler', '~> 2.3'
39
+ spec.add_development_dependency 'capybara', '~> 3.38.0'
40
+ spec.add_development_dependency 'rails', '>= 6.0'
41
+ spec.add_development_dependency 'rspec', '~> 3.12'
42
+ spec.add_development_dependency 'rubocop', '~> 1.36'
43
+ spec.add_development_dependency 'rubocop-rails', '~> 2.16'
44
+ spec.add_development_dependency 'rubocop-rake', '~> 0.6'
45
+ spec.add_development_dependency 'rubocop-rspec', '~> 2.13'
46
+ spec.add_development_dependency 'yard', '~> 0.9'
46
47
 
47
48
  # For more information and examples about making a new gem, check out our
48
49
  # guide at: https://bundler.io/guides/creating_gem.html
@@ -19,7 +19,7 @@ module CrownMarketplaceUtils
19
19
  # @param summary_text [String] the summary text for the details element
20
20
  # @param govuk_details_options [Hash] options that will be used in customising the HTML
21
21
  #
22
- # @option govuk_details_options [String] :classes additional CSS classes for the error message HTML
22
+ # @option govuk_details_options [String] :classes additional CSS classes for the details HTML
23
23
  # @option govuk_details_options [Hash] :attributes ({ data: { module: 'govuk-details' } }) any additional attributes that will added as part of the HTML
24
24
  #
25
25
  # @yield HTML that will be contained within the 'govuk-details__text' div
@@ -22,7 +22,7 @@ module CrownMarketplaceUtils
22
22
  #
23
23
  # @option govuk_error_message_options [String] :classes additional CSS classes for the error message HTML
24
24
  # @option govuk_error_message_options [String] :visually_hidden_text ('Error') visualy hidden text before the error message
25
- # @option govuk_error_message_options [Hash] :attributes ({}) any additional attributes that will added as part of the HTML
25
+ # @option govuk_error_message_options [Hash] :attributes ({}) any additional attributes that will be added as part of the HTML
26
26
  #
27
27
  # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK Error message
28
28
  # which can then be rendered on the page
@@ -0,0 +1,193 @@
1
+ # frozen_string_literal: true
2
+
3
+ require_relative 'textarea'
4
+
5
+ module CrownMarketplaceUtils
6
+ module GovUkHelper
7
+ module Field
8
+ # = GOV.UK Character count
9
+ #
10
+ # This helper is used for generating the character count component from the
11
+ # {https://design-system.service.gov.uk/components/character-count GDS - Components - Character count}
12
+ #
13
+ # This is a wrapper around a Textarea module and so makes use of the methods in {Textarea}
14
+
15
+ module CharacterCount
16
+ include Textarea
17
+
18
+ # Generates the HTML for the GOV.UK character count component.
19
+ # It works by warpping the govuk_textarea in HTML which will trigger the JavaScript to do the character count.
20
+ #
21
+ # @param attribute [String, Symbol] the attribute of the character count text area
22
+ # @param error_message [String] the error message to be displayed
23
+ # @param govuk_character_count_options [Hash] options that will be used for the parts of the form group, label, hint, textarea and the character count
24
+ #
25
+ # @option govuk_character_count_options [Hash] :form_group_options see {govuk_field}
26
+ # @option govuk_character_count_options [Hash] :label see {govuk_field}
27
+ # @option govuk_character_count_options [Hash] :hint see {govuk_field}
28
+ # @option govuk_character_count_options [Hash] :textarea_options see {govuk_textarea}
29
+ # @option govuk_character_count_options [Hash] :character_count_options ({}) the options that will be used when rendering the textarea.
30
+ # See {_govuk_character_count} for more details.
31
+ #
32
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK chracter count
33
+ # which can then be rendered on the page
34
+
35
+ def govuk_character_count(attribute, error_message = nil, **govuk_character_count_options)
36
+ _govuk_character_count(attribute, **govuk_character_count_options) do |govuk_text_textarea_options|
37
+ govuk_textarea(attribute, error_message, **govuk_text_textarea_options)
38
+ end
39
+ end
40
+
41
+ # Generates the HTML for the GOV.UK character count component.
42
+ # It works by warpping the govuk_textarea in HTML which will trigger the JavaScript to do the character count.
43
+ #
44
+ # @param attribute [String, Symbol] the attribute of the character count
45
+ # @param error_message [String] the error message to be displayed
46
+ # @param govuk_character_count_options [Hash] options that will be used for the parts of the form group, label, hint and textarea
47
+ #
48
+ # @option govuk_character_count_options [Hash] :form_group_options see {govuk_field}
49
+ # @option govuk_character_count_options [Hash] :label see {govuk_field}
50
+ # @option govuk_character_count_options [Hash] :hint see {govuk_field}
51
+ # @option govuk_character_count_options [Hash] :textarea_options see {govuk_textarea}
52
+ # @option govuk_character_count_options [Hash] :character_count_options ({}) the options that will be used when rendering the textarea.
53
+ # See {_govuk_character_count} for more details.
54
+ #
55
+ # @return [ActiveSupport::SafeBuffer] the HTML for the GOV.UK chracter count
56
+ # which can then be rendered on the page
57
+
58
+ # Generates the HTML for the GOV.UK textarea component using an ActionView::Helpers::FormBuilder.
59
+ # Unlike {#govuk_textarea}, the method will be able to automatically determine if the error message needs to be shown.
60
+ #
61
+ # @param form [ActionView::Helpers::FormBuilder] :form the form builder used to create the character count textarea
62
+ # @param attribute [String, Symbol] the attribute of the character count text area
63
+ # @param govuk_character_count_options [Hash] options that will be used for the parts of the form group, label, hint, textarea and the character count
64
+ #
65
+ # @option govuk_character_count_options [Hash] :form_group_options see {govuk_field_with_form}
66
+ # @option govuk_character_count_options [Hash] :label see {govuk_field_with_form}
67
+ # @option govuk_character_count_options [Hash] :hint see {govuk_field_with_form}
68
+ # @option govuk_character_count_options [Hash] :textarea_options see {govuk_textarea_with_form}
69
+ # @option govuk_character_count_options [Hash] :character_count_options ({}) the options that will be used when rendering the textarea.
70
+ # See {_govuk_character_count} for more details.
71
+ #
72
+ # @return (see govuk_character_count)
73
+
74
+ def govuk_character_count_with_form(form, attribute, **govuk_character_count_options)
75
+ _govuk_character_count(attribute, **govuk_character_count_options) do |govuk_text_textarea_options|
76
+ govuk_textarea_with_form(form, attribute, **govuk_text_textarea_options)
77
+ end
78
+ end
79
+
80
+ private
81
+
82
+ # Wrapper method used by {govuk_character_count} and {govuk_character_count_with_form} to generate the character count HTML
83
+ #
84
+ # @param attribute [String, Symbol] the attribute of the character count
85
+ # @param govuk_character_count_options [Hash] options that will be used in customising the HTML.
86
+ # This includes everything described in {govuk_character_count} and {govuk_character_count_with_form}
87
+ # with the addition of the +:character_count_options+ which are described below
88
+ #
89
+ # @option govuk_character_count_options [String] :maxlength (required) - if +maxwords+ is set, this is not required.
90
+ # The maximum number of characters.
91
+ # If +maxwords+ is provided, the +maxlength+ option will be ignored.
92
+ # @option govuk_character_count_options [String] :maxwords (required) - if maxlength is set, this is not required.
93
+ # The maximum number of words.
94
+ # If +maxwords+ is provided, the +maxlength+ option will be ignored.
95
+ # @option govuk_character_count_options [String] :threshold the percentage value of the limit at which point the count message is displayed.
96
+ # If this attribute is set, the count message will be hidden by default.
97
+ # @option govuk_text_textarea_options [Hash] :fallback_hint ({}) additional parameters that will be used to create the hint containing the character count text.
98
+ # This includes all the options in {govuk_hint} plus +:count_message+.
99
+ # This will replace the default text for the count message.
100
+ # If you want the count number to appear, put %<count>s in the string and it will be replaced with the number
101
+ #
102
+ # @yield the textarea HTML generated by {govuk_character_count} or {govuk_character_count_with_form}
103
+ #
104
+ # @yieldparam govuk_text_textarea_options [Hash] the options used in the textarea called by {govuk_character_count} or {govuk_character_count_with_form}
105
+ #
106
+ # @return [ActiveSupport::SafeBuffer] the HTML for the chracter count which wrpas arround {govuk_character_count} or {govuk_character_count_with_form}
107
+
108
+ def _govuk_character_count(attribute, **govuk_character_count_options)
109
+ deep_init_hash(govuk_character_count_options, :textarea_options, :attributes, :aria)
110
+ govuk_character_count_options[:textarea_options][:attributes][:aria][:describedby] = [govuk_character_count_options.dig(:textarea_options, :attributes, :aria, :describedby), "#{attribute}-hint-info"].compact.join(' ')
111
+
112
+ govuk_character_count_options[:textarea_options][:classes] = [govuk_character_count_options[:textarea_options][:classes], 'govuk-js-character-count'].compact
113
+
114
+ tag.div(class: 'govuk-character-count', **get_character_count_attributes(**govuk_character_count_options)) do
115
+ capture do
116
+ concat(yield(govuk_character_count_options))
117
+ concat(character_count_hint(attribute, **govuk_character_count_options))
118
+ end
119
+ end
120
+ end
121
+
122
+ # Generates the fallback hint HTML for {_govuk_character_count}
123
+ #
124
+ # @param (see _govuk_character_count)
125
+ #
126
+ # @option (see _govuk_character_count)
127
+ #
128
+ # @return [ActiveSupport::SafeBuffer] the HTML for the fullback hint used in {_govuk_character_count}
129
+
130
+ def character_count_hint(attribute, **govuk_character_count_options)
131
+ fallback_hint_length = govuk_character_count_options[:character_count_options][:maxwords] || govuk_character_count_options[:character_count_options][:maxlength]
132
+ fallback_hint_default = "You can enter up to %<count>s #{govuk_character_count_options[:character_count_options][:maxwords] ? 'words' : 'characters'}"
133
+
134
+ deep_init_hash(govuk_character_count_options, :character_count_options, :fallback_hint, :attributes)
135
+
136
+ fallback_hint_text = format(govuk_character_count_options[:character_count_options][:fallback_hint][:count_message] || fallback_hint_default, count: fallback_hint_length)
137
+
138
+ govuk_character_count_options[:character_count_options][:fallback_hint][:classes] = [govuk_character_count_options.dig(:character_count_options, :fallback_hint, :classes), 'govuk-character-count__message']
139
+ govuk_character_count_options[:character_count_options][:fallback_hint][:attributes].merge!(id: "#{attribute}-hint-info")
140
+
141
+ govuk_hint(fallback_hint_text, **govuk_character_count_options[:character_count_options][:fallback_hint])
142
+ end
143
+
144
+ # Generates a hash with the character count attributes used in {_govuk_character_count}
145
+ #
146
+ # @param govuk_character_count_options [Hash] options that will be used in customising the HTML.
147
+ # This includes everything described in {govuk_character_count} and {govuk_character_count_with_form}
148
+ # with the addition of the +:character_count_options+ which are described below
149
+ #
150
+ # @option (see _govuk_character_count)
151
+ #
152
+ # @return [Hash] contains the HTMl attributes used in {_govuk_character_count}
153
+
154
+ def get_character_count_attributes(**govuk_character_count_options)
155
+ govuk_character_count_attributes = { data: { module: 'govuk-character-count' } }
156
+
157
+ %i[maxlength threshold maxwords].each do |data_attribute|
158
+ govuk_character_count_attributes[:data][data_attribute] = govuk_character_count_options[:character_count_options][data_attribute].to_s if govuk_character_count_options[:character_count_options][data_attribute]
159
+ end
160
+
161
+ govuk_character_count_attributes
162
+ end
163
+
164
+ # Method to initialise hashes within hashes if it is not already initialised
165
+ #
166
+ # @param hash [Hash] the hash that is going to be initialised
167
+ # @param keys [Array] the keys that are going to be initialised in the hash
168
+ #
169
+ # @example When the hash is completely empty
170
+ # hash = { }
171
+ # keys = [:a, :b, :c]
172
+ #
173
+ # deep_init_hash(hash, *keys)
174
+ #
175
+ # hash = { a: { b: { c: { } } } }
176
+ #
177
+ # @example When the hash has already been initialised
178
+ # hash = { a: { b: { d: 'hello' } } }
179
+ # keys = [:a, :b, :c]
180
+ #
181
+ # deep_init_hash(hash, *keys)
182
+ #
183
+ # hash = { a: { b: { d: 'hello', c: { } } } }
184
+
185
+ def deep_init_hash(hash, *keys)
186
+ current_hash = hash
187
+
188
+ keys.each { |key| current_hash = (current_hash[key] ||= {}) }
189
+ end
190
+ end
191
+ end
192
+ end
193
+ end