hexx 6.0.3 → 7.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 (40) hide show
  1. checksums.yaml +4 -4
  2. data/.rubocop.yml +3 -0
  3. data/README.rdoc +63 -48
  4. data/lib/hexx.rb +1 -0
  5. data/lib/hexx/coercible.rb +2 -2
  6. data/lib/hexx/configurable.rb +1 -1
  7. data/lib/hexx/{helpers → creators}/base.rb +11 -15
  8. data/lib/hexx/{helpers → creators}/coercion.rb +8 -8
  9. data/lib/hexx/{helpers → creators}/dependency.rb +8 -8
  10. data/lib/hexx/{helpers → creators}/module_dependency.rb +2 -2
  11. data/lib/hexx/{helpers → creators}/parameter.rb +1 -1
  12. data/lib/hexx/dependable.rb +1 -1
  13. data/lib/hexx/helpers/exceptions.rb +53 -0
  14. data/lib/hexx/helpers/messages.rb +28 -0
  15. data/lib/hexx/helpers/parameters.rb +47 -0
  16. data/lib/hexx/helpers/validations.rb +21 -0
  17. data/lib/hexx/message.rb +79 -0
  18. data/lib/hexx/null.rb +0 -4
  19. data/lib/hexx/service.rb +259 -208
  20. data/lib/hexx/service_invalid.rb +73 -0
  21. data/lib/hexx/version.rb +1 -1
  22. data/spec/hexx/helpers/exceptions_spec.rb +96 -0
  23. data/spec/hexx/helpers/messages_spec.rb +56 -0
  24. data/spec/hexx/helpers/parameters_spec.rb +96 -0
  25. data/spec/hexx/helpers/validations_spec.rb +32 -0
  26. data/spec/hexx/message_spec.rb +83 -0
  27. data/spec/hexx/service_invalid_spec.rb +46 -0
  28. data/spec/hexx/service_spec.rb +41 -242
  29. data/spec/spec_helper.rb +1 -1
  30. data/spec/{initializers → support/initializers}/focus.rb +0 -0
  31. data/spec/{initializers → support/initializers}/garbage_collection.rb +0 -0
  32. data/spec/{initializers → support/initializers}/i18n.rb +0 -0
  33. data/spec/{initializers → support/initializers}/random_order.rb +0 -0
  34. data/spec/{initializers → support/initializers}/rspec.rb +0 -0
  35. data/spec/support/matchers/methods.rb +11 -0
  36. metadata +37 -23
  37. data/lib/hexx/service/invalid.rb +0 -76
  38. data/lib/hexx/service/message.rb +0 -81
  39. data/spec/hexx/service/invalid_spec.rb +0 -52
  40. data/spec/hexx/service/message_spec.rb +0 -85
@@ -0,0 +1,73 @@
1
+ require_relative "message"
2
+
3
+ module Hexx
4
+
5
+ # The exception to be risen by invalid services.
6
+ #
7
+ # @example
8
+ # service GetItem < Hexx::Service
9
+ # allow_params :uuid
10
+ # validates :uuid, presence: true
11
+ # def run
12
+ # validate!
13
+ # end
14
+ # end
15
+ #
16
+ # service = GetItem.new
17
+ # service.run # => fails with the {Hexx::ServiceInvalid}.
18
+ class ServiceInvalid < ::RuntimeError
19
+
20
+ # @!attribute [r] service
21
+ # @return [Hexx::Service] The invalid service object.
22
+ attr_reader :service
23
+
24
+ # @!scope class
25
+ # @!method new(service)
26
+ # Initializes the exception.
27
+ #
28
+ # @example
29
+ # fail Hexx::ServiceInvalid.new service
30
+ #
31
+ # @param [Hexx::Service] service The invalid service.
32
+ # @raise [ArgumentError] if the argument is not a service object.
33
+ # @return [Hexx::ServiceInvalid] The exception.
34
+
35
+ # @api hide
36
+ def initialize(service)
37
+ @service = service
38
+ end
39
+
40
+ # @!attribute [r] message
41
+ # Returns a default text message for the exception.
42
+ #
43
+ # @example
44
+ # error = Hexx::ServiceInvalid.new service
45
+ # error.message # => "Service invalid: #<Hexx::Service... >"
46
+ #
47
+ # @return [String] The message.
48
+ def message
49
+ "Service invalid: #{ service.inspect }"
50
+ end
51
+
52
+ # @!attribute [r] messages
53
+ # Returns a list of error messages from the service.
54
+ #
55
+ # @example
56
+ # service.errors.add :base, "some error"
57
+ #
58
+ # error = Hexx::ServiceInvalid.new service
59
+ # error.messages
60
+ # # => [#<Hexx::Message @type="error" @text="some error" >]
61
+ #
62
+ # @return [Array<Hexx::Message>] The list of error messages.
63
+ def messages
64
+ errors.map { |text| Message.new type: "error", text: text }
65
+ end
66
+
67
+ private
68
+
69
+ def errors
70
+ service.errors.messages.values.flatten
71
+ end
72
+ end
73
+ end
@@ -2,5 +2,5 @@
2
2
  module Hexx
3
3
 
4
4
  # Current release.
5
- VERSION = "6.0.3"
5
+ VERSION = "7.0.0"
6
6
  end
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ module Hexx
5
+ describe Helpers::Exceptions do
6
+
7
+ before { class Test; include Helpers::Exceptions; end }
8
+ after { Hexx.send :remove_const, :Test }
9
+
10
+ let(:service_invalid) { Hexx::ServiceInvalid }
11
+ let(:message) { Hexx::Message.new type: "error", text: "text" }
12
+ let(:described_class) { Test }
13
+ subject { described_class.new }
14
+
15
+ it "includes Messages" do
16
+ expect(described_class).to include Helpers::Messages
17
+ end
18
+
19
+ describe ".raises" do
20
+
21
+ it "declares the specific StandardError exception(s)" do
22
+ described_class.send :raises, :TestException
23
+ exception = described_class.const_get :TestException
24
+ expect(exception.new).to be_kind_of StandardError
25
+ end
26
+
27
+ it "accepts a list of values" do
28
+ expect { described_class.send :raises, :One, :Two }.not_to raise_error
29
+ expect(described_class.const_defined? :One).to be_truthy
30
+ expect(described_class.const_defined? :Two).to be_truthy
31
+ end
32
+
33
+ it "accepts an array of values" do
34
+ expect { described_class.send :raises, %w(One Two) }.not_to raise_error
35
+ expect(described_class.const_defined? :One).to be_truthy
36
+ expect(described_class.const_defined? :Two).to be_truthy
37
+ end
38
+
39
+ it "requires value" do
40
+ expect { described_class.send :raises }.to raise_error ArgumentError
41
+ end
42
+
43
+ it "fails if non-string or non-symbol value given" do
44
+ expect { described_class.send :raises, 1 }.to raise_error TypeError
45
+ end
46
+ end
47
+
48
+ describe "#on_error" do
49
+
50
+ it "fails with ServiceInvalid" do
51
+ expect { subject.on_error [message] }.to raise_error service_invalid
52
+ end
53
+
54
+ it "adds errors to the service" do
55
+ begin; subject.on_error [message]; rescue; end
56
+ expect(subject.errors.messages).to eq(base: ["text"])
57
+ end
58
+ end
59
+
60
+ describe "#escape" do
61
+
62
+ it "yields a block" do
63
+ value = "Hello!"
64
+ result = subject.escape { value }
65
+ expect(result).to eq value
66
+ end
67
+
68
+ context "when a block raises ServiceInvalid error" do
69
+
70
+ let!(:exception) { service_invalid.new(subject) }
71
+
72
+ it "re-raises the exception" do
73
+ expect { subject.escape { fail exception } }
74
+ .to raise_error { exception }
75
+ end
76
+ end
77
+
78
+ context "when a block raises StandardError" do
79
+
80
+ let(:run) { subject.escape { fail "text" } }
81
+
82
+ it "re-raises the ServiceInvalid" do
83
+ expect { run }.to raise_error service_invalid
84
+ end
85
+
86
+ it "adds error to the messages" do
87
+ begin
88
+ run
89
+ rescue => err
90
+ expect(err.messages).to contain_exactly message
91
+ end
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,56 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ module Hexx
5
+ describe Helpers::Messages do
6
+
7
+ before { class Test; include Helpers::Messages; end }
8
+ subject { Test.new }
9
+ after { Hexx.send :remove_const, :Test }
10
+
11
+ describe "#t" do
12
+
13
+ let(:scope) { %w(activemodel messages models hexx/test) }
14
+ let(:traslation) { I18n.t(:text, scope: scope, name: "name") }
15
+
16
+ it "translates symbols in the service scope" do
17
+ expect(subject.t(:text, name: "name")).to eq traslation
18
+ end
19
+
20
+ it "doesn't translate the string" do
21
+ expect(subject.t("text")).to eq "text"
22
+ end
23
+ end
24
+
25
+ describe "#messages" do
26
+
27
+ it "returns an array" do
28
+ expect(subject.messages).to be_kind_of Array
29
+ end
30
+ end
31
+
32
+ describe "#messages=" do
33
+
34
+ it "sets #messages" do
35
+ expect { subject.messages = ["text"] }
36
+ .to change { subject.messages }.to ["text"]
37
+ end
38
+ end
39
+
40
+ describe "#add_message" do
41
+
42
+ before { subject.add_message :info, :text }
43
+ let(:message) { subject.messages.first }
44
+
45
+ it "adds a new message" do
46
+ expect(message).to be_kind_of Hexx::Message
47
+ expect(message.type).to eq "info"
48
+ end
49
+
50
+ it "translates a symbol" do
51
+ translation = subject.t :text
52
+ expect(message.text).to eq translation
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,96 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ module Hexx
5
+ describe Helpers::Parameters do
6
+
7
+ before { class Test; include Helpers::Parameters; end }
8
+ let(:described_class) { Test }
9
+ after { Hexx.send :remove_const, :Test }
10
+
11
+ describe "#params" do
12
+
13
+ subject { described_class.new }
14
+
15
+ it "is defined" do
16
+ expect(subject).to respond_to :params
17
+ end
18
+
19
+ it "has no setter" do
20
+ expect(subject).not_to respond_to :params=
21
+ end
22
+ end
23
+
24
+ describe ".new" do
25
+
26
+ it "accepts parameters" do
27
+ expect { described_class.new name: "name" }.not_to raise_error
28
+ end
29
+
30
+ it "doesn't require parameters" do
31
+ expect { described_class.new }.not_to raise_error
32
+ end
33
+ end
34
+
35
+ describe ".allow_params" do
36
+
37
+ it "is defined" do
38
+ expect(described_class).to respond_to(:allow_params)
39
+ end
40
+
41
+ it "accepts one argument" do
42
+ expect { described_class.send :allow_params, :name }
43
+ .not_to raise_error
44
+ end
45
+
46
+ it "accepts a list of arguments" do
47
+ expect { described_class.send :allow_params, :name, :type }
48
+ .not_to raise_error
49
+ end
50
+
51
+ it "accepts an array of arguments" do
52
+ expect { described_class.send :allow_params, %w(name type) }
53
+ .not_to raise_error
54
+ end
55
+
56
+ it "requires strings or symbols" do
57
+ expect { described_class.send :allow_params, 1 }
58
+ .to raise_error SyntaxError
59
+ end
60
+
61
+ it "requires non-empty values" do
62
+ expect { described_class.send :allow_params, "" }
63
+ .to raise_error ArgumentError
64
+ end
65
+
66
+ it "requires values" do
67
+ expect { described_class.send :allow_params }
68
+ .to raise_error ArgumentError
69
+ end
70
+
71
+ context "with valid argument" do
72
+
73
+ before { described_class.send :allow_params, :name }
74
+ subject { described_class.new name: "name" }
75
+
76
+ it "allows initialization of the parameter" do
77
+ expect(subject.params).to eq("name" => "name")
78
+ end
79
+
80
+ it "defines private getter for the parameter" do
81
+ expect(described_class.private_instance_methods)
82
+ .to be_include :name
83
+ expect { subject.params["name"] = "new" }
84
+ .to change { subject.send :name }.to "new"
85
+ end
86
+
87
+ it "defines private setter for the parameter" do
88
+ expect(described_class.private_instance_methods)
89
+ .to be_include :name=
90
+ expect { subject.send :name=, "new" }
91
+ .to change { subject.params["name"] }.to "new"
92
+ end
93
+ end
94
+ end
95
+ end
96
+ end
@@ -0,0 +1,32 @@
1
+ # encoding: utf-8
2
+ require "spec_helper"
3
+
4
+ module Hexx
5
+ describe Helpers::Validations do
6
+
7
+ before { class Test; include Helpers::Validations; end }
8
+ after { Hexx.send :remove_const, :Test }
9
+
10
+ let(:service_invalid) { Hexx::ServiceInvalid }
11
+ let(:message) { Hexx::Message.new type: "error", text: "text" }
12
+ let(:described_class) { Test }
13
+ subject { described_class.new }
14
+
15
+ it "includes ActiveModel::Validations" do
16
+ expect(described_class).to include ActiveModel::Validations
17
+ end
18
+
19
+ describe "#validate!" do
20
+
21
+ it "passes when service is valid" do
22
+ allow(subject).to receive(:valud?).and_return true
23
+ expect { subject.validate! }.not_to raise_error
24
+ end
25
+
26
+ it "fails when service is invalid" do
27
+ allow(subject).to receive(:valid?).and_return false
28
+ expect { subject.validate! }.to raise_error service_invalid
29
+ end
30
+ end
31
+ end
32
+ end
@@ -0,0 +1,83 @@
1
+ require "spec_helper"
2
+
3
+ module Hexx
4
+ describe Message do
5
+
6
+ describe ".new" do
7
+
8
+ subject { Message }
9
+
10
+ it "requires type" do
11
+ expect { subject.new text: "" }.to raise_error
12
+ end
13
+
14
+ it "requires text" do
15
+ expect { subject.new type: "" }.to raise_error
16
+ end
17
+ end
18
+
19
+ describe "#type" do
20
+
21
+ subject { Message.new type: "info", text: "text" }
22
+
23
+ it "returns message type" do
24
+ expect(subject.type).to eq "info"
25
+ end
26
+ end
27
+
28
+ describe "#text" do
29
+
30
+ subject { Message.new type: "info", text: "text" }
31
+
32
+ it "returns message text" do
33
+ expect(subject.text).to eq "text"
34
+ end
35
+ end
36
+
37
+ describe "#==" do
38
+
39
+ let!(:params) { { type: "info", text: "text" } }
40
+
41
+ it "returns true if type and text of two messages are the same" do
42
+ expect(Message.new params).to eq(Message.new params)
43
+ end
44
+
45
+ it "returns false if types of two messages are different" do
46
+ expect(Message.new params)
47
+ .not_to eq(Message.new params.merge(type: "error"))
48
+ end
49
+
50
+ it "returns false if texts of two messages are different" do
51
+ expect(Message.new params)
52
+ .not_to eq(Message.new params.merge(text: "another"))
53
+ end
54
+
55
+ it "returns false when a message compares to non-message" do
56
+ expect(Message.new params).not_to eq("text")
57
+ end
58
+ end
59
+
60
+ describe "#<=>" do
61
+
62
+ let!(:aa) { Message.new type: "a", text: "a" }
63
+ let!(:ab) { Message.new type: "a", text: "b" }
64
+ let!(:ba) { Message.new type: "b", text: "a" }
65
+
66
+ it "orders messages by type" do
67
+ expect(aa < ba).to be_truthy
68
+ end
69
+
70
+ it "orders messages by text" do
71
+ expect(aa < ab).to be_truthy
72
+ end
73
+
74
+ it "orders messages first by type" do
75
+ expect(ab < ba).to be_truthy
76
+ end
77
+
78
+ it "fails when compared with non-message" do
79
+ expect { ab < "" }.to raise_error
80
+ end
81
+ end
82
+ end
83
+ end