hexx 7.1.0 → 8.0.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.
Files changed (82) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +2 -0
  3. data/.gitignore +9 -0
  4. data/.metrics +5 -0
  5. data/.rspec +2 -0
  6. data/.rubocop.yml +2 -63
  7. data/.travis.yml +5 -0
  8. data/.yardopts +2 -0
  9. data/Gemfile +3 -0
  10. data/Guardfile +16 -0
  11. data/{LICENSE.rdoc → LICENSE} +2 -2
  12. data/README.md +138 -0
  13. data/Rakefile +8 -14
  14. data/config/initializer.rb +5 -0
  15. data/config/initializers/capture.rb +19 -0
  16. data/config/initializers/sandbox.rb +16 -0
  17. data/config/initializers/sandbox/helpers.rb +38 -0
  18. data/config/initializers/sandbox/matchers.rb +19 -0
  19. data/config/metrics/STYLEGUIDE +230 -0
  20. data/config/metrics/cane.yml +5 -0
  21. data/config/metrics/churn.yml +6 -0
  22. data/config/metrics/flay.yml +2 -0
  23. data/config/metrics/metric_fu.yml +15 -0
  24. data/config/metrics/pippi.yml +3 -0
  25. data/config/metrics/reek.yml +1 -0
  26. data/config/metrics/roodi.yml +24 -0
  27. data/config/metrics/rubocop.yml +79 -0
  28. data/config/metrics/saikuro.yml +3 -0
  29. data/config/metrics/simplecov.yml +6 -0
  30. data/config/metrics/yardstick.yml +37 -0
  31. data/hexx.gemspec +24 -0
  32. data/lib/hexx.rb +8 -15
  33. data/lib/hexx/generator.rb +71 -0
  34. data/lib/hexx/generator/file.rb +83 -0
  35. data/lib/hexx/generator/folder.rb +68 -0
  36. data/lib/hexx/name.rb +122 -46
  37. data/lib/hexx/version.rb +6 -5
  38. data/spec/fixtures/root/_.beta +1 -0
  39. data/spec/fixtures/root/__omega +0 -0
  40. data/spec/fixtures/root/delta.erb.erb +0 -0
  41. data/spec/fixtures/root/gamma.rb.erb +1 -0
  42. data/spec/fixtures/root/subfolder/alfa.yml +0 -0
  43. data/spec/spec_helper.rb +5 -10
  44. data/spec/tests/lib/generator_spec.rb +126 -0
  45. data/spec/tests/lib/name_spec.rb +113 -0
  46. metadata +54 -168
  47. data/README.rdoc +0 -371
  48. data/lib/hexx/coercible.rb +0 -43
  49. data/lib/hexx/configurable.rb +0 -101
  50. data/lib/hexx/creators/base.rb +0 -103
  51. data/lib/hexx/creators/coercion.rb +0 -82
  52. data/lib/hexx/creators/dependency.rb +0 -87
  53. data/lib/hexx/creators/module_dependency.rb +0 -57
  54. data/lib/hexx/creators/parameter.rb +0 -40
  55. data/lib/hexx/dependable.rb +0 -51
  56. data/lib/hexx/helpers/exceptions.rb +0 -53
  57. data/lib/hexx/helpers/messages.rb +0 -26
  58. data/lib/hexx/helpers/parameters.rb +0 -47
  59. data/lib/hexx/helpers/validations.rb +0 -21
  60. data/lib/hexx/message.rb +0 -79
  61. data/lib/hexx/null.rb +0 -218
  62. data/lib/hexx/service.rb +0 -388
  63. data/lib/hexx/service/with_callbacks.rb +0 -104
  64. data/lib/hexx/service_invalid.rb +0 -73
  65. data/spec/hexx/coercible_spec.rb +0 -72
  66. data/spec/hexx/configurable_spec.rb +0 -93
  67. data/spec/hexx/dependable_spec.rb +0 -125
  68. data/spec/hexx/helpers/exceptions_spec.rb +0 -96
  69. data/spec/hexx/helpers/messages_spec.rb +0 -48
  70. data/spec/hexx/helpers/parameters_spec.rb +0 -96
  71. data/spec/hexx/helpers/validations_spec.rb +0 -32
  72. data/spec/hexx/message_spec.rb +0 -83
  73. data/spec/hexx/name_spec.rb +0 -80
  74. data/spec/hexx/null_spec.rb +0 -152
  75. data/spec/hexx/service_invalid_spec.rb +0 -46
  76. data/spec/hexx/service_spec.rb +0 -89
  77. data/spec/support/initializers/focus.rb +0 -5
  78. data/spec/support/initializers/garbage_collection.rb +0 -11
  79. data/spec/support/initializers/i18n.rb +0 -3
  80. data/spec/support/initializers/random_order.rb +0 -4
  81. data/spec/support/initializers/rspec.rb +0 -5
  82. data/spec/support/matchers/methods.rb +0 -11
metadata CHANGED
@@ -1,192 +1,96 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: hexx
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.1.0
4
+ version: 8.0.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Andrew Kozin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-01-21 00:00:00.000000000 Z
11
+ date: 2015-03-02 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
- name: activemodel
14
+ name: extlib
15
15
  requirement: !ruby/object:Gem::Requirement
16
16
  requirements:
17
17
  - - "~>"
18
18
  - !ruby/object:Gem::Version
19
- version: '4.1'
19
+ version: '0.9'
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: '4.1'
26
+ version: '0.9'
27
27
  - !ruby/object:Gem::Dependency
28
- name: wisper
28
+ name: hexx-suit
29
29
  requirement: !ruby/object:Gem::Requirement
30
30
  requirements:
31
31
  - - "~>"
32
32
  - !ruby/object:Gem::Version
33
- version: '1.3'
33
+ version: '0.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: '1.3'
41
- - !ruby/object:Gem::Dependency
42
- name: coveralls
43
- requirement: !ruby/object:Gem::Requirement
44
- requirements:
45
- - - "~>"
46
- - !ruby/object:Gem::Version
47
- version: '0.7'
48
- type: :development
49
- prerelease: false
50
- version_requirements: !ruby/object:Gem::Requirement
51
- requirements:
52
- - - "~>"
53
- - !ruby/object:Gem::Version
54
- version: '0.7'
55
- - !ruby/object:Gem::Dependency
56
- name: inch
57
- requirement: !ruby/object:Gem::Requirement
58
- requirements:
59
- - - "~>"
60
- - !ruby/object:Gem::Version
61
- version: '0.5'
62
- type: :development
63
- prerelease: false
64
- version_requirements: !ruby/object:Gem::Requirement
65
- requirements:
66
- - - "~>"
67
- - !ruby/object:Gem::Version
68
- version: '0.5'
69
- - !ruby/object:Gem::Dependency
70
- name: metric_fu
71
- requirement: !ruby/object:Gem::Requirement
72
- requirements:
73
- - - "~>"
74
- - !ruby/object:Gem::Version
75
- version: '4.11'
76
- type: :development
77
- prerelease: false
78
- version_requirements: !ruby/object:Gem::Requirement
79
- requirements:
80
- - - "~>"
81
- - !ruby/object:Gem::Version
82
- version: '4.11'
83
- - !ruby/object:Gem::Dependency
84
- name: rake
85
- requirement: !ruby/object:Gem::Requirement
86
- requirements:
87
- - - "~>"
88
- - !ruby/object:Gem::Version
89
- version: '10.3'
90
- type: :development
91
- prerelease: false
92
- version_requirements: !ruby/object:Gem::Requirement
93
- requirements:
94
- - - "~>"
95
- - !ruby/object:Gem::Version
96
- version: '10.3'
97
- - !ruby/object:Gem::Dependency
98
- name: rspec
99
- requirement: !ruby/object:Gem::Requirement
100
- requirements:
101
- - - "~>"
102
- - !ruby/object:Gem::Version
103
- version: '3.0'
104
- type: :development
105
- prerelease: false
106
- version_requirements: !ruby/object:Gem::Requirement
107
- requirements:
108
- - - "~>"
109
- - !ruby/object:Gem::Version
110
- version: '3.0'
111
- - !ruby/object:Gem::Dependency
112
- name: rubocop
113
- requirement: !ruby/object:Gem::Requirement
114
- requirements:
115
- - - "~>"
116
- - !ruby/object:Gem::Version
117
- version: '0.23'
118
- type: :development
119
- prerelease: false
120
- version_requirements: !ruby/object:Gem::Requirement
121
- requirements:
122
- - - "~>"
123
- - !ruby/object:Gem::Version
124
- version: '0.23'
125
- - !ruby/object:Gem::Dependency
126
- name: guard-rspec
127
- requirement: !ruby/object:Gem::Requirement
128
- requirements:
129
- - - "~>"
130
- - !ruby/object:Gem::Version
131
- version: '4.3'
132
- type: :development
133
- prerelease: false
134
- version_requirements: !ruby/object:Gem::Requirement
135
- requirements:
136
- - - "~>"
137
- - !ruby/object:Gem::Version
138
- version: '4.3'
139
- description: Defines domain service object and model attributes coercion.
40
+ version: '0.0'
41
+ description: Collection of scaffolders.
140
42
  email: andrew.kozin@gmail.com
141
43
  executables: []
142
44
  extensions: []
143
45
  extra_rdoc_files:
144
- - LICENSE.rdoc
145
- - README.rdoc
46
+ - README.md
47
+ - LICENSE
48
+ - config/metrics/STYLEGUIDE
146
49
  files:
50
+ - ".coveralls.yml"
51
+ - ".gitignore"
52
+ - ".metrics"
53
+ - ".rspec"
147
54
  - ".rubocop.yml"
148
- - LICENSE.rdoc
149
- - README.rdoc
55
+ - ".travis.yml"
56
+ - ".yardopts"
57
+ - Gemfile
58
+ - Guardfile
59
+ - LICENSE
60
+ - README.md
150
61
  - Rakefile
62
+ - config/initializer.rb
63
+ - config/initializers/capture.rb
64
+ - config/initializers/sandbox.rb
65
+ - config/initializers/sandbox/helpers.rb
66
+ - config/initializers/sandbox/matchers.rb
67
+ - config/metrics/STYLEGUIDE
68
+ - config/metrics/cane.yml
69
+ - config/metrics/churn.yml
70
+ - config/metrics/flay.yml
71
+ - config/metrics/metric_fu.yml
72
+ - config/metrics/pippi.yml
73
+ - config/metrics/reek.yml
74
+ - config/metrics/roodi.yml
75
+ - config/metrics/rubocop.yml
76
+ - config/metrics/saikuro.yml
77
+ - config/metrics/simplecov.yml
78
+ - config/metrics/yardstick.yml
79
+ - hexx.gemspec
151
80
  - lib/hexx.rb
152
- - lib/hexx/coercible.rb
153
- - lib/hexx/configurable.rb
154
- - lib/hexx/creators/base.rb
155
- - lib/hexx/creators/coercion.rb
156
- - lib/hexx/creators/dependency.rb
157
- - lib/hexx/creators/module_dependency.rb
158
- - lib/hexx/creators/parameter.rb
159
- - lib/hexx/dependable.rb
160
- - lib/hexx/helpers/exceptions.rb
161
- - lib/hexx/helpers/messages.rb
162
- - lib/hexx/helpers/parameters.rb
163
- - lib/hexx/helpers/validations.rb
164
- - lib/hexx/message.rb
81
+ - lib/hexx/generator.rb
82
+ - lib/hexx/generator/file.rb
83
+ - lib/hexx/generator/folder.rb
165
84
  - lib/hexx/name.rb
166
- - lib/hexx/null.rb
167
- - lib/hexx/service.rb
168
- - lib/hexx/service/with_callbacks.rb
169
- - lib/hexx/service_invalid.rb
170
85
  - lib/hexx/version.rb
171
- - spec/hexx/coercible_spec.rb
172
- - spec/hexx/configurable_spec.rb
173
- - spec/hexx/dependable_spec.rb
174
- - spec/hexx/helpers/exceptions_spec.rb
175
- - spec/hexx/helpers/messages_spec.rb
176
- - spec/hexx/helpers/parameters_spec.rb
177
- - spec/hexx/helpers/validations_spec.rb
178
- - spec/hexx/message_spec.rb
179
- - spec/hexx/name_spec.rb
180
- - spec/hexx/null_spec.rb
181
- - spec/hexx/service_invalid_spec.rb
182
- - spec/hexx/service_spec.rb
86
+ - spec/fixtures/root/_.beta
87
+ - spec/fixtures/root/__omega
88
+ - spec/fixtures/root/delta.erb.erb
89
+ - spec/fixtures/root/gamma.rb.erb
90
+ - spec/fixtures/root/subfolder/alfa.yml
183
91
  - spec/spec_helper.rb
184
- - spec/support/initializers/focus.rb
185
- - spec/support/initializers/garbage_collection.rb
186
- - spec/support/initializers/i18n.rb
187
- - spec/support/initializers/random_order.rb
188
- - spec/support/initializers/rspec.rb
189
- - spec/support/matchers/methods.rb
92
+ - spec/tests/lib/generator_spec.rb
93
+ - spec/tests/lib/name_spec.rb
190
94
  homepage: https://github.com/nepalez/hexx
191
95
  licenses:
192
96
  - MIT
@@ -197,7 +101,7 @@ require_paths:
197
101
  - lib
198
102
  required_ruby_version: !ruby/object:Gem::Requirement
199
103
  requirements:
200
- - - "~>"
104
+ - - ">="
201
105
  - !ruby/object:Gem::Version
202
106
  version: '2.1'
203
107
  required_rubygems_version: !ruby/object:Gem::Requirement
@@ -210,27 +114,9 @@ rubyforge_project:
210
114
  rubygems_version: 2.2.2
211
115
  signing_key:
212
116
  specification_version: 4
213
- summary: Service objects for Rails.
117
+ summary: Collection of scaffolders for projects that follow the hexagonal architecture.
214
118
  test_files:
215
119
  - spec/spec_helper.rb
216
- - spec/hexx/service_spec.rb
217
- - spec/hexx/message_spec.rb
218
- - spec/hexx/null_spec.rb
219
- - spec/hexx/helpers/parameters_spec.rb
220
- - spec/hexx/helpers/messages_spec.rb
221
- - spec/hexx/helpers/validations_spec.rb
222
- - spec/hexx/helpers/exceptions_spec.rb
223
- - spec/hexx/service_invalid_spec.rb
224
- - spec/hexx/coercible_spec.rb
225
- - spec/hexx/dependable_spec.rb
226
- - spec/hexx/name_spec.rb
227
- - spec/hexx/configurable_spec.rb
228
- - spec/support/matchers/methods.rb
229
- - spec/support/initializers/garbage_collection.rb
230
- - spec/support/initializers/i18n.rb
231
- - spec/support/initializers/focus.rb
232
- - spec/support/initializers/random_order.rb
233
- - spec/support/initializers/rspec.rb
234
- - Rakefile
235
- - ".rubocop.yml"
120
+ - spec/tests/lib/generator_spec.rb
121
+ - spec/tests/lib/name_spec.rb
236
122
  has_rdoc:
@@ -1,371 +0,0 @@
1
- = Hexx
2
-
3
- {<img src="http://img.shields.io/gem/v/hexx.svg?style=flat" alt="Gem Version" />}[https://rubygems.org/gems/hexx]
4
- {<img src="http://img.shields.io/travis/nepalez/hexx.svg?style=flat" alt="Bild Status" />}[https://travis-ci.org/nepalez/hexx]
5
- {<img src="http://img.shields.io/codeclimate/github/nepalez/hexx.svg?style=flat" alt="Code Metrics" />}[https://codeclimate.com/github/nepalez/hexx]
6
- {<img src="http://img.shields.io/gemnasium/nepalez/hexx.svg?style=flat" alt="Dependency Status" />}[https://gemnasium.com/nepalez/hexx]
7
- {<img src="http://img.shields.io/coveralls/nepalez/hexx.svg?style=flat" alt="Coverage Status" />}[https://coveralls.io/r/nepalez/hexx]
8
- {<img src="http://img.shields.io/badge/license-MIT-blue.svg?style=flat" alt="License" />}[https://github.com/nepalez/hexx/blob/master/LICENSE.rdoc]
9
-
10
- The base library for domain models.
11
-
12
- == API
13
-
14
- Includes classes and modules as below:
15
- <tt>Hexx::Service</tt>:: The base class for service objects.
16
- <tt>Hexx::Message</tt>:: The message provided by service objects.
17
- <tt>Hexx::Null</tt>:: The Null object.
18
- <tt>Hexx::Coercible</tt>:: The module that makes model attributes coercible.
19
- <tt>Hexx::Configurable</tt>:: The module to convert a core domain module to the
20
- dependency injection framework.
21
- <tt>Hexx::Dependable</tt>:: The module provides +depends_on+ class helper methodto
22
- to implement the setter dependency injection.
23
-
24
- The module is expected to be used in PORO domains for Ruby MRI 2.1+.
25
-
26
- For usage in active record bases domains consider the
27
- { hexx-active_record }[https://github.com/nepalez/hexx-active_record]
28
- gem extension.
29
-
30
- == Installation
31
-
32
- Add this line to your application's Gemfile:
33
-
34
- gem "hexx", "~> 2.0"
35
-
36
- And then execute:
37
-
38
- $ bundle
39
-
40
- Or install it yourself as:
41
-
42
- $ gem install hexx
43
-
44
- == Usage
45
-
46
- === Hexx::Configurable
47
-
48
- Adds the +configure+ and +depends_on+ helpers to the module to convert it
49
- to the {dependency injection container}[http://en.m.wikipedia.org/wiki/Dependency_injection].
50
-
51
- Extend the base class of the gem and declare the module dependencies from
52
- outer classes and modules with the +depend_on+ helper:
53
-
54
- # lib/my_gem.rb
55
- module MyGem
56
- extend Hexx::Configurable
57
-
58
- depend_on :get_item, :add_item
59
- end
60
-
61
- Inject the dependencies in the gem config with the +configure+ wrapper:
62
-
63
- # config/dependencies.rb
64
- MyGem.configure do |c|
65
- c.get_item = OuterModule::Services::Get
66
- c.add_item = OuterModule::Services::Add
67
- end
68
-
69
- Use the dependencies somewhere inside the code of the gem:
70
-
71
- MyGem.get_item # => OuterModule::Services::Get
72
-
73
- === Hexx::Coercible
74
-
75
- Adds the +attr_coerced+ class helper method to the PORO model.
76
-
77
- Provide a value object that accepts <tt>0..1</tt> arguments.
78
-
79
- # app/attributes/coercer.rb
80
- class Coercer < MultiByte::Chars
81
- def self.new(source = nil)
82
- return unless source
83
- end
84
-
85
- def initialize(source)
86
- # ...
87
- end
88
- end
89
-
90
- Extend the model with a +Coercible+ module and declare its attributes
91
- with the +attr_coerced+ helper.
92
-
93
- # app/models/some_model.rb
94
- class SomeModel
95
- extend Hexx::Coercible
96
-
97
- attr_coerced :name, type: Coercer
98
- end
99
-
100
- Both the getter and setter will return the coerced value, provided by
101
- the +Coercer+ class.
102
-
103
- object = SomeModel.new name: "Ivo"
104
- object.name
105
- # #<Coercer @wrapped_string="Ivo" >
106
-
107
- Be careful when designing a coercer class. Its constructor should accept both
108
- the raw value (<tt>"Ivo"</tt>) and the coerced one (<tt>#<Coercer @wrapped_string = "Ivo"></tt>).
109
- This is needed because the coercer works twofold - it coerces both the
110
- setter and getter. The getter coercer will take the coerced value.
111
-
112
- This feature is added for compatibility with +ActiveRecord+ attributes
113
- whose getters gives raw values from a database.
114
-
115
- *Note*: The coercer from the +hexx+ gem itself won't work for +ActiveRecord+ models.
116
- Use the +hexx-active_record+ gem instead. The gem extends the +Coercible+ model
117
- so that the +attr_coerced+ reloads +ActiveRecord+ attributes properly.
118
-
119
- === Hexx::Service
120
-
121
- Inherit services from the <tt>Hexx::Service</tt> class.
122
-
123
- The class implements a set of patterns:
124
-
125
- * The {Service object pattern}[http://blog.codeclimate.com/blog/2012/10/17/7-ways-to-decompose-fat-activerecord-models/] used to decouple business logics from both the models and web delivery mechanism (such as +Rails+).
126
- * The {Observer pattern}[http://reefpoints.dockyard.com/2013/08/20/design-patterns-observer-pattern.html] to follow the {Tell, don't ask}[http://martinfowler.com/bliki/TellDontAsk.html] design princible.
127
- The pattern is implemented with the help of {wisper}[http://www.github.com/krisleech/wisper] gem by Kris Leech.
128
-
129
- A typical service object is shown below:
130
-
131
- # app/services/add_item.rb
132
- require 'hexx'
133
- class AddItem < Hexx::Service
134
-
135
- # Whitelists parameters and defines corresponding attributes.
136
- # For example, the #name attribute is avalable.
137
- allow_params :name
138
-
139
- # Defines some validation using ActiveModel::Validations helpers.
140
- validate :name, presence: true
141
-
142
- # Runs a service
143
- def run
144
- run!
145
- rescue Found
146
- # Publishes notification in case the item exists.
147
- publish :found, item
148
- rescue => err
149
- publish :error, err.messages
150
- else
151
- # The notification to be published if the #run! raises nothing.
152
- publish :added, item
153
- end
154
-
155
- private
156
-
157
- attr_accessor :item
158
-
159
- # Declares specific exceptions to be raised by the #run! method
160
- # and processed by the #run differently.
161
- #
162
- # All other exceptions will be re-raised as Hexx::Service::Invalid
163
- # and processed by publishing the :error notification.
164
- raises :Found
165
-
166
- # The sequence of the service steps. Any step can raise error to
167
- # be rescued in #run with publishing a corresponding notification.
168
- def run!
169
- find_item
170
- add_item
171
- end
172
-
173
- def find_item
174
- # The method runs another service and listens to its notifications
175
- # via private callback methods available to that service only.
176
- # The callback names should start from given prefix (:on_item_).
177
- run_service GetItem, :on_item, name: name
178
- end
179
-
180
- # The callback to listen to :found notification of the 'get_item' service.
181
- def on_item_found(item, *)
182
- @item = item
183
- # Adds the Hexx::Message object of type "error" to the +messages+ array.
184
- # The :not_found key will be translated in context of current service:
185
- # {locale}.activemodule.messages.models.add_item.not_found
186
- add_message "error", :not_found
187
- fail Found # goes to publishing a result
188
- end
189
-
190
- # The callback to listen to :error notification of the 'get_item' service.
191
- # that is expected to publish a list of error messages.
192
- def on_item_error(*, messages)
193
- # The helper raises Hexx::Service::Invalid exception where the messages
194
- # are added to. The exception will be rescued by the #run method.
195
- on_error(messages)
196
- end
197
-
198
- def add_item
199
- # The escape re-raises any error as the Hexx::Service::Invalid
200
- # with the array of Hexx::Message messages.
201
- escape { @item = Item.create! name: name }
202
- end
203
- end
204
-
205
- A typical usage of the service (in a Rails controller):
206
-
207
- # app/controllers/items_controller.rb
208
- class ItemsController < ActionController::Base
209
-
210
- # Creates an item with given name
211
- def create
212
- service = AddItem.new params.allow(:name)
213
- service.subscribe self, prefix: :on
214
- service.run
215
- end
216
-
217
- # Publishes a success message
218
- def on_created(item, messages)
219
- @item = item
220
- self.messages.concat messages
221
- render "created", status: 201
222
- end
223
-
224
- # Responds with 304 (not changed)
225
- def on_found(*)
226
- render nothing: true, status: 304
227
- end
228
-
229
- # Publishes an error messages
230
- def on_error(messages)
231
- @messages = messages
232
- render "error", status: 422
233
- end
234
- end
235
-
236
- The controller knows nothing about the action itself. It only needs to
237
- send the request to a corresponding service and sort out the notifications.
238
-
239
- === Hexx::Message
240
-
241
- The messages published by the service has two attributes: +type+ and +text+.
242
-
243
- message = Hexx::Message.new type: :error, text: "some error message"
244
- message.type # => "error"
245
- message.text # => "some error message"
246
-
247
- Inside a service use the +add_message+ to add message to the +messages+ array:
248
-
249
- add_message "error", "text"
250
- messages # => [#<Hexx::Message @type="error", @text="text" >]
251
-
252
- === Hexx::Dependable
253
-
254
- The module provides the +depends_on+ class helper for {setter-based dependency injection}[http://brandonhilkert.com/blog/a-ruby-refactor-exploring-dependency-injection-options/]. It allows decoupling the service from another services it uses.
255
-
256
- Extend the service class and declare the dependencies with an optional default
257
- implementation (see example above):
258
-
259
- class AddItem < Hexx::Service
260
- extend Hexx::Dependable
261
-
262
- depends_on :get_item, default: GetItem
263
-
264
- # ...
265
-
266
- def find_item
267
- run_service get_item, :on_item, name: name
268
- end
269
- end
270
-
271
- Now the dependency can be injected afterwards:
272
-
273
- # The default implementation
274
- service = AddItem.new
275
- service.get_item # => GetItem
276
-
277
- # Change it to other implementation
278
- service.get_item = FindItem
279
- service.get_item # => FindItem
280
-
281
- # Reset it to default by assigning +nil+
282
- service.get_item = nil
283
- service.get_item # => GetItem
284
-
285
- It is possible to test a service in isolation from its dependencies.
286
-
287
- # spec/services/my_service_spec.rb
288
- describe AddService do
289
-
290
- describe "#run" do
291
-
292
- # Mock a service objects to publish expected notifications
293
- let(:object) { Hexx::Service }
294
- before { allow(object).to receive(:run) { publish :not_found } }
295
-
296
- # Inject a class dependency
297
- before { service.get_item = class_double "Hexx::Service", new: object }
298
-
299
- # ...
300
- end
301
- end
302
-
303
- === Hexx::Name
304
-
305
- The module provides the base class for name constructors for various instances.
306
-
307
- It declares helpers:
308
-
309
- * +object+:: the attribute for the object to be named
310
- * +locale+:: the locale to name the object in
311
- * +scope+:: the current translation scope
312
- * +t(value, options):: the translator of the value in current scope and locale
313
-
314
- Inherit the class and reload its <tt>#for</tt> instance method:
315
-
316
- module Names
317
- class Hash < Hexx::Name
318
- def for
319
- user ? t(:user, value: user) : t(:empty)
320
- end
321
-
322
- def user
323
- value = object[:user]
324
- value ? value.upcase : nil
325
- end
326
- end
327
- end
328
-
329
- Add the necessary translations:
330
-
331
- # config/locales/ru.yml
332
- ru:
333
- activemodel:
334
- names/hash:
335
- user: "чувак %{value}"
336
- empty: "н/д"
337
-
338
- # config/locales/en.yml
339
- en:
340
- activemodel:
341
- names/hash:
342
- user: "dude %{value}"
343
- empty: "-"
344
-
345
- Then use its <tt>for</tt> class method to construct names:
346
-
347
- Names::Hash.for { user: "Ivan" }, locale: :en
348
- # => "dude IVAN"
349
-
350
- Names::Hash.for { user: nil }, locale: :ru
351
- # => "н/д"
352
-
353
- === Hexx::Null
354
-
355
- The class implements the {Null object}[http://robots.thoughtbot.com/rails-refactoring-example-introduce-null-object] pattern. The object:
356
-
357
- * responds like +nil+ to <tt><=></tt>, +eq?+, +nil?+, +false?+, +true?+, +to_s+,
358
- +to_i+, +to_f+, +to_c+, +to_r+, +to_nil+
359
- * responds with +self+ to any other method call
360
-
361
- Providing {this problem}[http://devblog.avdi.org/2011/05/30/null-objects-and-falsiness/], use double negation in logical expressions:
362
-
363
- # Though:
364
- Hexx::Null && true # => true
365
-
366
- # But:
367
- !!Hexx::Null && true # => false
368
-
369
- == License
370
-
371
- The project is distributed under the {MIT LICENSE}[LICENSE.rdoc].