exposant 0.1.1 → 0.2.0

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: d1e1e4a2106643469e0007c4d6655fb2fa80aaa8373a97a71a09f8c473effc9c
4
- data.tar.gz: e37e005611d1f6c055f1d99101aa70aa5d8237d7d02f9783eaa1f4f3c48c3028
3
+ metadata.gz: 3b348ab3f3c0d4c3d274469598cd72c5d234d9a832348ec4824fbfc8936a5957
4
+ data.tar.gz: 94ee91f4ae16555a4161e22f4075d2f83293f72af04f5f0c834e9a351634c072
5
5
  SHA512:
6
- metadata.gz: cf007a8c253a74c14b7d41abdcede220a9e131288ffd10831f298c8ec293b14d9f5a9e393c594d5c735cdd4872b9eb15357e49e470dbfa7b5f6bdca74acd729f
7
- data.tar.gz: 48e9792620ea3226bc2409f02fd655e71c866ce6359706ed5e053b4991394e74dfa0bd85027126b2f62d4d4168106ddc1fff965111e59f37984cdcac155feda7
6
+ metadata.gz: b51a4907d36637a6d86d209b9577539a2e21ae8cc7c0bdd72c17395927acfe26981e19e7503d04de0677f7036609fadecada2c6ded173cb9d85492144748c842
7
+ data.tar.gz: 467b366ac5b9c5ea8f6a60f4bf3e55a32d5049c3b89c1be222836df651a6b7e12194fe5c5160df38c1855507473d9f8328fae896e3eb0685f82b5db5ec1fa3cb
data/.rubocop.yml CHANGED
@@ -19,7 +19,7 @@ Lint/EmptyClass:
19
19
  Enabled: false
20
20
 
21
21
  Metrics/AbcSize:
22
- Max: 50
22
+ Max: 55
23
23
 
24
24
  Metrics/CyclomaticComplexity:
25
25
  Max: 15
data/Gemfile CHANGED
@@ -10,3 +10,5 @@ gem 'rake', '~> 13.0'
10
10
  gem 'minitest', '~> 5.0'
11
11
 
12
12
  gem 'rubocop', '~> 1.21'
13
+
14
+ gem 'pry'
data/Gemfile.lock CHANGED
@@ -1,29 +1,45 @@
1
1
  PATH
2
2
  remote: .
3
3
  specs:
4
- exposant (0.1.1)
5
- activemodel (~> 7.0)
6
- activesupport (~> 7.0)
4
+ exposant (0.2.0)
5
+ activemodel (> 5.0)
6
+ activesupport (> 5.0)
7
7
 
8
8
  GEM
9
9
  remote: https://rubygems.org/
10
10
  specs:
11
- activemodel (7.0.4)
12
- activesupport (= 7.0.4)
13
- activesupport (7.0.4)
11
+ activemodel (7.1.1)
12
+ activesupport (= 7.1.1)
13
+ activesupport (7.1.1)
14
+ base64
15
+ bigdecimal
14
16
  concurrent-ruby (~> 1.0, >= 1.0.2)
17
+ connection_pool (>= 2.2.5)
18
+ drb
15
19
  i18n (>= 1.6, < 2)
16
20
  minitest (>= 5.1)
21
+ mutex_m
17
22
  tzinfo (~> 2.0)
18
23
  ast (2.4.2)
19
- concurrent-ruby (1.1.10)
20
- i18n (1.12.0)
24
+ base64 (0.1.1)
25
+ bigdecimal (3.1.4)
26
+ coderay (1.1.3)
27
+ concurrent-ruby (1.2.2)
28
+ connection_pool (2.4.1)
29
+ drb (2.1.1)
30
+ ruby2_keywords
31
+ i18n (1.14.1)
21
32
  concurrent-ruby (~> 1.0)
22
33
  json (2.6.1)
34
+ method_source (1.0.0)
23
35
  minitest (5.16.3)
36
+ mutex_m (0.1.2)
24
37
  parallel (1.22.1)
25
38
  parser (3.1.2.1)
26
39
  ast (~> 2.4.1)
40
+ pry (0.14.2)
41
+ coderay (~> 1.1)
42
+ method_source (~> 1.0)
27
43
  rainbow (3.1.1)
28
44
  rake (13.0.6)
29
45
  regexp_parser (2.5.0)
@@ -41,7 +57,8 @@ GEM
41
57
  rubocop-ast (1.21.0)
42
58
  parser (>= 3.1.1.0)
43
59
  ruby-progressbar (1.11.0)
44
- tzinfo (2.0.5)
60
+ ruby2_keywords (0.0.5)
61
+ tzinfo (2.0.6)
45
62
  concurrent-ruby (~> 1.0)
46
63
  unicode-display_width (2.2.0)
47
64
 
@@ -51,6 +68,7 @@ PLATFORMS
51
68
  DEPENDENCIES
52
69
  exposant!
53
70
  minitest (~> 5.0)
71
+ pry
54
72
  rake (~> 13.0)
55
73
  rubocop (~> 1.21)
56
74
 
data/README.md CHANGED
@@ -2,9 +2,14 @@
2
2
 
3
3
  In a Rails application, it is often required to fill a gap between Models and
4
4
  Views. There are of course, many differents ways to fill this gap, one of these
5
- is exhibitors (or improved decorators).
5
+ is decorators and its variants exhibits or presenters.
6
6
 
7
- This gem provide an easy way to create Ruby exhibitors or decorators.
7
+ The main difference between decorators, exhibits and presenters are their
8
+ proximity with the rendering layer. Typically a decorator is not meant to be
9
+ contextualized, whereas an exhibit is intended to have access to rendering
10
+ context.
11
+
12
+ This gem provide an easy way to create theese concepts in Ruby.
8
13
 
9
14
  ## Installation
10
15
 
@@ -16,74 +21,90 @@ gem 'exposant'
16
21
 
17
22
  And then execute:
18
23
 
19
- $ bundle install
24
+ ```ruby
25
+ $ bundle install
26
+ ```
20
27
 
21
28
  Or install it yourself as:
22
29
 
23
- $ gem install exposant
30
+ ```
31
+ $ gem install exposant
32
+ ```
24
33
 
25
34
  ## Usage
26
35
 
27
- There are two kinds of exhibitors refering to model or collection.
28
-
29
- A collection exhibitor is meant to encapsulate an enumerable object (like
30
- ActiveRecord Relation or just Array). It overrides `each` method to ensure
31
- encapsulation of resulting objects.
36
+ Exposant objects are intended to overload class (scopes) and instance methods
37
+ of any other object. The default type is exposant, choosing between decorator,
38
+ exhibit or any other type name is up to you. There is no magic involved for the
39
+ context, you just have to call contextualize and provide the required context.
32
40
 
33
- A model exhibitor improve it's associated object, like adding non-database
34
- related methods to an ActiveRecord object for example.
35
-
36
- To use this gem in a Rails application, create a folder `app/exhibitors`.
37
- Create pluralized exhibitors for collections and singularized exhibitors for
38
- models.
39
-
40
- ### Example:
41
+ ### Basic example
41
42
 
42
43
  Consider having a User model with `first_name` and `last_name`
43
44
 
44
45
  ```ruby
45
- # app/models/application_record.rb
46
- class ApplicationRecord < ActiveRecord::Base
47
- include Exposant::Exposable
46
+ # app/models/user.rb
47
+ class User < ActiveRecord::Base
48
+ include Exposant::Model
49
+ has_exposant type: :decorator
48
50
  end
49
51
 
50
- # app/exhibitors/user_exhibitor.rb
51
- class UserExhibitor < Exposant::ModelExhibitor
52
+ # app/decorators/user_decorator.rb
53
+ class UserDecorator < Exposant::Base
54
+ exposant_type :decorator
55
+
52
56
  def full_name
53
57
  "#{first_name} #{last_name}"
54
58
  end
55
59
  end
60
+ ```
61
+
62
+ Then you may want to use your brand new decorator in your controller
56
63
 
57
- # app/exhibitors/users_exhibitor.rb
58
- class UsersExhibitor < Exposant::CollectionExhibitor
59
- # You can add methods for collections too if necessary
64
+ ```ruby
65
+ # app/controllers/users_controller.rb
66
+ class UsersController < DefaultController
67
+ def index
68
+ @users = User.decorator(User.all)
69
+ end
70
+
71
+ def show
72
+ @user = User.find(...).decorator
73
+ end
60
74
  end
61
75
  ```
62
76
 
63
- Then you may want to use your brand new exhibitor in your controller
77
+ ### Contextualization example
78
+
79
+ If you want to contextualize a presenter, for example in a Rails application.
80
+
64
81
  ```ruby
65
82
  # app/controllers/users_controller.rb
66
83
  class UsersController < DefaultController
67
84
  def index
68
- @users = User.exhibitor(User.all)
85
+ @users = User.presenter(User.all)
86
+ @users.contextualize(self)
69
87
  end
70
88
 
71
89
  def show
72
- @user = User.find(...).exhibitor
90
+ @user = User.find(...).presenter
91
+ @user.contextualize(self)
73
92
  end
74
93
  end
75
94
  ```
76
95
 
77
96
  ## Development
78
97
 
79
- After checking out the repo, run `bin/setup` to install dependencies. You can also run `bin/console` for an interactive prompt that will allow you to experiment.
80
-
81
- To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and the created tag, and push the `.gem` file to [rubygems.org](https://rubygems.org).
98
+ After checking out the repo, run `bin/setup` to install dependencies. You can
99
+ also run `bin/console` for an interactive prompt that will allow you to
100
+ experiment.
82
101
 
83
102
  ## Contributing
84
103
 
85
- Bug reports and pull requests are welcome on GitHub at https://github.com/kmmndr/exposant.
104
+ Bug reports and pull requests are welcome on GitHub at
105
+ https://github.com/kmmndr/exposant.
86
106
 
87
107
  ## License
88
108
 
89
- The gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).
109
+ The gem is available as open source under the terms of the
110
+ [MIT License](https://opensource.org/licenses/MIT).
data/exposant.gemspec CHANGED
@@ -30,9 +30,8 @@ Gem::Specification.new do |spec|
30
30
  spec.executables = spec.files.grep(%r{\Aexe/}) { |f| File.basename(f) }
31
31
  spec.require_paths = ['lib']
32
32
 
33
- # Uncomment to register a new dependency of your gem
34
- spec.add_dependency 'activemodel', '~> 7.0'
35
- spec.add_dependency 'activesupport', '~> 7.0'
33
+ spec.add_dependency 'activemodel', '> 5.0'
34
+ spec.add_dependency 'activesupport', '> 5.0'
36
35
 
37
36
  # For more information and examples about making a new gem, check out our
38
37
  # guide at: https://bundler.io/guides/creating_gem.html
@@ -0,0 +1,92 @@
1
+ module Exposant
2
+ class Base < SimpleDelegator
3
+ include Exposant::Contextualizable
4
+ extend ActiveModel::Naming
5
+
6
+ def initialize(*)
7
+ super
8
+
9
+ extend(Exposant::Collection) if __getobj__.is_a?(Enumerable)
10
+ end
11
+
12
+ def to_model
13
+ __getobj__
14
+ end
15
+
16
+ def self.respond_to_missing?(name, *)
17
+ klass.respond_to?(name) || super
18
+ end
19
+
20
+ def self.method_missing(name, *args, &block)
21
+ klass.send(name, *args, &block)
22
+ end
23
+
24
+ def self.human_attribute_name(*args)
25
+ exposed_class.human_attribute_name(*args)
26
+ end
27
+
28
+ def self.klass
29
+ @klass ||= exposed_class
30
+ end
31
+
32
+ def self.belongs_to_model(name)
33
+ exposed_class(name)
34
+ end
35
+
36
+ def self.exposed_class(value = nil)
37
+ @exposed_class = value.constantize if value.present?
38
+ return @exposed_class if @exposed_class.present?
39
+
40
+ return ancestors[1].exposed_class unless ancestors[1] == Exposant::Base || ancestors[1].exposant_base?
41
+
42
+ klass_name = name.gsub(/#{type_name}$/, '')
43
+
44
+ klass_name.constantize
45
+ end
46
+
47
+ def self.exposant_type(value = nil)
48
+ @exposant_type = value if value.present?
49
+ return @exposant_type if @exposant_type.present?
50
+
51
+ return ancestors[1].exposant_type unless ancestors[1] == Exposant::Base
52
+
53
+ :exposant
54
+ end
55
+
56
+ def self.type_name
57
+ exposant_type.to_s.camelcase
58
+ end
59
+
60
+ def self.custom_type?
61
+ exposant_type != :exposant
62
+ end
63
+
64
+ def self.exposant_base?
65
+ !!@exposant_base
66
+ end
67
+
68
+ def self.exposant_base
69
+ @exposant_base = true
70
+ end
71
+
72
+ def self.exposant_variant
73
+ exposed_name = exposed_class.name.demodulize
74
+
75
+ variant = name
76
+ .split('::')
77
+ .tap { |arr| arr.last.gsub!(/#{exposed_name}#{type_name}$/, '') }
78
+ .last
79
+ .downcase
80
+
81
+ return nil if variant.blank?
82
+
83
+ variant.to_sym
84
+ end
85
+
86
+ def self.parent_exposant
87
+ return ancestors[1].parent_exposant unless ancestors[1] == Exposant::Base
88
+
89
+ name.constantize
90
+ end
91
+ end
92
+ end
@@ -0,0 +1,16 @@
1
+ module Exposant
2
+ module Collection
3
+ include Enumerable
4
+
5
+ def each
6
+ return enum_for(:each) unless block_given?
7
+
8
+ super do |obj|
9
+ exposant = obj.exposant(self.class.exposant_variant, self.class.exposant_type)
10
+ exposant.contextualize(context) if contextualized?
11
+
12
+ yield exposant
13
+ end
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,13 @@
1
+ module Exposant
2
+ module Contextualizable
3
+ attr_accessor :context
4
+
5
+ def contextualize(context)
6
+ self.context = context
7
+ end
8
+
9
+ def contextualized?
10
+ context.present?
11
+ end
12
+ end
13
+ end
@@ -0,0 +1,82 @@
1
+ require 'pry'
2
+ module Exposant
3
+ module Model
4
+ extend ActiveSupport::Concern
5
+
6
+ def exposant(variant = nil, type = nil)
7
+ self.class.exposant_class(variant, type).new(self)
8
+ end
9
+
10
+ module ClassMethods
11
+ def has_exposant(name: nil, type: nil)
12
+ @exposant_class = name
13
+ @exposant_type = type
14
+
15
+ if type.present? && type != :exposant
16
+ raise 'Type must be a symbol' unless type.is_a?(Symbol)
17
+
18
+ define_method type do |variant = nil|
19
+ exposant(variant, type)
20
+ end
21
+
22
+ define_singleton_method type do |obj, variant = nil|
23
+ exposant(obj, variant, type)
24
+ end
25
+ end
26
+
27
+ self
28
+ end
29
+
30
+ def exposant_type
31
+ @exposant_type || :exposant
32
+ end
33
+
34
+ def exposant(obj, variant = nil, type = nil)
35
+ obj.extend(ExposantMethods)
36
+ obj.model_klass = self
37
+
38
+ if type.present? && type != :exposant
39
+ raise 'Type must be a symbol' unless type.is_a?(Symbol)
40
+
41
+ obj.singleton_class.class_eval do
42
+ define_method type do |var = nil|
43
+ exposant(var, type)
44
+ end
45
+ end
46
+ end
47
+
48
+ obj.exposant(variant, type)
49
+ end
50
+
51
+ def exposant_class(variant = nil, type = nil)
52
+ type_name = (type || exposant_type).to_s.camelcase
53
+ klass = if @exposant_class.present?
54
+ @exposant_class
55
+ else
56
+ name.dup.concat(type_name)
57
+ end
58
+
59
+ klass = klass
60
+ .split('::')
61
+ .tap { |arr| arr.last.prepend(variant&.to_s&.downcase&.capitalize || '') }
62
+ .join('::')
63
+
64
+ raise "Missing exposant #{klass}" unless const_defined?(klass)
65
+
66
+ klass.constantize
67
+ end
68
+ end
69
+ end
70
+
71
+ module ExposantMethods
72
+ attr_accessor :model_klass
73
+
74
+ def exposant(variant = nil, type = nil)
75
+ exposant_class(variant, type).new(self)
76
+ end
77
+
78
+ def exposant_class(variant = nil, type = nil)
79
+ model_klass.exposant_class(variant, type)
80
+ end
81
+ end
82
+ end
@@ -1,5 +1,5 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Exposant
4
- VERSION = '0.1.1'
4
+ VERSION = '0.2.0'
5
5
  end
data/lib/exposant.rb CHANGED
@@ -4,13 +4,12 @@ require 'delegate'
4
4
  require 'active_support'
5
5
  require 'active_model'
6
6
 
7
- require_relative 'exposant/concerns/exhibitor'
8
- require_relative 'exposant/concerns/exposable'
9
- require_relative 'exposant/collection_exhibitor'
10
- require_relative 'exposant/model_exhibitor'
7
+ require_relative 'exposant/concerns/contextualizable'
8
+ require_relative 'exposant/concerns/collection'
9
+ require_relative 'exposant/model'
10
+ require_relative 'exposant/base'
11
11
  require_relative 'exposant/version'
12
12
 
13
13
  module Exposant
14
14
  class Error < StandardError; end
15
- # Your code goes here...
16
15
  end
metadata CHANGED
@@ -1,43 +1,43 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: exposant
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.1
4
+ version: 0.2.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Thomas Kienlen
8
8
  autorequire:
9
9
  bindir: exe
10
10
  cert_chain: []
11
- date: 2022-12-08 00:00:00.000000000 Z
11
+ date: 2023-11-06 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: activemodel
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
- - - "~>"
17
+ - - ">"
18
18
  - !ruby/object:Gem::Version
19
- version: '7.0'
19
+ version: '5.0'
20
20
  type: :runtime
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: '7.0'
26
+ version: '5.0'
27
27
  - !ruby/object:Gem::Dependency
28
28
  name: activesupport
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
- - - "~>"
31
+ - - ">"
32
32
  - !ruby/object:Gem::Version
33
- version: '7.0'
33
+ version: '5.0'
34
34
  type: :runtime
35
35
  prerelease: false
36
36
  version_requirements: !ruby/object:Gem::Requirement
37
37
  requirements:
38
- - - "~>"
38
+ - - ">"
39
39
  - !ruby/object:Gem::Version
40
- version: '7.0'
40
+ version: '5.0'
41
41
  description:
42
42
  email:
43
43
  - kommander@laposte.net
@@ -54,10 +54,10 @@ files:
54
54
  - Rakefile
55
55
  - exposant.gemspec
56
56
  - lib/exposant.rb
57
- - lib/exposant/collection_exhibitor.rb
58
- - lib/exposant/concerns/exhibitor.rb
59
- - lib/exposant/concerns/exposable.rb
60
- - lib/exposant/model_exhibitor.rb
57
+ - lib/exposant/base.rb
58
+ - lib/exposant/concerns/collection.rb
59
+ - lib/exposant/concerns/contextualizable.rb
60
+ - lib/exposant/model.rb
61
61
  - lib/exposant/version.rb
62
62
  homepage: http://127.0.0.1:3000
63
63
  licenses:
@@ -80,7 +80,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
80
80
  - !ruby/object:Gem::Version
81
81
  version: '0'
82
82
  requirements: []
83
- rubygems_version: 3.3.7
83
+ rubygems_version: 3.4.10
84
84
  signing_key:
85
85
  specification_version: 4
86
86
  summary: Simple way to create decorators and presenters
@@ -1,25 +0,0 @@
1
- module Exposant
2
- class CollectionExhibitor < SimpleDelegator
3
- include Exhibitor
4
- extend ActiveModel::Naming
5
- include Enumerable
6
-
7
- def self.exhibitor_variant
8
- self::MODEL_PRESENTER_VARIANT if const_defined?('MODEL_PRESENTER_VARIANT')
9
- end
10
-
11
- def each
12
- return enum_for(:each) unless block_given?
13
-
14
- __getobj__.each do |o|
15
- exh = o.exhibitor(self.class.exhibitor_variant)
16
- exh.contextualize(context) if contextualized?
17
- yield exh
18
- end
19
- end
20
-
21
- def to_model
22
- self
23
- end
24
- end
25
- end
@@ -1,34 +0,0 @@
1
- module Exhibitor
2
- extend ActiveSupport::Concern
3
- attr_accessor :context
4
-
5
- def obj
6
- __getobj__
7
- end
8
-
9
- def exhibitor_for(obj)
10
- self.class.exhibitor_for(obj)
11
- end
12
-
13
- def contextualize(context)
14
- self.context = context
15
- end
16
-
17
- def contextualized?
18
- context.present?
19
- end
20
-
21
- module ClassMethods
22
-
23
- def exhibitor_for_super(method, klass = nil)
24
- define_method(method) do |*args|
25
- klass ||= self.class
26
- klass.new(super(*args))
27
- end
28
- end
29
-
30
- def exhibitor_for(obj)
31
- new(obj)
32
- end
33
- end
34
- end
@@ -1,56 +0,0 @@
1
- module Exposant
2
- module Exposable
3
- module Model
4
- extend ActiveSupport::Concern
5
-
6
- def exhibitor(variant = nil)
7
- self.class.exhibitor_class(variant).new(self)
8
- end
9
-
10
- module ClassMethods
11
- def exhibitor(obj, variant = nil)
12
- obj.extend(Exposable::Collection)
13
- obj.model_klass = self
14
-
15
- obj.exhibitor(variant)
16
- end
17
-
18
- def exhibitor_class(variant = nil)
19
- klass = [
20
- name,
21
- variant&.downcase&.capitalize,
22
- 'Exhibitor'
23
- ].join
24
-
25
- raise "Missing exhibitor #{klass}" unless const_defined?(klass)
26
-
27
- klass.constantize
28
- end
29
- end
30
- end
31
-
32
- module Collection
33
- attr_accessor :model_klass
34
-
35
- def exhibitor(variant = nil)
36
- exhibitor_class(variant).new(self)
37
- end
38
-
39
- def exhibitor_class(variant = nil)
40
- klass_name = model_klass.name
41
-
42
- klass = [
43
- klass_name.pluralize,
44
- variant&.downcase&.capitalize,
45
- 'Exhibitor'
46
- ].join
47
-
48
- begin
49
- klass.constantize
50
- rescue NameError
51
- raise "Missing exhibitor #{klass}"
52
- end
53
- end
54
- end
55
- end
56
- end
@@ -1,34 +0,0 @@
1
- module Exposant
2
- class ModelExhibitor < SimpleDelegator
3
- include Exhibitor
4
- extend ActiveModel::Naming
5
-
6
- def to_model
7
- obj
8
- end
9
-
10
- def self.human_attribute_name(*args)
11
- exhibited_class.human_attribute_name(*args)
12
- end
13
-
14
- def self.exhibited_class
15
- return ancestors[1].exhibited_class unless ancestors[1] == ModelExhibitor
16
-
17
- name.gsub(/Exhibitor$/, '').constantize
18
- end
19
-
20
- def self.exhibitor_variant
21
- variant = name[parent_exhibitor.exhibited_class.name.length..].gsub(/Exhibitor$/, '').downcase
22
-
23
- return nil if variant.blank?
24
-
25
- variant.to_sym
26
- end
27
-
28
- def self.parent_exhibitor
29
- return ancestors[1].parent_exhibitor unless ancestors[1] == ModelExhibitor
30
-
31
- name.constantize
32
- end
33
- end
34
- end