service_objects 0.1.0 → 1.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 (63) hide show
  1. checksums.yaml +4 -4
  2. data/.coveralls.yml +1 -0
  3. data/.metrics +1 -0
  4. data/.travis.yml +9 -1
  5. data/.yardopts +1 -1
  6. data/Gemfile +1 -1
  7. data/Guardfile +29 -8
  8. data/LICENSE +1 -1
  9. data/README.md +179 -342
  10. data/Rakefile +3 -3
  11. data/config/metrics/churn.yml +1 -1
  12. data/config/metrics/flay.yml +1 -1
  13. data/config/metrics/metric_fu.yml +1 -0
  14. data/config/metrics/rubocop.yml +4 -4
  15. data/config/metrics/simplecov.yml +1 -1
  16. data/lib/service_objects.rb +6 -9
  17. data/lib/service_objects/base.rb +190 -17
  18. data/lib/service_objects/listener.rb +21 -75
  19. data/lib/service_objects/message.rb +15 -96
  20. data/lib/service_objects/version.rb +1 -1
  21. data/service_objects.gemspec +11 -9
  22. data/spec/lib/base_spec.rb +247 -0
  23. data/spec/lib/listener_spec.rb +96 -0
  24. data/spec/lib/message_spec.rb +48 -0
  25. data/spec/spec_helper.rb +8 -6
  26. metadata +56 -93
  27. data/bin/service +0 -17
  28. data/config/metrics/pippi.yml +0 -3
  29. data/lib/service_objects/cli.rb +0 -117
  30. data/lib/service_objects/cli/locale.erb +0 -20
  31. data/lib/service_objects/cli/service.erb +0 -125
  32. data/lib/service_objects/cli/spec.erb +0 -87
  33. data/lib/service_objects/helpers.rb +0 -17
  34. data/lib/service_objects/helpers/dependable.rb +0 -63
  35. data/lib/service_objects/helpers/exceptions.rb +0 -64
  36. data/lib/service_objects/helpers/messages.rb +0 -95
  37. data/lib/service_objects/helpers/parameterized.rb +0 -85
  38. data/lib/service_objects/helpers/parameters.rb +0 -71
  39. data/lib/service_objects/helpers/validations.rb +0 -54
  40. data/lib/service_objects/invalid.rb +0 -55
  41. data/lib/service_objects/null.rb +0 -26
  42. data/lib/service_objects/parsers.rb +0 -13
  43. data/lib/service_objects/parsers/dependency.rb +0 -69
  44. data/lib/service_objects/parsers/notification.rb +0 -85
  45. data/lib/service_objects/rspec.rb +0 -75
  46. data/lib/service_objects/utils/normal_hash.rb +0 -34
  47. data/spec/tests/base_spec.rb +0 -43
  48. data/spec/tests/bin/service_spec.rb +0 -18
  49. data/spec/tests/cli_spec.rb +0 -179
  50. data/spec/tests/helpers/dependable_spec.rb +0 -77
  51. data/spec/tests/helpers/exceptions_spec.rb +0 -112
  52. data/spec/tests/helpers/messages_spec.rb +0 -64
  53. data/spec/tests/helpers/parameterized_spec.rb +0 -136
  54. data/spec/tests/helpers/parameters_spec.rb +0 -71
  55. data/spec/tests/helpers/validations_spec.rb +0 -60
  56. data/spec/tests/invalid_spec.rb +0 -69
  57. data/spec/tests/listener_spec.rb +0 -73
  58. data/spec/tests/message_spec.rb +0 -191
  59. data/spec/tests/null_spec.rb +0 -17
  60. data/spec/tests/parsers/dependency_spec.rb +0 -29
  61. data/spec/tests/parsers/notification_spec.rb +0 -84
  62. data/spec/tests/rspec_spec.rb +0 -86
  63. data/spec/tests/utils/normal_hash_spec.rb +0 -16
@@ -1,87 +0,0 @@
1
- # encoding: utf-8
2
- require "service_objects/rspec"
3
-
4
- describe <%= project.type %>::<%= service.type %> do
5
-
6
- # defines helpers and matcher for testing services:
7
- #
8
- # Helper arguments:
9
- # * params ({} by default)
10
- # * service
11
- # * listener - it is subscribed for the service
12
- #
13
- # Helper methods:
14
- # * service_double(*args) { |*args| ... }
15
- #
16
- # Matchers:
17
- # * correspond_to(hash)
18
- # * be_notified_on(notification, *args)
19
- #
20
- include ServiceObjects::RSpec
21
- <% dependencies.each do |item| -%>
22
-
23
- # describe "#<%= item.name %>" do
24
-
25
- # it "is set to <%= item.type %>" do
26
- # expect(subject.<%= item.name %>).to eq <%= item.type %>
27
- # end
28
-
29
- # it "is injectable" do
30
- # injection = double
31
- # expect { subject.<%= item.name %> = injection)
32
- # .to change { subject.<%= item.name %> }.to injection
33
- # end
34
-
35
- # end # describe #<%= item.name %>
36
- <% end -%>
37
-
38
- describe "#run" do
39
- <% dependencies.each do |item| -%>
40
-
41
- # shared_context "#<%= item.name %> publishes @todo" do |options|
42
-
43
- # before do
44
- # injection = service_double(@todo) { publish @todo }
45
- # inject :<%= item.name %>, with: options, constucts: injection
46
- # end
47
-
48
- # end # shared_context
49
- <% end -%>
50
- <% notifications.each do |item| -%>
51
-
52
- # shared_examples "@todo" do
53
-
54
- # it "[@todo]" do
55
- # expect { service.run }
56
- # .to change { @todo }
57
- # .from(@todo)
58
- # .to(@todo)
59
- # end
60
-
61
- # it "publishes :<%= item.name %>" do
62
- # expect(listener)
63
- # .to receive(:<%= item.name %>) do |<%= item.args.join(", ") %>|
64
- <% item.args.each do |arg| -%>
65
- # expect(<%= arg %>).to eq @todo
66
- <% end -%>
67
- # end
68
- # service.run
69
- # end
70
-
71
- # end
72
- <% end -%>
73
-
74
- # context "when @todo" do
75
-
76
- # before { params.merge! "@todo" => @todo }
77
- <% dependencies.each do |item| -%>
78
- # include_context "#<%= item.name %> publishes @todo", @todo
79
- <% end -%>
80
-
81
- # it_behaves_like "@todo"
82
-
83
- # end
84
-
85
- end
86
-
87
- end # describe <%= project.type %>::<%= service.type %>
@@ -1,17 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module ServiceObjects
4
-
5
- # Contains helper objecs for the base service
6
- module Helpers
7
-
8
- require_relative "helpers/messages"
9
- require_relative "helpers/validations"
10
- require_relative "helpers/exceptions"
11
- require_relative "helpers/dependable"
12
- require_relative "helpers/parameters"
13
- require_relative "helpers/parameterized"
14
-
15
- end # module Helpers
16
-
17
- end # module ServiceObjects
@@ -1,63 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module ServiceObjects
4
-
5
- module Helpers
6
-
7
- # Features for service dependencies declaration
8
- #
9
- # @note
10
- # A target class should be **extended** by the module
11
- module Dependable
12
-
13
- # Declares the dependency setter and getter
14
- #
15
- # @example
16
- # class AddFoo
17
- # extend ServiceObjects::Helpers::Dependable
18
- #
19
- # depends_on :get_item, default: GetItem
20
- # end
21
- #
22
- # service = AddFoo.new
23
- # service.get_item
24
- # # => GetItem
25
- #
26
- # # Depencency injection
27
- # service.get_item = FindItem
28
- # service.get_item
29
- # # => FindItem
30
- #
31
- # # Resetting to default
32
- # service.get_item = nil
33
- # service.get_item
34
- # # => GetItem
35
- #
36
- # @example Set to NULL Object by default
37
- # class AddFoo
38
- # extend ServiceObjects::Helpers::Dependable
39
- #
40
- # depends_on :get_item
41
- # end
42
- #
43
- # service = AddFoo.new
44
- # service.get_item
45
- # # => <ServiceObjects::NULL>
46
- #
47
- # @param [#to_sym] name
48
- # the name for the dependency
49
- # @param [BaseObject] default (ServiceObjects::NULL)
50
- # default implementation for the dependency
51
- #
52
- # @return [:depends_on]
53
- # the name of the method
54
- def depends_on(name, default: NULL)
55
- attr_writer name
56
- define_method(name) { instance_eval("@#{ name }") || default }
57
- end
58
-
59
- end # Dependable
60
-
61
- end # module Helpers
62
-
63
- end # module ServiceObjects
@@ -1,64 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module ServiceObjects
4
-
5
- module Helpers
6
-
7
- # Features for escaping from runtime errors
8
- #
9
- # @note
10
- # A target class should **include** the module
11
- module Exceptions
12
-
13
- # Re-raises standard errors as <tt>ServiceObjects::Invalid</tt>
14
- #
15
- # Mutates the current object by adding error messages
16
- #
17
- # @example
18
- # class MyClass
19
- # includes ServiceObjects::Helpers::Exceptions
20
- # end
21
- #
22
- # begin
23
- # MyClass.new.escape { fail StandardError.new "foo" }
24
- # rescue => err
25
- # puts err.class.name
26
- # puts messages
27
- # end
28
- #
29
- # # => ServiceObjects::Invalid
30
- # # => [<ServiceObject::Message type="error" text="foo" ...>]
31
- #
32
- # @yield the block
33
- #
34
- # @raise [ServiceObjects::Invalid]
35
- # if the block raises +StandardError+
36
- #
37
- # @return [Object] the value returned by the block
38
- def escape
39
- yield if block_given?
40
- rescue => error
41
- collect_messages_from error
42
- raise Invalid.new(self)
43
- end
44
-
45
- private
46
-
47
- # @!parse include ServiceObjects::Helpers::Messages
48
- def self.included(klass)
49
- klass.include Messages
50
- end
51
-
52
- def collect_messages_from(error)
53
- if error.is_a? Invalid
54
- messages.concat(error.messages) if error.object != self
55
- else
56
- add_message type: "error", text: error.message
57
- end
58
- end
59
-
60
- end # module Exceptions
61
-
62
- end # module Helpers
63
-
64
- end # module ServiceObjects
@@ -1,95 +0,0 @@
1
- # encoding: utf-8
2
- require "extlib"
3
-
4
- module ServiceObjects
5
-
6
- module Helpers
7
-
8
- # Features for collecting service messages
9
- #
10
- # @note
11
- # A target class should **include** the module
12
- module Messages
13
-
14
- # Translates the text in the current scope with given options
15
- #
16
- # The method uses I18n.t library method.
17
- #
18
- # @example Returns a translation for symbolic argument
19
- # class Test
20
- # include ServiceObjects::Helpers::Messages
21
- # end
22
- #
23
- # MyClass.new.translate :item
24
- # # => translation not found: en.activemodel.messages.models.test.item
25
- #
26
- # @example Converts non-symbolic argument to a string.
27
- # class Test
28
- # include ServiceObjects::Helpers::Messages
29
- # end
30
- #
31
- # MyClass.new.translate 1
32
- # # => "1"
33
- #
34
- # @param [#to_s] text
35
- # @param [Hash] options ({})
36
- #
37
- # @return [String]
38
- def translate(text, options = {})
39
- return text.to_s unless text.is_a? Symbol
40
- I18n.t text, Utils::NormalHash.from(options).merge(scope: __scope__)
41
- end
42
-
43
- # A list of object messages
44
- #
45
- # @return [Array<ServiceObjects::Message>]
46
- def messages
47
- @messages ||= []
48
- end
49
-
50
- # Translates the text and adds a new message to the list of {#messages}
51
- #
52
- # @example
53
- # class MyClass
54
- # include ServiceObjects::Helpers::Messages
55
- # end
56
- #
57
- # object = MyClass.new
58
- # object.add_message type: "foo", text: "bar", priority: 2.5
59
- # object.messages
60
- # # => [<ServiceObjects::Message type="foo" text="bar" priority=2.5>]
61
- #
62
- # @param [Hash] options
63
- # the list of options for the message and its translation
64
- #
65
- # @option options [#to_s] :text
66
- # the text of a new message to be translated via {#translate} method
67
- # @option options [#to_s] :type
68
- # the type of a new message
69
- # @option options [#to_f] :priority
70
- # optional priority fo a new message
71
- #
72
- # @return [Array<ServiceObjects::Message>] The updated {#messages}
73
- def add_message(options)
74
- params = Utils::NormalHash.from(options)
75
- type = params.delete :type
76
- priority = params.delete :priority
77
- text = translate params.delete(:text), params
78
- messages << Message.new(text: text, type: type, priority: priority)
79
- end
80
-
81
- private
82
-
83
- def __scope__
84
- @__scope__ ||= [:activemodel, :messages, :models, __class_name__.to_sym]
85
- end
86
-
87
- def __class_name__
88
- self.class.name.split("::").map(&:snake_case).join("/")
89
- end
90
-
91
- end # module Messages
92
-
93
- end # module Helpers
94
-
95
- end # module Services
@@ -1,85 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module ServiceObjects
4
-
5
- module Helpers
6
-
7
- # Features for service parameters declaration
8
- #
9
- # @note
10
- # A target class should be **extended** by the module
11
- module Parameterized
12
-
13
- # Whitelists {.new} options assigned to params
14
- #
15
- # Mutates the current class by adding the corresponding attribute
16
- # for every parameter.
17
- #
18
- # @example Whitelists options
19
- # class AddFoo
20
- # extend ServiceObjects::Helpers::Parameterized
21
- #
22
- # allows_params :foo
23
- # end
24
- #
25
- # service = AddFoo.new foo: "foo", bar: "baz"
26
- # service.params # => { foo: "foo" }
27
- #
28
- # @example Adds attributes as aliases to corresponding params
29
- # class AddFoo
30
- # extend ServiceObjects::Helpers::Parameterized
31
- #
32
- # allows_params :foo
33
- # end
34
- #
35
- # service = AddFoo.new foo: "foo"
36
- # service.foo # => "foo"
37
- #
38
- # service.params[:foo] = "bar"
39
- # service.foo # => "bar"
40
- #
41
- # service.foo = "baz"
42
- # service.foo # => "baz"
43
- # service.params[:foo] # => "baz"
44
- #
45
- # @param [Array<#to_sym>] list
46
- #
47
- # @return [Array<Symbol>]
48
- # the list of arguments
49
- def allows_params(*list)
50
- @whitelist = list.flatten.map(&:to_sym).freeze
51
- __attr_params__
52
-
53
- whitelist
54
- end
55
-
56
- private
57
-
58
- # @!parse include ServiceObjects::Helpers::Parameters
59
- def self.extended(klass)
60
- klass.include Parameters
61
- super
62
- end
63
-
64
- def __attr_params__
65
- whitelist.each(&method(:__attr_param_accessor__))
66
- end
67
-
68
- def __attr_param_accessor__(name)
69
- __attr_param_reader__ name
70
- __attr_param_writer__ name
71
- end
72
-
73
- def __attr_param_reader__(name)
74
- define_method(name) { params[name] }
75
- end
76
-
77
- def __attr_param_writer__(name)
78
- define_method("#{ name }=") { |value| params[name] = value }
79
- end
80
-
81
- end # module Parameters
82
-
83
- end # module Helpers
84
-
85
- end # module ServiceObjects
@@ -1,71 +0,0 @@
1
- # encoding: utf-8
2
-
3
- module ServiceObjects
4
-
5
- module Helpers
6
-
7
- # Features for whitelisting service options
8
- #
9
- # @note
10
- # A target class should **include** the module
11
- module Parameters
12
-
13
- # @!scope class
14
- # @!attribute [r] whitelist
15
- # Returns the list of allowed parameters
16
- #
17
- # @return [Array<Symbol>]
18
-
19
- # @!attribute [r] params
20
- # Service object parameters
21
- #
22
- # @return [Hash]
23
- attr_reader :params
24
-
25
- # Service object initializer
26
- #
27
- # @example Normalizing options
28
- # class AddFoo
29
- # include ServiceObjects::Helpers::Parameters
30
- #
31
- # @whitelist = [:foo]
32
- # end
33
- #
34
- # service = AddFoo.new("foo" => { "bar" => "baz" })
35
- # service.params # => { foo: { bar: "baz" } }
36
- #
37
- # @example Whitelisting options
38
- # class AddFoo
39
- # include ServiceObjects::Helpers::Parameters
40
- #
41
- # @whitelist = [:foo]
42
- # end
43
- #
44
- # service = AddFoo.new(foo: "bar", bar: "baz")
45
- # service.params # => { foo: "bar" }
46
- #
47
- # @param [Hash] options
48
- #
49
- # @return [undefined]
50
- def initialize(options = {})
51
- @params = Utils::NormalHash.from(options).slice(*__whitelist__)
52
- end
53
-
54
- private
55
-
56
- def self.included(klass)
57
- klass
58
- .singleton_class
59
- .send(:define_method, :whitelist) { @whitelist ||= [] }
60
- super
61
- end
62
-
63
- def __whitelist__
64
- @whitelist ||= self.class.send :whitelist
65
- end
66
-
67
- end # module Parameters
68
-
69
- end # module Helpers
70
-
71
- end # module ServiceObjects