chic 0.1.0 → 0.3.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: a6ee27baaf52ccaffd000c9ffc37ba80e929ab93386c2f1dc2fb3d419d9cd86e
4
- data.tar.gz: aebe4ade08bfff97f1fa3f4a96334dc4cb5cb9efdcbc108d6b00e1f81e781f1c
3
+ metadata.gz: 29c1b7b66f93c55e96cd4f3399b52a89461f32212c5752df80f3413a5c8898ce
4
+ data.tar.gz: 3cd78efa318d5614ab2c37a02c986bbe2f27760e1710591b32059889aa1c7cd4
5
5
  SHA512:
6
- metadata.gz: 200473240b8f99cbef6229c0181a7e820df796b744f199f0b25bcb22656109c0338b14c63385f8fe6c6eaa06027bc97a33edd8e0635f995eb974d1635f449b48
7
- data.tar.gz: 1b0dc1cc823cfd555e19f4c6aea0306a852fcef8ff9f66bb1c3f1c7189a6003368fb7f5497a825311c24dc65d8551e3779cd53f0c1da2f4192d8ac6f358f6115
6
+ metadata.gz: 101121d9551d426c4c6d8e39b75f96def4ae7bd22955d1c0a93ff6509e755bcad33eb55bc1bfbae0cbdbffae03c1aea459c82fcbc3dfad0410b5db77960e73ea
7
+ data.tar.gz: edef9ddd2761744818b172b34f1d6942fc2d3fafaf81ec6edc600e26eab36bfafb75d55916830931b74cf1e20679f657c81babf326ee5bc75e8241d6cdb370e8
data/.rubocop.yml CHANGED
@@ -1,8 +1,11 @@
1
1
  AllCops:
2
- TargetRubyVersion: 2.5
2
+ NewCops: enable
3
+ TargetRubyVersion: 2.7
4
+ Exclude:
5
+ - 'bin/**/*'
3
6
 
4
- Documentation:
5
- Enabled: false
6
-
7
- Metrics/LineLength:
7
+ Layout/LineLength:
8
8
  Max: 120
9
+
10
+ Style/Documentation:
11
+ Enabled: false
data/README.md CHANGED
@@ -1,86 +1,354 @@
1
1
  # Chic
2
2
 
3
- Opinionated presentation layer comprised of presenters and formatters.
3
+ An opinionated presentation layer comprising presenters and formatters.
4
+
5
+ Chic was borne out of a need for a simple PORO-style presentation layer for Rails applications to help DRY up formatting logic in views and view helpers.
4
6
 
5
7
  ## Installation
6
8
 
7
- Add this line to your application's Gemfile:
9
+ To get started, add this line to your Gemfile and install it using Bundler:
8
10
 
9
- gem 'chic'
11
+ ```ruby
12
+ gem 'chic'
13
+ ```
10
14
 
11
- And then execute:
15
+ ## Usage
12
16
 
13
- $ bundle
17
+ Though it is not a requirement, for ease of reference it is assumed that you will be using this library in a Rails application where you will be creating presenters for your models.
14
18
 
15
- Or install it yourself as:
19
+ ### Creating Presenters
16
20
 
17
- $ gem install chic
21
+ Create a presenter by deriving from `Chic::Presenter`, and then declare which attributes should return formatters or presenters.
18
22
 
19
- ## Usage
23
+ ```ruby
24
+ # app/presenters/foo_presenter.rb
20
25
 
21
- ### Being Presentable
26
+ class FooPresenter < Chic::Presenter
27
+ formats :baz
28
+
29
+ presents bar: 'BarPresenter'
30
+ end
31
+ ```
22
32
 
23
- Make objects easily presentable by:
33
+ ### Using Presenters
34
+
35
+ Include `Chic::Presentable` to make your objects presentable:
24
36
 
25
37
  ```ruby
26
- class Foo
38
+ # app/models/foo.rb
39
+
40
+ class Foo < ApplicationRecord
27
41
  include Chic::Presentable
42
+
43
+ belongs_to :bar
28
44
  end
29
45
  ```
30
46
 
31
- ### Creating Presenters
47
+ Instantiate a presenter by calling `.present` on the presenter class, for example in a Rails view:
32
48
 
33
- Present presentables with a presenter by inheriting from `Chic::Presenter`:
49
+ ```erb
50
+ <% FooPresenter.present @foo do |foo_presenter| %>
51
+ <!-- ... -->
52
+ <% end %>
53
+ ```
54
+
55
+ Collections can be presented using `.present_each`:
56
+
57
+ ```erb
58
+ <% FooPresenter.present_each @foos do |foo_presenter, foo| %>
59
+ <!-- ... -->
60
+ <% end %>
61
+ ```
62
+
63
+ You can also include the view helpers:
34
64
 
35
65
  ```ruby
36
- class FooPresenter < Chic::Presenter
37
- # ...
66
+ module ApplicationHelper
67
+ include Chic::Helpers::View
38
68
  end
39
69
  ```
40
70
 
41
- You can also include `Chic::Presents` and `Chic::Formats` as needed:
71
+ Which will allow you to instantiate presenters without having to use the class name:
72
+
73
+ ```erb
74
+ <% present @foo do |foo_presenter| %>
75
+ <!-- ... -->
76
+ <% end %>
77
+
78
+ <% present_each @foos do |foo_presenter, foo| %>
79
+ <!-- ... -->
80
+ <% end %>
81
+ ```
82
+
83
+ See the [Conventions](#conventions) section below for more on using presenters.
84
+
85
+ ### Creating Formatters
86
+
87
+ Formatters format values by deriving from `Chic::Formatters::Nil` and overriding the private `value` method:
42
88
 
43
89
  ```ruby
44
- class FooPresenter
45
- include Chic::Formats
46
- include Chic::Presents
47
- # ...
90
+ # app/formatters/date_time_formatter.rb
91
+
92
+ class DateTimeFormatter < Chic::Formatters::Nil
93
+ private
94
+
95
+ def value
96
+ return if object.blank?
97
+
98
+ object.strftime('%-d %b %Y %H:%M')
99
+ end
48
100
  end
49
101
  ```
50
102
 
51
- **Note:** You need to make sure that the object being presented and the context in which it is being presented, for example the view, are accessible through `object` and `context` on the presenter instance respectively.
103
+ **Note:** You should always return `nil` if the object being formatted is blank so that the `Nil` formatter behaves correctly.
52
104
 
53
- ### Using Presenters
105
+ Provide additional formatter options as chainable methods:
106
+
107
+ ```ruby
108
+ # app/formatters/date_time_formatter.rb
109
+
110
+ class DateTimeFormatter < Chic::Formatters::Nil
111
+ def format=(value)
112
+ @format = value
113
+ self
114
+ end
115
+
116
+ private
117
+
118
+ def value
119
+ return if object.blank?
120
+
121
+ object.strftime(@format || '%-d %b %Y %H:%M')
122
+ end
123
+ end
124
+ ```
54
125
 
55
- Presenters should be instantiated from views using `.present`:
126
+ ### Using Formatters
127
+
128
+ Declare formatted values in presenters using `formats`:
56
129
 
57
130
  ```ruby
131
+ # app/presenters/foo_presenter.rb
132
+
133
+ class FooPresenter < Chic::Presenter
134
+ formats :created_at,
135
+ with: 'DateTimeFormatter'
136
+ end
137
+ ```
138
+
139
+ Render formatted values by calling `#to_s` on the formatter returned, which happens implicitly in Rails views for example:
140
+
141
+ ```erb
58
142
  <% FooPresenter.present @foo do |foo_presenter, _foo| %>
59
- <!-- ... -->
143
+ <%= foo_presenter.created_at %>
60
144
  <% end %>
61
145
  ```
62
146
 
63
- Collections can be presented using `.present_each`:
147
+ #### Configurable options
148
+
149
+ If the formatter derives from `Chic::Formatters::Nil`, then configure a blank value to be used:
64
150
 
65
151
  ```ruby
66
- <% FooPresenter.present_each @foos do |foo_presenter, _foo| %>
67
- <!-- ... -->
152
+ # app/presenters/foo_presenter.rb
153
+
154
+ class FooPresenter < Chic::Presenter
155
+ formats :created_at,
156
+ with: 'DateTimeFormatter',
157
+ options: {
158
+ blank_value: '(Not yet created)'
159
+ }
160
+ end
161
+ ```
162
+
163
+ If the formatter supports additional options using chainable methods as described above, configure those options in the same way:
164
+
165
+ ```ruby
166
+ # app/presenters/foo_presenter.rb
167
+
168
+ class FooPresenter < Chic::Presenter
169
+ formats :created_at,
170
+ with: 'DateTimeFormatter',
171
+ options: {
172
+ format: '%-d %B %Y at %H:%M'
173
+ }
174
+ end
175
+ ```
176
+
177
+ If needed, override those options where the formatted value is being rendered:
178
+
179
+ ```erb
180
+ <% FooPresenter.present @foo do |foo_presenter, _foo| %>
181
+ <%= foo_presenter.created_at.format('%c').blank_value('–') %>
68
182
  <% end %>
69
183
  ```
70
184
 
71
- If you've made use of the view helpers, you can drop the class name:
185
+ #### Named formatters
186
+
187
+ Optionally configure formatters with a name, for example in a Rails initializer:
188
+
189
+ ```ruby
190
+ # config/initializers/chic.rb
191
+
192
+ require 'chic'
193
+
194
+ Chic.configure do |config|
195
+ config.formatters.merge!(
196
+ date_time: 'DateTimeFormatter'
197
+ )
198
+ end
199
+ ```
200
+
201
+ Allowing you to refer to those formatters by name instead of by class:
72
202
 
73
203
  ```ruby
74
- <% present @foo do |foo_presenter, _foo| %>
204
+ # app/presenters/foo_presenter.rb
205
+
206
+ class FooPresenter < Chic::Presenter
207
+ formats :created_at,
208
+ with: :date_time
209
+ end
210
+ ```
211
+
212
+ ## Logging
213
+
214
+ If a presenter class for an object you're trying to present can't be found, an entry at debug level will be made to the configured logger.
215
+
216
+ You can configure the logger to be used:
217
+
218
+ ```ruby
219
+ # config/initializers/chic.rb
220
+
221
+ require 'chic'
222
+
223
+ Chic.configure do |config|
224
+ config.logger = Logger.new($stdout)
225
+ end
226
+ ```
227
+
228
+ It may be beneficial to know about missing presenter classes sooner than later, in which case you can enable exceptions when it makes sense to do so – for example, a Rails application in any environment other than production:
229
+
230
+ ```ruby
231
+ # config/initializers/chic.rb
232
+
233
+ require 'chic'
234
+
235
+ Chic.configure do |config|
236
+ config.raise_exceptions = Rails.env.production? == false
237
+ end
238
+ ```
239
+
240
+ ## Conventions
241
+
242
+ A few helpful conventions that have gone a long way to keep things maintainable.
243
+
244
+ ### Naming presenter classes
245
+
246
+ Presenter class names are derived by appending `Presenter` to the `#model_name` or the class name of the object being presented. It is strongly recommended that you stick to this convention, but if you need to change it – for example you might have overridden `#model_name` – you can do so by defining a `#presenter_class` method:
247
+
248
+ ```ruby
249
+ # app/forms/user/sign_up_form.rb
250
+
251
+ class User::SignUpForm < User
252
+ include Chic::Presentable
253
+
254
+ def self.model_name
255
+ ActiveModel::Name.new(self, nil, 'User')
256
+ end
257
+
258
+ def presenter_class
259
+ User::SignUpFormPresenter
260
+ end
261
+ end
262
+ ```
263
+
264
+ ### Instantiate presenters in views only
265
+
266
+ Try not instantiate presenters outside of the view layer if possible.
267
+
268
+ **Don't**
269
+
270
+ ```ruby
271
+ # app/controllers/foo_controller.rb
272
+
273
+ class FoosController < ApplicationController
274
+ def show
275
+ @foo = Foo.find(params[:id])
276
+ @foo_presenter = FooPresenter.new(@foo)
277
+ end
278
+ end
279
+ ```
280
+
281
+ ```erb
282
+ <!-- app/views/foos/_show.html.erb -->
283
+
284
+ <%= link_to @foo_presenter.created_at, foo_path(@foo) %>
285
+ ```
286
+
287
+ **Do**
288
+
289
+ ```ruby
290
+ # app/controllers/foo_controller.rb
291
+
292
+ class FoosController < ApplicationController
293
+ def show
294
+ @foo = Foo.find(params[:id])
295
+ end
296
+ end
297
+ ```
298
+
299
+ ```erb
300
+ <!-- app/views/foos/_show.html.erb -->
301
+
302
+ <% present @foo do |foo_presenter| %>
303
+ <%= link_to foo_presenter.created_at, foo_path(@foo) %>
304
+ <% end %>
305
+ ```
306
+
307
+ ### Keep presenter instances scoped to only the view in which they're being used
308
+
309
+ It can get messy if you pass presenter instances to other views, try avoid that if possible.
310
+
311
+ **Don't**
312
+
313
+ ```erb
314
+ <% present @foo do |foo_presenter| %>
75
315
  <!-- ... -->
316
+ <%= render partial: 'path/to/partial', locals: { foo: foo_presenter } %>
76
317
  <% end %>
77
318
  ```
78
319
 
79
- And:
320
+ **Do**
80
321
 
81
- ```ruby
82
- <% present_each @foo do |foo_presenter, _foo| %>
322
+ ```erb
323
+ <% present @foo do |foo_presenter| %>
83
324
  <!-- ... -->
325
+ <%= render partial: 'path/to/partial', locals: { foo: @foo } %>
326
+ <% end %>
327
+ ```
328
+
329
+ ### Use presenters and formatters for presentation only
330
+
331
+ It may be tempting to use presenters for conditional logic, but it's far better to use the original object for anything other than presentation.
332
+
333
+ **Don't**
334
+
335
+ ```erb
336
+ <% present_each @foos do |foo_presenter, foo| %>
337
+ <% if foo_presenter.created_at %>
338
+ <%= link_to foo_presenter.created_at, foo_path(foo_presenter) %>
339
+ <% end
340
+ <% end %>
341
+ ```
342
+
343
+ **Note:** Passing a presenter instance to a route helper as shown would only work if the presenter declared `id` as a formatted attribute. While this may work, it is not predictable behaviour.
344
+
345
+ **Do**
346
+
347
+ ```erb
348
+ <% present_each @foos do |foo_presenter, foo| %>
349
+ <% if foo.created_at %>
350
+ <%= link_to foo_presenter.created_at, foo_path(foo) %>
351
+ <% end
84
352
  <% end %>
85
353
  ```
86
354
 
data/bin/bundle ADDED
@@ -0,0 +1,114 @@
1
+ #!/usr/bin/env ruby
2
+ # frozen_string_literal: true
3
+
4
+ #
5
+ # This file was generated by Bundler.
6
+ #
7
+ # The application 'bundle' is installed as part of a gem, and
8
+ # this file is here to facilitate running it.
9
+ #
10
+
11
+ require "rubygems"
12
+
13
+ m = Module.new do
14
+ module_function
15
+
16
+ def invoked_as_script?
17
+ File.expand_path($0) == File.expand_path(__FILE__)
18
+ end
19
+
20
+ def env_var_version
21
+ ENV["BUNDLER_VERSION"]
22
+ end
23
+
24
+ def cli_arg_version
25
+ return unless invoked_as_script? # don't want to hijack other binstubs
26
+ return unless "update".start_with?(ARGV.first || " ") # must be running `bundle update`
27
+ bundler_version = nil
28
+ update_index = nil
29
+ ARGV.each_with_index do |a, i|
30
+ if update_index && update_index.succ == i && a =~ Gem::Version::ANCHORED_VERSION_PATTERN
31
+ bundler_version = a
32
+ end
33
+ next unless a =~ /\A--bundler(?:[= ](#{Gem::Version::VERSION_PATTERN}))?\z/
34
+ bundler_version = $1
35
+ update_index = i
36
+ end
37
+ bundler_version
38
+ end
39
+
40
+ def gemfile
41
+ gemfile = ENV["BUNDLE_GEMFILE"]
42
+ return gemfile if gemfile && !gemfile.empty?
43
+
44
+ File.expand_path("../../Gemfile", __FILE__)
45
+ end
46
+
47
+ def lockfile
48
+ lockfile =
49
+ case File.basename(gemfile)
50
+ when "gems.rb" then gemfile.sub(/\.rb$/, gemfile)
51
+ else "#{gemfile}.lock"
52
+ end
53
+ File.expand_path(lockfile)
54
+ end
55
+
56
+ def lockfile_version
57
+ return unless File.file?(lockfile)
58
+ lockfile_contents = File.read(lockfile)
59
+ return unless lockfile_contents =~ /\n\nBUNDLED WITH\n\s{2,}(#{Gem::Version::VERSION_PATTERN})\n/
60
+ Regexp.last_match(1)
61
+ end
62
+
63
+ def bundler_version
64
+ @bundler_version ||=
65
+ env_var_version || cli_arg_version ||
66
+ lockfile_version
67
+ end
68
+
69
+ def bundler_requirement
70
+ return "#{Gem::Requirement.default}.a" unless bundler_version
71
+
72
+ bundler_gem_version = Gem::Version.new(bundler_version)
73
+
74
+ requirement = bundler_gem_version.approximate_recommendation
75
+
76
+ return requirement unless Gem::Version.new(Gem::VERSION) < Gem::Version.new("2.7.0")
77
+
78
+ requirement += ".a" if bundler_gem_version.prerelease?
79
+
80
+ requirement
81
+ end
82
+
83
+ def load_bundler!
84
+ ENV["BUNDLE_GEMFILE"] ||= gemfile
85
+
86
+ activate_bundler
87
+ end
88
+
89
+ def activate_bundler
90
+ gem_error = activation_error_handling do
91
+ gem "bundler", bundler_requirement
92
+ end
93
+ return if gem_error.nil?
94
+ require_error = activation_error_handling do
95
+ require "bundler/version"
96
+ end
97
+ return if require_error.nil? && Gem::Requirement.new(bundler_requirement).satisfied_by?(Gem::Version.new(Bundler::VERSION))
98
+ warn "Activating bundler (#{bundler_requirement}) failed:\n#{gem_error.message}\n\nTo install the version of bundler this project requires, run `gem install bundler -v '#{bundler_requirement}'`"
99
+ exit 42
100
+ end
101
+
102
+ def activation_error_handling
103
+ yield
104
+ nil
105
+ rescue StandardError, LoadError => e
106
+ e
107
+ end
108
+ end
109
+
110
+ m.load_bundler!
111
+
112
+ if m.invoked_as_script?
113
+ load Gem.bin_path("bundler", "bundle")
114
+ end
data/chic.gemspec CHANGED
@@ -23,8 +23,10 @@ Gem::Specification.new do |spec|
23
23
  spec.executables = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
24
24
  spec.require_paths = ['lib']
25
25
 
26
- spec.add_development_dependency 'bundler', '~> 2.0'
26
+ spec.required_ruby_version = '>= 2.7'
27
+
28
+ spec.add_development_dependency 'bundler', '~> 2.3.10'
27
29
  spec.add_development_dependency 'minitest', '~> 5.0'
28
- spec.add_development_dependency 'rake', '~> 10.0'
29
- spec.add_development_dependency 'rubocop', '>= 0.49.0'
30
+ spec.add_development_dependency 'rake', '~> 13.0'
31
+ spec.add_development_dependency 'rubocop', '~> 0.71'
30
32
  end
@@ -11,15 +11,20 @@ module Chic
11
11
  nil: Formatters::Nil
12
12
  }.freeze
13
13
 
14
- attr_writer :logger,
15
- :formatters
14
+ attr_writer :formatters,
15
+ :logger,
16
+ :raise_exceptions
16
17
 
17
18
  def formatters
18
19
  @formatters ||= FORMATTERS.dup
19
20
  end
20
21
 
21
22
  def logger
22
- @logger ||= Logger.new(STDOUT)
23
+ @logger ||= Logger.new($stdout)
24
+ end
25
+
26
+ def raise_exceptions
27
+ @raise_exceptions == true
23
28
  end
24
29
  end
25
30
  end
data/lib/chic/errors.rb CHANGED
@@ -1,6 +1,8 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chic
4
- class PresentsOptionsNotValid < StandardError; end
4
+ class ConfigFormatterNotValid < StandardError; end
5
5
  class FormatsOptionsNotValid < StandardError; end
6
+ class PresenterClassNotDefined < StandardError; end
7
+ class PresentsOptionsNotValid < StandardError; end
6
8
  end
data/lib/chic/formats.rb CHANGED
@@ -41,7 +41,6 @@ module Chic
41
41
  end
42
42
 
43
43
  # rubocop: disable Metrics/AbcSize
44
- # rubocop: disable Metrics/CyclomaticComplexity
45
44
  def _validate_formats_options_with!(attributes, options)
46
45
  _raise_formats_options_not_valid '`with` must be a symbol or a class', attributes \
47
46
  if options.key?(:with) && !options[:with].is_a?(Symbol) && !options[:with].is_a?(Class)
@@ -49,9 +48,8 @@ module Chic
49
48
  _raise_formats_options_not_valid "`with` formatter :#{options[:with]} doesn't exist", attributes \
50
49
  if options.key?(:with) && options[:with].is_a?(Symbol) && !Chic.configuration.formatters.key?(options[:with])
51
50
  end
52
- # rubocop: enable Metrics/AbcSize
53
- # rubocop: enable Metrics/CyclomaticComplexity
54
51
 
52
+ # rubocop: enable Metrics/AbcSize
55
53
  def _validate_formats_options_value!(attributes, options)
56
54
  _raise_formats_options_not_valid '`value` must be a symbol or a lambda', attributes \
57
55
  if options.key?(:value) && !options[:value].is_a?(Symbol) && !options[:value].is_a?(Proc)
@@ -70,17 +68,33 @@ module Chic
70
68
 
71
69
  private
72
70
 
71
+ # rubocop: disable Metrics/MethodLength
73
72
  def _formatters
74
- Chic.configuration.formatters
73
+ @_formatters ||= Chic.configuration.formatters.reduce({}) do |result, (key, klass)|
74
+ formatter = case klass
75
+ when Class
76
+ klass
77
+ when String
78
+ klass.constantize
79
+ else
80
+ raise ConfigFormatterNotValid, "Configured formatter for #{key} must be a class or class-string"
81
+ end
82
+
83
+ result.merge(key => formatter)
84
+ end
75
85
  end
86
+ # rubocop: enable Metrics/MethodLength
76
87
 
77
88
  def _formats_options_value(attribute, options)
78
89
  return object&.public_send(attribute) unless options.is_a?(Hash) && options.key?(:value)
79
90
 
80
- if options[:value].is_a?(Symbol)
91
+ case options[:value]
92
+ when Symbol
81
93
  send(options[:value])
82
- elsif options[:value].is_a?(Proc)
94
+ when Proc
83
95
  instance_exec(&options[:value])
96
+ else
97
+ raise FormatsOptionsNotValid, "Options value for #{attribute} must be a symbol or a Proc"
84
98
  end
85
99
  end
86
100
 
@@ -17,7 +17,7 @@ module Chic
17
17
  private
18
18
 
19
19
  def value
20
- object&.to_s
20
+ object.to_s
21
21
  end
22
22
  end
23
23
  end
@@ -12,6 +12,8 @@ module Chic
12
12
 
13
13
  module_function
14
14
 
15
+ # rubocop: disable Metrics/AbcSize
16
+ # rubocop: disable Metrics/MethodLength
15
17
  def presenter_for(object)
16
18
  if object.respond_to?(:presenter_class)
17
19
  object.presenter_class
@@ -19,8 +21,14 @@ module Chic
19
21
  "#{object&.model_name || object.class.name}Presenter".constantize
20
22
  end
21
23
  rescue NameError, LoadError
24
+ if Chic.configuration.raise_exceptions
25
+ raise PresenterClassNotDefined, "Couldn't find a presenter for '#{object.class.name}'"
26
+ end
27
+
22
28
  Chic.configuration.logger&.debug "Couldn't find a presenter for '#{object.class.name}'"
23
29
  nil
24
30
  end
31
+ # rubocop: enable Metrics/AbcSize
32
+ # rubocop: enable Metrics/MethodLength
25
33
  end
26
34
  end
data/lib/chic/presents.rb CHANGED
@@ -90,7 +90,7 @@ module Chic
90
90
 
91
91
  def present(object, with: nil)
92
92
  if object.is_a?(Enumerable)
93
- object.map { |o| present(o, with) }
93
+ object.map { |o| present(o, with: with) }
94
94
  elsif with.present?
95
95
  with.new(object, context)
96
96
  elsif object.nil?
@@ -115,10 +115,13 @@ module Chic
115
115
  def _presents_options_value(attribute, options)
116
116
  return object&.public_send(attribute) unless options.is_a?(Hash) && options.key?(:value)
117
117
 
118
- if options[:value].is_a?(Symbol)
118
+ case options[:value]
119
+ when Symbol
119
120
  send(options[:value])
120
- elsif options[:value].is_a?(Proc)
121
+ when Proc
121
122
  instance_exec(&options[:value])
123
+ else
124
+ raise PresentsOptionsNotValid, "Options value for #{attribute} must be a symbol or a Proc"
122
125
  end
123
126
  end
124
127
  end
data/lib/chic/version.rb CHANGED
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Chic
4
- VERSION = '0.1.0'
4
+ VERSION = '0.3.1'
5
5
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: chic
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.3.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lawrance Shepstone
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2019-06-16 00:00:00.000000000 Z
11
+ date: 2022-08-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -16,14 +16,14 @@ dependencies:
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '2.0'
19
+ version: 2.3.10
20
20
  type: :development
21
21
  prerelease: false
22
22
  version_requirements: !ruby/object:Gem::Requirement
23
23
  requirements:
24
24
  - - "~>"
25
25
  - !ruby/object:Gem::Version
26
- version: '2.0'
26
+ version: 2.3.10
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: minitest
29
29
  requirement: !ruby/object:Gem::Requirement
@@ -44,28 +44,28 @@ dependencies:
44
44
  requirements:
45
45
  - - "~>"
46
46
  - !ruby/object:Gem::Version
47
- version: '10.0'
47
+ version: '13.0'
48
48
  type: :development
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
- version: '10.0'
54
+ version: '13.0'
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: rubocop
57
57
  requirement: !ruby/object:Gem::Requirement
58
58
  requirements:
59
- - - ">="
59
+ - - "~>"
60
60
  - !ruby/object:Gem::Version
61
- version: 0.49.0
61
+ version: '0.71'
62
62
  type: :development
63
63
  prerelease: false
64
64
  version_requirements: !ruby/object:Gem::Requirement
65
65
  requirements:
66
- - - ">="
66
+ - - "~>"
67
67
  - !ruby/object:Gem::Version
68
- version: 0.49.0
68
+ version: '0.71'
69
69
  description:
70
70
  email:
71
71
  - lawrance@collabcollective.com
@@ -81,6 +81,7 @@ files:
81
81
  - LICENSE.txt
82
82
  - README.md
83
83
  - Rakefile
84
+ - bin/bundle
84
85
  - bin/console
85
86
  - bin/setup
86
87
  - chic.gemspec
@@ -111,15 +112,14 @@ required_ruby_version: !ruby/object:Gem::Requirement
111
112
  requirements:
112
113
  - - ">="
113
114
  - !ruby/object:Gem::Version
114
- version: '0'
115
+ version: '2.7'
115
116
  required_rubygems_version: !ruby/object:Gem::Requirement
116
117
  requirements:
117
118
  - - ">="
118
119
  - !ruby/object:Gem::Version
119
120
  version: '0'
120
121
  requirements: []
121
- rubyforge_project:
122
- rubygems_version: 2.7.6
122
+ rubygems_version: 3.1.2
123
123
  signing_key:
124
124
  specification_version: 4
125
125
  summary: Opinionated presentation layer comprised of presenters and formatters.