hexx 5.4.0 → 6.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.
- checksums.yaml +4 -4
- data/README.rdoc +211 -81
- data/Rakefile +1 -2
- data/lib/hexx.rb +1 -0
- data/lib/hexx/{models.rb → coercible.rb} +10 -12
- data/lib/hexx/configurable.rb +101 -0
- data/lib/hexx/dependable.rb +51 -0
- data/lib/hexx/helpers/base.rb +111 -0
- data/lib/hexx/helpers/coersion.rb +82 -0
- data/lib/hexx/helpers/dependency.rb +87 -0
- data/lib/hexx/helpers/module_dependency.rb +57 -0
- data/lib/hexx/helpers/parameter.rb +40 -0
- data/lib/hexx/service.rb +96 -51
- data/lib/hexx/service/with_callbacks.rb +6 -7
- data/lib/hexx/version.rb +1 -1
- data/spec/hexx/coercible_spec.rb +56 -0
- data/spec/hexx/{dependencies_spec.rb → configurable_spec.rb} +7 -20
- data/spec/hexx/dependable_spec.rb +125 -0
- data/spec/hexx/service_spec.rb +24 -16
- metadata +16 -10
- data/lib/hexx/dependencies.rb +0 -182
- data/lib/hexx/models/base_coercer.rb +0 -44
- data/lib/hexx/service/parameters.rb +0 -81
- data/spec/hexx/models_spec.rb +0 -40
data/lib/hexx/dependencies.rb
DELETED
@@ -1,182 +0,0 @@
|
|
1
|
-
# encoding: utf-8
|
2
|
-
|
3
|
-
module Hexx
|
4
|
-
|
5
|
-
# Contains methods to declare and inject module dependencies.
|
6
|
-
#
|
7
|
-
# Allows to provide DJ framework for the gem.
|
8
|
-
#
|
9
|
-
# @example
|
10
|
-
# # Declare the dependencies for the gem root module
|
11
|
-
#
|
12
|
-
# # lib/my_gem.rb
|
13
|
-
# module MyGem
|
14
|
-
# extend Hexx::Dependencies
|
15
|
-
# self.depends_on :get_item, :add_item, :delete_item
|
16
|
-
# end
|
17
|
-
#
|
18
|
-
# # Inject dependencies (as a constant or its name)
|
19
|
-
#
|
20
|
-
# # config/my_gem.rb
|
21
|
-
# MyGem.configure do |config|
|
22
|
-
# config.get_item = AnotherGem::Services::Get
|
23
|
-
# config.add_item = "AnotherGem::Services::Add"
|
24
|
-
# end
|
25
|
-
#
|
26
|
-
# # Use dependency in the module code (models, services, etc.)
|
27
|
-
# # When the dependency hasn't been set, fails with +NotImplementedError+
|
28
|
-
#
|
29
|
-
# MyGem.get_item # => AnotherGem::Services::Get
|
30
|
-
# MyGem.add_item # => AnotherGem::Services::Add
|
31
|
-
# MyGem.delete_item # raises #<NotImplementedError ... >
|
32
|
-
module Dependencies
|
33
|
-
|
34
|
-
# Yields a block and gives it self
|
35
|
-
#
|
36
|
-
# @example
|
37
|
-
# module MyGem
|
38
|
-
# extend Hexx::Dependencies
|
39
|
-
# end
|
40
|
-
#
|
41
|
-
# MyGem.configure do |config|
|
42
|
-
# c # => MyGem
|
43
|
-
# end
|
44
|
-
#
|
45
|
-
# @yield The block.
|
46
|
-
# @yieldparam [Dependencies] +self+.
|
47
|
-
def configure
|
48
|
-
yield(self)
|
49
|
-
end
|
50
|
-
|
51
|
-
# Declares dependency getter and setter.
|
52
|
-
#
|
53
|
-
# The getter constants, strings and symbols. The setter constantize the
|
54
|
-
# assigned value.
|
55
|
-
#
|
56
|
-
# This allows setting dependency before definition of a corresponding
|
57
|
-
# constant.
|
58
|
-
#
|
59
|
-
# @example
|
60
|
-
# module MyGem
|
61
|
-
# extend Hexx::Dependencies
|
62
|
-
# self.depends_on :some_class
|
63
|
-
# end
|
64
|
-
#
|
65
|
-
# MyGem.some_class = String
|
66
|
-
# # => "String"
|
67
|
-
# MyGem.some_class # => String
|
68
|
-
#
|
69
|
-
# MyGem.some_class = "String"
|
70
|
-
# # => "String"
|
71
|
-
# MyGem.some_class # => String
|
72
|
-
#
|
73
|
-
# MyGem.some_class = :String
|
74
|
-
# # => "String"
|
75
|
-
# MyGem.some_class # => String
|
76
|
-
#
|
77
|
-
# @example Dependencies can be set as a plain list of names
|
78
|
-
# module MyGem
|
79
|
-
# extend Hexx::Dependencies
|
80
|
-
# self.depends_on :some_class, "another_class"
|
81
|
-
# end
|
82
|
-
#
|
83
|
-
# @example Dependencies can be set as an array of names
|
84
|
-
# module MyGem
|
85
|
-
# extend Hexx::Dependencies
|
86
|
-
# self.depends_on %w(some_class another_class)
|
87
|
-
# end
|
88
|
-
#
|
89
|
-
# @param [Array<String, Symbol>] names The list of names for dependencies.
|
90
|
-
def depends_on(*names, default: nil)
|
91
|
-
names.flatten.each do |name|
|
92
|
-
DependencyName.new(name).validate
|
93
|
-
add_dependency_setter name
|
94
|
-
add_dependency_getter name, default
|
95
|
-
end
|
96
|
-
end
|
97
|
-
|
98
|
-
private
|
99
|
-
|
100
|
-
# @api hide
|
101
|
-
# Checks the name of the dependency.
|
102
|
-
class DependencyName < Struct.new(:name)
|
103
|
-
|
104
|
-
# @api hide
|
105
|
-
# Runs validations and fails in case of any error.
|
106
|
-
# @raise [TypeError] if the name has a wrong type.
|
107
|
-
# @raise [ArgumentError] if the name is blank.
|
108
|
-
def validate
|
109
|
-
check_type
|
110
|
-
check_value
|
111
|
-
end
|
112
|
-
|
113
|
-
private
|
114
|
-
|
115
|
-
def check_type
|
116
|
-
return if [String, Symbol].include? name.class
|
117
|
-
fail TypeError.new "#{ name.inspect } is neither a string nor symbol."
|
118
|
-
end
|
119
|
-
|
120
|
-
def check_value
|
121
|
-
return unless name.to_s == ""
|
122
|
-
fail ArgumentError.new "The dependency name should not be blank."
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
# @api hide
|
127
|
-
# Checks the value of the dependency.
|
128
|
-
class Dependency < Struct.new(:name, :value)
|
129
|
-
|
130
|
-
# @api hide
|
131
|
-
# Runs validations and fails in case of any error.
|
132
|
-
# @raise [TypeError] if the value has a wrong type.
|
133
|
-
# @raise [ArgumentError] if the value name is blank.
|
134
|
-
def validate
|
135
|
-
check_type
|
136
|
-
check_value
|
137
|
-
end
|
138
|
-
|
139
|
-
private
|
140
|
-
|
141
|
-
def check_type
|
142
|
-
return if value.is_a? String
|
143
|
-
return if value.is_a? Symbol
|
144
|
-
return if value.is_a? Module
|
145
|
-
fail TypeError.new "#{ inspect } is not a string, symbol or module."
|
146
|
-
end
|
147
|
-
|
148
|
-
def check_value
|
149
|
-
return unless value.to_s == ""
|
150
|
-
fail ArgumentError.new "The dependency #{ name } should not be blank."
|
151
|
-
end
|
152
|
-
|
153
|
-
def inspect
|
154
|
-
value.inspect
|
155
|
-
end
|
156
|
-
end
|
157
|
-
|
158
|
-
def add_dependency_setter(name)
|
159
|
-
instance_eval "
|
160
|
-
def #{ name }=(value);
|
161
|
-
Dependency.new(:#{ name }, value).validate;
|
162
|
-
@#{ name }= value.to_s;
|
163
|
-
end"
|
164
|
-
end
|
165
|
-
|
166
|
-
def add_dependency_getter(name, default)
|
167
|
-
instance_eval "
|
168
|
-
def #{ name };
|
169
|
-
value = @#{ default_name name, default };
|
170
|
-
constantize(value);
|
171
|
-
end"
|
172
|
-
end
|
173
|
-
|
174
|
-
def constantize(value)
|
175
|
-
value.is_a?(Module) ? value : Kernel.const_get(value.to_s)
|
176
|
-
end
|
177
|
-
|
178
|
-
def default_name(name, default)
|
179
|
-
[name, default].compact.map(&:to_s).join " || "
|
180
|
-
end
|
181
|
-
end
|
182
|
-
end
|
@@ -1,44 +0,0 @@
|
|
1
|
-
module Hexx
|
2
|
-
module Models
|
3
|
-
|
4
|
-
# @api hide
|
5
|
-
# Coerces class attribute getter and setter with given type.
|
6
|
-
class BaseCoercer < Struct.new(:klass, :name, :type)
|
7
|
-
|
8
|
-
# Coerces class attribute's getter and setter.
|
9
|
-
#
|
10
|
-
# @example
|
11
|
-
# BaseCoercer.new SomeModel, :name, StrippedString
|
12
|
-
# BaseCoercer.coerce
|
13
|
-
#
|
14
|
-
# model = SomeModel.new name: "string"
|
15
|
-
# model.name.class # => StrippedString
|
16
|
-
def coerce
|
17
|
-
coerce_setter
|
18
|
-
coerce_getter
|
19
|
-
end
|
20
|
-
|
21
|
-
private
|
22
|
-
|
23
|
-
def coerce_setter
|
24
|
-
klass.class_eval(
|
25
|
-
"def #{ name };
|
26
|
-
#{ type_name }.new(@#{ name });
|
27
|
-
end"
|
28
|
-
)
|
29
|
-
end
|
30
|
-
|
31
|
-
def coerce_getter
|
32
|
-
klass.class_eval(
|
33
|
-
"def #{ name }=(value);
|
34
|
-
@#{ name } = #{ type_name }.new(value);
|
35
|
-
end"
|
36
|
-
)
|
37
|
-
end
|
38
|
-
|
39
|
-
def type_name
|
40
|
-
@type_name ||= type.name
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
44
|
-
end
|
@@ -1,81 +0,0 @@
|
|
1
|
-
module Hexx
|
2
|
-
class Service
|
3
|
-
|
4
|
-
# @api hide
|
5
|
-
# Contains methods to declare parameters and set their values.
|
6
|
-
module Parameters
|
7
|
-
extend ActiveSupport::Concern
|
8
|
-
|
9
|
-
# Methods to declare and allow services params.
|
10
|
-
module ClassMethods
|
11
|
-
|
12
|
-
# @!attribute [r] params
|
13
|
-
# The list of allowed instance parameters. The parameters are added
|
14
|
-
# to the list by the {.allow_params} method.
|
15
|
-
#
|
16
|
-
# @example
|
17
|
-
# class Service
|
18
|
-
# include Parameters
|
19
|
-
# allow_params :name
|
20
|
-
# end
|
21
|
-
#
|
22
|
-
# Service.params # => "name"
|
23
|
-
#
|
24
|
-
# @return [Array<String>] The list of allowed instance parameters.
|
25
|
-
def params
|
26
|
-
@params ||= []
|
27
|
-
end
|
28
|
-
|
29
|
-
private
|
30
|
-
|
31
|
-
# Sets a list of allowed parameters for the class constructor and
|
32
|
-
# defines the corresponding instance attributes.
|
33
|
-
#
|
34
|
-
# @example (see Hexx::Service::Parameters.params)
|
35
|
-
# @param [Array<Symbol, String>] keys The list of allowed parameters.
|
36
|
-
def allow_params(*keys)
|
37
|
-
@params = keys.map(&:to_s)
|
38
|
-
define_individual_params
|
39
|
-
end
|
40
|
-
|
41
|
-
def define_individual_params
|
42
|
-
params.each do |name|
|
43
|
-
add_getter(name)
|
44
|
-
add_setter(name)
|
45
|
-
end
|
46
|
-
end
|
47
|
-
|
48
|
-
def add_getter(name)
|
49
|
-
define_method(name) { params[name] }
|
50
|
-
end
|
51
|
-
|
52
|
-
def add_setter(name)
|
53
|
-
define_method("#{name}=") { |value| params[name] = value }
|
54
|
-
end
|
55
|
-
end
|
56
|
-
|
57
|
-
# @!method new(params)
|
58
|
-
# Constructs a service object with a hash of parameters.
|
59
|
-
#
|
60
|
-
# @example
|
61
|
-
# Service.new name: "name"
|
62
|
-
#
|
63
|
-
# @param [Hash] params ({}) The parameters of the service object.
|
64
|
-
def initialize(params = {})
|
65
|
-
extract_params_from params
|
66
|
-
end
|
67
|
-
|
68
|
-
# @!attribute [r] params
|
69
|
-
# The parameters of the service objects. The parameters are set on
|
70
|
-
# the object initialization, then are stringified and whitelisted.
|
71
|
-
# @return [Hash] the service object parameters.
|
72
|
-
attr_reader :params
|
73
|
-
|
74
|
-
private
|
75
|
-
|
76
|
-
def extract_params_from(hash)
|
77
|
-
@params = hash.stringify_keys.slice(*(self.class.params))
|
78
|
-
end
|
79
|
-
end
|
80
|
-
end
|
81
|
-
end
|
data/spec/hexx/models_spec.rb
DELETED
@@ -1,40 +0,0 @@
|
|
1
|
-
require "spec_helper"
|
2
|
-
|
3
|
-
module Hexx
|
4
|
-
describe Models do
|
5
|
-
|
6
|
-
# ==========================================================================
|
7
|
-
# Prepare environment
|
8
|
-
# ==========================================================================
|
9
|
-
|
10
|
-
around do |example|
|
11
|
-
class TestModel; extend Models; end
|
12
|
-
class TestAttribute; end
|
13
|
-
example.run
|
14
|
-
Hexx.send :remove_const, :TestAttribute
|
15
|
-
Hexx.send :remove_const, :TestModel
|
16
|
-
end
|
17
|
-
|
18
|
-
let!(:coerced_attribute) { double "coerced attribute" }
|
19
|
-
before do
|
20
|
-
allow(TestAttribute).to receive(:new) { |val| coerced_attribute if val }
|
21
|
-
end
|
22
|
-
|
23
|
-
# ==========================================================================
|
24
|
-
# Run tests
|
25
|
-
# ==========================================================================
|
26
|
-
|
27
|
-
describe ".attr_coerced" do
|
28
|
-
|
29
|
-
subject { TestModel }
|
30
|
-
before { subject.send :attr_coerced, :name, type: TestAttribute }
|
31
|
-
let(:object) { TestModel.new }
|
32
|
-
|
33
|
-
it "coerces an attribute with given type" do
|
34
|
-
expect { object.name = "some name" }
|
35
|
-
.to change { object.name }
|
36
|
-
.from(nil).to coerced_attribute
|
37
|
-
end
|
38
|
-
end
|
39
|
-
end
|
40
|
-
end
|