service_objects 0.1.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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