chic 0.1.0 → 0.3.1

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: 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.