wardrobe 0.1.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 +7 -0
- data/.codeclimate.yml +10 -0
- data/.gitignore +19 -0
- data/.ruby-version +1 -0
- data/.travis.yml +11 -0
- data/CHANGELOG.md +5 -0
- data/Gemfile +18 -0
- data/Guardfile +42 -0
- data/LICENSE +19 -0
- data/README.md +227 -0
- data/Rakefile +20 -0
- data/examples/new_york_times_article.rb +55 -0
- data/lib/wardrobe/attribute.rb +76 -0
- data/lib/wardrobe/attribute_store.rb +16 -0
- data/lib/wardrobe/block_setup.rb +124 -0
- data/lib/wardrobe/boolean.rb +6 -0
- data/lib/wardrobe/class_methods.rb +127 -0
- data/lib/wardrobe/getter_setter.rb +48 -0
- data/lib/wardrobe/instance_methods.rb +56 -0
- data/lib/wardrobe/module_methods.rb +51 -0
- data/lib/wardrobe/option.rb +30 -0
- data/lib/wardrobe/option_store.rb +22 -0
- data/lib/wardrobe/plugin.rb +39 -0
- data/lib/wardrobe/plugin_store.rb +28 -0
- data/lib/wardrobe/plugins/alias_setters.rb +35 -0
- data/lib/wardrobe/plugins/coercible/refinements/array.rb +63 -0
- data/lib/wardrobe/plugins/coercible/refinements/boolean.rb +36 -0
- data/lib/wardrobe/plugins/coercible/refinements/date.rb +31 -0
- data/lib/wardrobe/plugins/coercible/refinements/date_time.rb +29 -0
- data/lib/wardrobe/plugins/coercible/refinements/float.rb +23 -0
- data/lib/wardrobe/plugins/coercible/refinements/hash.rb +65 -0
- data/lib/wardrobe/plugins/coercible/refinements/integer.rb +23 -0
- data/lib/wardrobe/plugins/coercible/refinements/object.rb +15 -0
- data/lib/wardrobe/plugins/coercible/refinements/set.rb +33 -0
- data/lib/wardrobe/plugins/coercible/refinements/string.rb +21 -0
- data/lib/wardrobe/plugins/coercible/refinements/symbol.rb +21 -0
- data/lib/wardrobe/plugins/coercible/refinements/time.rb +30 -0
- data/lib/wardrobe/plugins/coercible/refinements/unsupported_error.rb +11 -0
- data/lib/wardrobe/plugins/coercible.rb +52 -0
- data/lib/wardrobe/plugins/configurable/configurable_store.rb +26 -0
- data/lib/wardrobe/plugins/configurable.rb +40 -0
- data/lib/wardrobe/plugins/default.rb +33 -0
- data/lib/wardrobe/plugins/dirty_tracker.rb +66 -0
- data/lib/wardrobe/plugins/equality.rb +19 -0
- data/lib/wardrobe/plugins/html_initializer.rb +38 -0
- data/lib/wardrobe/plugins/immutable.rb +164 -0
- data/lib/wardrobe/plugins/ivy_presenter.rb +42 -0
- data/lib/wardrobe/plugins/json_initializer.rb +41 -0
- data/lib/wardrobe/plugins/nil_if_empty.rb +27 -0
- data/lib/wardrobe/plugins/nil_if_zero.rb +19 -0
- data/lib/wardrobe/plugins/optional_getter.rb +21 -0
- data/lib/wardrobe/plugins/optional_setter.rb +24 -0
- data/lib/wardrobe/plugins/presenter/refinements/array.rb +15 -0
- data/lib/wardrobe/plugins/presenter/refinements/hash.rb +15 -0
- data/lib/wardrobe/plugins/presenter/refinements/object.rb +15 -0
- data/lib/wardrobe/plugins/presenter/refinements/time.rb +19 -0
- data/lib/wardrobe/plugins/presenter/refinements.rb +6 -0
- data/lib/wardrobe/plugins/presenter.rb +25 -0
- data/lib/wardrobe/plugins/validation/block_handler.rb +83 -0
- data/lib/wardrobe/plugins/validation/class_methods.rb +13 -0
- data/lib/wardrobe/plugins/validation/deep_merge.rb +27 -0
- data/lib/wardrobe/plugins/validation/error_store.rb +27 -0
- data/lib/wardrobe/plugins/validation/instance_methods.rb +39 -0
- data/lib/wardrobe/plugins/validation/refinements/_size.rb +30 -0
- data/lib/wardrobe/plugins/validation/refinements/array.rb +26 -0
- data/lib/wardrobe/plugins/validation/refinements/date.rb +15 -0
- data/lib/wardrobe/plugins/validation/refinements/hash.rb +27 -0
- data/lib/wardrobe/plugins/validation/refinements/integer.rb +21 -0
- data/lib/wardrobe/plugins/validation/refinements/nil_class.rb +19 -0
- data/lib/wardrobe/plugins/validation/refinements/numeric.rb +31 -0
- data/lib/wardrobe/plugins/validation/refinements/object.rb +35 -0
- data/lib/wardrobe/plugins/validation/refinements/set.rb +25 -0
- data/lib/wardrobe/plugins/validation/refinements/string.rb +55 -0
- data/lib/wardrobe/plugins/validation/refinements/symbol.rb +26 -0
- data/lib/wardrobe/plugins/validation/refinements.rb +13 -0
- data/lib/wardrobe/plugins/validation/validation.rb +63 -0
- data/lib/wardrobe/plugins/validation/validation_error.rb +19 -0
- data/lib/wardrobe/plugins/validation/validaton_runner.rb +38 -0
- data/lib/wardrobe/plugins/validation/validator.rb +119 -0
- data/lib/wardrobe/plugins/validation.rb +28 -0
- data/lib/wardrobe/root_config.rb +31 -0
- data/lib/wardrobe/store.rb +62 -0
- data/lib/wardrobe/stores.rb +106 -0
- data/lib/wardrobe/version.rb +5 -0
- data/lib/wardrobe.rb +34 -0
- data/sandbox/Gemfile +5 -0
- data/sandbox/Gemfile.lock +52 -0
- data/sandbox/bench_mutable_coercion.rb +91 -0
- data/sandbox/bench_test_1.rb +50 -0
- data/sandbox/bench_test_2.rb +48 -0
- data/sandbox/bench_test_3.rb +92 -0
- data/sandbox/cnn_article_find.rb +20 -0
- data/sandbox/define_method_procs.rb +139 -0
- data/sandbox/hanami_validations.rb +40 -0
- data/sandbox/middleware_bench_test.rb +97 -0
- data/sandbox/middleware_bench_v2_test.rb +130 -0
- data/test/assertions.rb +22 -0
- data/test/test_helper.rb +37 -0
- data/test/unit/atrs_config_test.rb +33 -0
- data/test/unit/atrs_root_module_test.rb +19 -0
- data/test/unit/attribute_test.rb +44 -0
- data/test/unit/block_runner/array_test.rb +29 -0
- data/test/unit/block_setup_test.rb +41 -0
- data/test/unit/class_methods_test.rb +92 -0
- data/test/unit/create_class_from_hash_test.rb +28 -0
- data/test/unit/define_getter_test.rb +94 -0
- data/test/unit/define_setter_test.rb +0 -0
- data/test/unit/disable_coercion_test.rb +19 -0
- data/test/unit/inheritance_composition_test.rb +36 -0
- data/test/unit/method_override_test.rb +18 -0
- data/test/unit/method_polution_test.rb +48 -0
- data/test/unit/option_test.rb +17 -0
- data/test/unit/plugin_test.rb +12 -0
- data/test/unit/plugins/alias_setters_test.rb +24 -0
- data/test/unit/plugins/coercible/array_test.rb +79 -0
- data/test/unit/plugins/coercible/boolean_test.rb +68 -0
- data/test/unit/plugins/coercible/custom_class_test.rb +61 -0
- data/test/unit/plugins/coercible/date_test.rb +38 -0
- data/test/unit/plugins/coercible/date_time_test.rb +44 -0
- data/test/unit/plugins/coercible/float_test.rb +42 -0
- data/test/unit/plugins/coercible/hash_test.rb +62 -0
- data/test/unit/plugins/coercible/integer_test.rb +42 -0
- data/test/unit/plugins/coercible/nested_wardrobe_test.rb +63 -0
- data/test/unit/plugins/coercible/set_test.rb +49 -0
- data/test/unit/plugins/coercible/string_test.rb +36 -0
- data/test/unit/plugins/coercible/symbol_test.rb +30 -0
- data/test/unit/plugins/coercible/time_test.rb +43 -0
- data/test/unit/plugins/configurable_test.rb +64 -0
- data/test/unit/plugins/default_value_test.rb +78 -0
- data/test/unit/plugins/dirty_tracker_test.rb +78 -0
- data/test/unit/plugins/equality_test.rb +36 -0
- data/test/unit/plugins/html_initializer_test.rb +19 -0
- data/test/unit/plugins/immutable_test.rb +149 -0
- data/test/unit/plugins/ivy_presenter_test.rb +57 -0
- data/test/unit/plugins/json_initializer_test.rb +67 -0
- data/test/unit/plugins/nil_if_empty_test.rb +39 -0
- data/test/unit/plugins/nil_if_zero_test.rb +26 -0
- data/test/unit/plugins/presenter_test.rb +68 -0
- data/test/unit/plugins/validate/inheritance_test.rb +36 -0
- data/test/unit/plugins/validate/nested_model_test.rb +40 -0
- data/test/unit/plugins/validate/predicates/each_key_each_value_test.rb +34 -0
- data/test/unit/plugins/validate/predicates/each_test.rb +33 -0
- data/test/unit/plugins/validate/predicates/empty_test.rb +37 -0
- data/test/unit/plugins/validate/predicates/even_test.rb +33 -0
- data/test/unit/plugins/validate/predicates/excluded_from_test.rb +55 -0
- data/test/unit/plugins/validate/predicates/filled_test.rb +49 -0
- data/test/unit/plugins/validate/predicates/format_test.rb +28 -0
- data/test/unit/plugins/validate/predicates/gt_test.rb +36 -0
- data/test/unit/plugins/validate/predicates/gteq_test.rb +36 -0
- data/test/unit/plugins/validate/predicates/included_in_test.rb +55 -0
- data/test/unit/plugins/validate/predicates/lt_test.rb +36 -0
- data/test/unit/plugins/validate/predicates/lteq_test.rb +36 -0
- data/test/unit/plugins/validate/predicates/max_size_test.rb +43 -0
- data/test/unit/plugins/validate/predicates/min_size_test.rb +43 -0
- data/test/unit/plugins/validate/predicates/none_test.rb +49 -0
- data/test/unit/plugins/validate/predicates/odd_test.rb +33 -0
- data/test/unit/plugins/validate/predicates/size_range_test.rb +43 -0
- data/test/unit/plugins/validate/predicates/size_test.rb +43 -0
- data/test/unit/plugins/validate/predicates/type_test.rb +77 -0
- data/test/unit/plugins/validate/predicates_test.rb +73 -0
- data/test/unit/plugins/validate/validate_bang_test.rb +30 -0
- data/test/unit/store_test.rb +15 -0
- data/test/unit/stores_test.rb +18 -0
- data/wardrobe.gemspec +26 -0
- metadata +344 -0
@@ -0,0 +1,50 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'pry-byebug'
|
3
|
+
|
4
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
5
|
+
require_relative '../lib/wardrobe'
|
6
|
+
require 'virtus'
|
7
|
+
require 'benchmark/ips'
|
8
|
+
|
9
|
+
# Test 1: Simple object
|
10
|
+
# Simple class with one attribute where input does not need coercion.
|
11
|
+
|
12
|
+
VanillaStruct = Struct.new(:name)
|
13
|
+
|
14
|
+
class VanillaClass
|
15
|
+
attr_reader :name
|
16
|
+
|
17
|
+
def initialize(name:)
|
18
|
+
@name = name
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class SimpleVirtus
|
23
|
+
include Virtus.model
|
24
|
+
attribute :name, String
|
25
|
+
end
|
26
|
+
|
27
|
+
class SimpleWardrobe
|
28
|
+
include Wardrobe
|
29
|
+
attribute :name, String
|
30
|
+
end
|
31
|
+
|
32
|
+
Benchmark.ips do |x|
|
33
|
+
x.report('Vanilla Struct') {
|
34
|
+
instance = VanillaStruct.new('Test')
|
35
|
+
instance.name == 'Test'
|
36
|
+
}
|
37
|
+
x.report('Vanilla Class') {
|
38
|
+
instance = VanillaClass.new(name: 'Test')
|
39
|
+
instance.name == 'Test'
|
40
|
+
}
|
41
|
+
x.report('Wardrobe Simple') {
|
42
|
+
instance = SimpleWardrobe.new(name: 'Test')
|
43
|
+
instance.name == 'Test'
|
44
|
+
}
|
45
|
+
x.report('Virtus Simple') {
|
46
|
+
instance = SimpleVirtus.new(name: 'Test')
|
47
|
+
instance.name == 'Test'
|
48
|
+
}
|
49
|
+
x.compare!
|
50
|
+
end
|
@@ -0,0 +1,48 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require_relative '../lib/wardrobe'
|
4
|
+
require 'virtus'
|
5
|
+
require 'benchmark/ips'
|
6
|
+
require 'pry'
|
7
|
+
require 'pry-byebug'
|
8
|
+
|
9
|
+
# Test 2: Normal object
|
10
|
+
# A user class where an integer and a float will need to be coerced from a string
|
11
|
+
|
12
|
+
class UserVirtus
|
13
|
+
include Virtus.model
|
14
|
+
attribute :first_name, String
|
15
|
+
attribute :last_name, String
|
16
|
+
attribute :age, Integer
|
17
|
+
attribute :a_float, Float
|
18
|
+
end
|
19
|
+
|
20
|
+
class UserWardrobe
|
21
|
+
include Wardrobe
|
22
|
+
attribute :first_name, String
|
23
|
+
attribute :last_name, String
|
24
|
+
attribute :age, Integer
|
25
|
+
attribute :a_float, Float
|
26
|
+
end
|
27
|
+
|
28
|
+
test_2_hash = {
|
29
|
+
first_name: 'Test', last_name: 'Person', age: '1', a_float: '0.001'
|
30
|
+
}
|
31
|
+
|
32
|
+
Benchmark.ips do |x|
|
33
|
+
x.report('Wardrobe Normal') {
|
34
|
+
instance = UserWardrobe.new(test_2_hash)
|
35
|
+
instance.first_name == 'Test'
|
36
|
+
instance.last_name == 'Person'
|
37
|
+
instance.age == 1
|
38
|
+
instance.a_float == 0.001
|
39
|
+
}
|
40
|
+
x.report('Virtus Normal') {
|
41
|
+
instance = UserVirtus.new(test_2_hash)
|
42
|
+
instance.first_name == 'Test'
|
43
|
+
instance.last_name == 'Person'
|
44
|
+
instance.age == 1
|
45
|
+
instance.a_float == 0.001
|
46
|
+
}
|
47
|
+
x.compare!
|
48
|
+
end
|
@@ -0,0 +1,92 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
|
3
|
+
require_relative '../lib/wardrobe'
|
4
|
+
require 'virtus'
|
5
|
+
require 'benchmark/ips'
|
6
|
+
require 'pry'
|
7
|
+
require 'pry-byebug'
|
8
|
+
|
9
|
+
# Test 3: Advanced object
|
10
|
+
# As in test 2 but with an address that needs to be coerced into a sub class.
|
11
|
+
|
12
|
+
class AddressVirtus
|
13
|
+
include Virtus.model
|
14
|
+
attribute :street, String
|
15
|
+
attribute :zip_code, String
|
16
|
+
end
|
17
|
+
|
18
|
+
class UserAdvancedVirtus
|
19
|
+
include Virtus.model
|
20
|
+
attribute :first_name, String
|
21
|
+
attribute :last_name, String
|
22
|
+
attribute :age, Integer
|
23
|
+
attribute :a_float, Float
|
24
|
+
attribute :with_default_literal, String, default: 'literal'
|
25
|
+
attribute :with_default_proc, String, default: ->(_,_) {'proc'}
|
26
|
+
attribute :with_default_method, String, default: :default_method
|
27
|
+
attribute :address, AddressVirtus
|
28
|
+
|
29
|
+
def default_method
|
30
|
+
'method'
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
class AddressWardrobe
|
35
|
+
include Wardrobe
|
36
|
+
attribute :street, String
|
37
|
+
attribute :zip_code, String
|
38
|
+
end
|
39
|
+
|
40
|
+
class UserAdvancedWardrobe
|
41
|
+
include Wardrobe
|
42
|
+
plugin :default
|
43
|
+
attribute :first_name, String
|
44
|
+
attribute :last_name, String
|
45
|
+
attribute :age, Integer
|
46
|
+
attribute :a_float, Float
|
47
|
+
attribute :with_default_literal, String, default: 'literal'
|
48
|
+
attribute :with_default_proc, String, default: -> { 'proc' }
|
49
|
+
attribute :with_default_method, String, default: :default_method
|
50
|
+
attribute :address, AddressWardrobe
|
51
|
+
|
52
|
+
def default_method
|
53
|
+
'method'
|
54
|
+
end
|
55
|
+
end
|
56
|
+
|
57
|
+
test_3_hash = {
|
58
|
+
first_name: 'Test', last_name: 'Person', age: '1', a_float: '0.001',
|
59
|
+
address: {
|
60
|
+
street: 'Somewhere In Japan',
|
61
|
+
zip_code: 12345
|
62
|
+
}
|
63
|
+
}
|
64
|
+
|
65
|
+
|
66
|
+
Benchmark.ips do |x|
|
67
|
+
x.report('Wardrobe Advanced') {
|
68
|
+
instance = UserAdvancedWardrobe.new(test_3_hash)
|
69
|
+
instance.first_name == 'Test'
|
70
|
+
instance.last_name == 'Person'
|
71
|
+
instance.age == 1
|
72
|
+
instance.a_float == 0.001
|
73
|
+
instance.with_default_literal == 'literal'
|
74
|
+
instance.with_default_proc == 'proc'
|
75
|
+
instance.with_default_method == 'method'
|
76
|
+
instance.address.street == 'Somewhere In Japan'
|
77
|
+
instance.address.zip_code == 12345
|
78
|
+
}
|
79
|
+
x.report('Virtus Advanced') {
|
80
|
+
instance = UserAdvancedVirtus.new(test_3_hash)
|
81
|
+
instance.first_name == 'Test'
|
82
|
+
instance.last_name == 'Person'
|
83
|
+
instance.age == 1
|
84
|
+
instance.a_float == 0.001
|
85
|
+
instance.with_default_literal == 'literal'
|
86
|
+
instance.with_default_proc == 'proc'
|
87
|
+
instance.with_default_method == 'method'
|
88
|
+
instance.address.street == 'Somewhere In Japan'
|
89
|
+
instance.address.zip_code == 12345
|
90
|
+
}
|
91
|
+
x.compare!
|
92
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
$:.unshift File.expand_path('../../lib', __FILE__)
|
2
|
+
require_relative '../lib/wardrobe'
|
3
|
+
require 'http'
|
4
|
+
require 'pry'
|
5
|
+
require 'pry-byebug'
|
6
|
+
|
7
|
+
class Article
|
8
|
+
include Wardrobe
|
9
|
+
plugin :html_initializer
|
10
|
+
attribute :title, String, html_selector: ->(h) { h.at_xpath('//h1[@class="pg-headline"]').text }
|
11
|
+
|
12
|
+
def self.find(url)
|
13
|
+
new(HTTP.get(url).to_s)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
article = Article.find('http://edition.cnn.com/2017/04/27/sport/yorkshire-cycling-revolution/index.html')
|
19
|
+
binding.pry
|
20
|
+
article.title
|
@@ -0,0 +1,139 @@
|
|
1
|
+
require 'pry'
|
2
|
+
require 'pry-byebug'
|
3
|
+
|
4
|
+
class Middleware
|
5
|
+
attr_reader :next_middleware
|
6
|
+
def initialize(next_middleware = nil)
|
7
|
+
@next_middleware = next_middleware
|
8
|
+
freeze
|
9
|
+
end
|
10
|
+
|
11
|
+
def call(input)
|
12
|
+
return input unless next_middleware
|
13
|
+
next_middleware.call(input)
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.build(*arr)
|
17
|
+
arr.reverse!
|
18
|
+
arr.inject(arr.shift.new) do |previous, current|
|
19
|
+
current.new(previous)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
class Split < Middleware
|
25
|
+
def call(value)
|
26
|
+
super(value.split(''))
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
class EachDowncase < Middleware
|
31
|
+
def call(value)
|
32
|
+
super(value.map(&:downcase))
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
class EachAddSpace < Middleware
|
37
|
+
def call(value)
|
38
|
+
super(value.map { |item| item + ' ' })
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
stack = Middleware.build(Split, EachDowncase, EachAddSpace)
|
43
|
+
stack.call('abc')
|
44
|
+
binding.pry
|
45
|
+
|
46
|
+
# module Split
|
47
|
+
# def self.call(input, instance)
|
48
|
+
# result = input.split('')
|
49
|
+
# if block_given?
|
50
|
+
# yield result, instance
|
51
|
+
# else
|
52
|
+
# result
|
53
|
+
# end
|
54
|
+
# end
|
55
|
+
# end
|
56
|
+
#
|
57
|
+
# module EachDowncase
|
58
|
+
# def self.call(input, instance)
|
59
|
+
# result = input.each(&:downcase)
|
60
|
+
# if block_given?
|
61
|
+
# yield result, instance
|
62
|
+
# else
|
63
|
+
# result
|
64
|
+
# end
|
65
|
+
# end
|
66
|
+
# end
|
67
|
+
|
68
|
+
array = [
|
69
|
+
Split,
|
70
|
+
EachDowncase
|
71
|
+
]
|
72
|
+
|
73
|
+
val = 'abcde'
|
74
|
+
|
75
|
+
stack =
|
76
|
+
|
77
|
+
|
78
|
+
# arr = [
|
79
|
+
# a_proc,
|
80
|
+
# a_proc,
|
81
|
+
# a_proc
|
82
|
+
# ].each do
|
83
|
+
#
|
84
|
+
# loop do
|
85
|
+
# begin
|
86
|
+
# current = arr.next
|
87
|
+
# next_ = arr.peek
|
88
|
+
# binding.pry
|
89
|
+
#
|
90
|
+
# rescue StopIteration => e
|
91
|
+
# binding.pry
|
92
|
+
# end
|
93
|
+
# end
|
94
|
+
|
95
|
+
# arr.inject(->(_,_){ input }).to_enum.each do |item|
|
96
|
+
# end
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
first_proc.call('', &another_proc)
|
101
|
+
|
102
|
+
proc_enum = procs.to_enum
|
103
|
+
|
104
|
+
proc_enum
|
105
|
+
|
106
|
+
proc_enum.inject(nil) do |value, pr|
|
107
|
+
|
108
|
+
binding.pry
|
109
|
+
end
|
110
|
+
|
111
|
+
|
112
|
+
|
113
|
+
# procs.each do |proc|
|
114
|
+
# binding.pry
|
115
|
+
# end
|
116
|
+
#
|
117
|
+
|
118
|
+
|
119
|
+
|
120
|
+
|
121
|
+
|
122
|
+
|
123
|
+
class SomeClass
|
124
|
+
proc2 = -> (one, two, &blk) {
|
125
|
+
one + two
|
126
|
+
}
|
127
|
+
|
128
|
+
define_method(:name, &proc2)
|
129
|
+
|
130
|
+
# end
|
131
|
+
end
|
132
|
+
|
133
|
+
ddd = SomeClass.new
|
134
|
+
ddd
|
135
|
+
|
136
|
+
binding.pry
|
137
|
+
ddd
|
138
|
+
|
139
|
+
1
|
@@ -0,0 +1,40 @@
|
|
1
|
+
require 'hanami'
|
2
|
+
require 'pry'
|
3
|
+
require 'pry-byebug'
|
4
|
+
|
5
|
+
class Foo
|
6
|
+
include Hanami::Validations
|
7
|
+
|
8
|
+
validations do
|
9
|
+
required(:one) { size?(3) }
|
10
|
+
required(:two) { hash? { size?(2..4) } }
|
11
|
+
required(:three) { hash? { size?(2..4) { each { int? }} } }
|
12
|
+
required(:four) { hash? { min_size?(3) } }
|
13
|
+
required(:five) { hash? { max_size?(0) } }
|
14
|
+
required(:six) { str? }
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
class Bar
|
19
|
+
include Hanami::Validations
|
20
|
+
|
21
|
+
validations do
|
22
|
+
required(:one) { format?(/ccc/) | format?(/ddd/) }
|
23
|
+
# required(:two) { included_in?(['one']) }
|
24
|
+
# required(:three) { included_in?(['one', [1], Time.now]) }
|
25
|
+
# required(:four) { empty? }
|
26
|
+
# required(:five) { empty? }
|
27
|
+
# required(:six) { empty? }
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
result = Bar.new(
|
32
|
+
one: 'abb',
|
33
|
+
two: :'',
|
34
|
+
three: [],
|
35
|
+
four: {},
|
36
|
+
five: nil
|
37
|
+
).validate
|
38
|
+
|
39
|
+
|
40
|
+
binding.irb
|
@@ -0,0 +1,97 @@
|
|
1
|
+
require 'benchmark/ips'
|
2
|
+
require 'pry'
|
3
|
+
require 'pry-byebug'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'middleware'
|
6
|
+
|
7
|
+
procs = [
|
8
|
+
Proc.new { |val, instance| instance.name + val },
|
9
|
+
Proc.new { |val, instance| instance.name + val },
|
10
|
+
Proc.new { |val, instance| instance.name + val }
|
11
|
+
]
|
12
|
+
|
13
|
+
lambdas = [
|
14
|
+
lambda { |val, instance| instance.name + val },
|
15
|
+
lambda { |val, instance| instance.name + val },
|
16
|
+
lambda { |val, instance| instance.name + val }
|
17
|
+
]
|
18
|
+
|
19
|
+
modules = [
|
20
|
+
Module.new {
|
21
|
+
def self.call(val, instance)
|
22
|
+
instance.name + val
|
23
|
+
end
|
24
|
+
},
|
25
|
+
Module.new {
|
26
|
+
def self.call(val, instance)
|
27
|
+
instance.name + val
|
28
|
+
end
|
29
|
+
},
|
30
|
+
Module.new {
|
31
|
+
def self.call(val, instance)
|
32
|
+
instance.name + val
|
33
|
+
end
|
34
|
+
}
|
35
|
+
]
|
36
|
+
|
37
|
+
classes = [
|
38
|
+
Class.new {
|
39
|
+
def call(val, instance)
|
40
|
+
instance.name + val
|
41
|
+
end
|
42
|
+
},
|
43
|
+
Class.new {
|
44
|
+
def call(val, instance)
|
45
|
+
instance.name + val
|
46
|
+
end
|
47
|
+
},
|
48
|
+
Class.new {
|
49
|
+
def call(val, instance)
|
50
|
+
instance.name + val
|
51
|
+
end
|
52
|
+
}
|
53
|
+
]
|
54
|
+
|
55
|
+
mid = Middleware::Builder.new { |b|
|
56
|
+
b.use lambda { |data| data[:val] = data[:instance].name + data[:val]; data }
|
57
|
+
b.use lambda { |data| data[:val] = data[:instance].name + data[:val]; data }
|
58
|
+
b.use lambda { |data| data[:val] = data[:instance].name + data[:val]; data }
|
59
|
+
}
|
60
|
+
|
61
|
+
instance = OpenStruct.new(name: 'Yes! ')
|
62
|
+
|
63
|
+
procs.inject('') do |val, item|
|
64
|
+
item.call(val, instance)
|
65
|
+
end
|
66
|
+
|
67
|
+
modules.inject('') do |val, item|
|
68
|
+
item.call(val, instance)
|
69
|
+
end
|
70
|
+
|
71
|
+
|
72
|
+
Benchmark.ips do |x|
|
73
|
+
x.report('Procs') {
|
74
|
+
procs.inject('') do |val, item|
|
75
|
+
item.call(val, instance)
|
76
|
+
end
|
77
|
+
}
|
78
|
+
x.report('Lambdas') {
|
79
|
+
lambdas.inject('') do |val, item|
|
80
|
+
item.call(val, instance)
|
81
|
+
end
|
82
|
+
}
|
83
|
+
x.report('Modules') {
|
84
|
+
modules.inject('') do |val, item|
|
85
|
+
item.call(val, instance)
|
86
|
+
end
|
87
|
+
}
|
88
|
+
x.report('Classes') {
|
89
|
+
classes.inject('') do |val, item|
|
90
|
+
item.new.call(val, instance)
|
91
|
+
end
|
92
|
+
}
|
93
|
+
x.report('Middleware Gem') {
|
94
|
+
mid.call({val: '', instance: instance})[:val]
|
95
|
+
}
|
96
|
+
x.compare!
|
97
|
+
end
|
@@ -0,0 +1,130 @@
|
|
1
|
+
require 'benchmark/ips'
|
2
|
+
require 'pry'
|
3
|
+
require 'pry-byebug'
|
4
|
+
require 'ostruct'
|
5
|
+
require 'middleware'
|
6
|
+
|
7
|
+
### One - Custom middleware System
|
8
|
+
|
9
|
+
class One
|
10
|
+
attr_reader :next_middleware
|
11
|
+
def initialize(next_middleware = nil)
|
12
|
+
@next_middleware = next_middleware
|
13
|
+
freeze
|
14
|
+
end
|
15
|
+
|
16
|
+
def call(input)
|
17
|
+
return input unless next_middleware
|
18
|
+
next_middleware.call(input)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.build(*arr)
|
22
|
+
arr.reverse!
|
23
|
+
arr.inject(arr.shift.new) do |previous, current|
|
24
|
+
current.new(previous)
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
class Split < One
|
30
|
+
def call(value)
|
31
|
+
super(value.split(''))
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
class EachDowncase < One
|
36
|
+
def call(value)
|
37
|
+
super(value.map(&:downcase))
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
class EachAddSpace < One
|
42
|
+
def call(value)
|
43
|
+
super(value.map { |item| item + ' ' })
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
one_stack = One.build(Split, EachDowncase, EachAddSpace)
|
48
|
+
|
49
|
+
|
50
|
+
#### Two - CUSTOM MIDDLEWARE SYSTEM WITH DYNAMIC CALL
|
51
|
+
|
52
|
+
module Some
|
53
|
+
def call(input)
|
54
|
+
return input unless next_middleware
|
55
|
+
next_middleware.call(input)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
|
60
|
+
class Two
|
61
|
+
attr_reader :middlewares
|
62
|
+
def initialize(middlewares = arr)
|
63
|
+
@middlewares = middlewares
|
64
|
+
freeze
|
65
|
+
end
|
66
|
+
|
67
|
+
def call(input)
|
68
|
+
middlewares.inject(input) do |val, pro|
|
69
|
+
pro.call(val)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
|
73
|
+
def self.build(*arr)
|
74
|
+
new(arr)
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
split_2 = ->(value) {
|
79
|
+
value.split('')
|
80
|
+
}
|
81
|
+
|
82
|
+
each_downcase_2 = ->(value) {
|
83
|
+
value.map(&:downcase)
|
84
|
+
}
|
85
|
+
|
86
|
+
each_add_space_2 = ->(value) {
|
87
|
+
value.map { |item| item + ' ' }
|
88
|
+
}
|
89
|
+
|
90
|
+
two_stack = Two.build(split_2, each_downcase_2, each_add_space_2)
|
91
|
+
|
92
|
+
CORRECT = ['a ', 'b ', 'c ', 'd ', 'e ', 'f ']
|
93
|
+
|
94
|
+
|
95
|
+
Benchmark.ips do |x|
|
96
|
+
x.report('One - Custom') {
|
97
|
+
result = one_stack.call('abcdef')
|
98
|
+
# raise "ERROR" unless result == CORRECT
|
99
|
+
}
|
100
|
+
|
101
|
+
x.report('Two - Array of procs with inject') {
|
102
|
+
result = two_stack.call('abcdef')
|
103
|
+
# raise "ERROR" unless result == CORRECT
|
104
|
+
}
|
105
|
+
|
106
|
+
# x.report('Procs') {
|
107
|
+
# procs.inject('') do |val, item|
|
108
|
+
# item.call(val, instance)
|
109
|
+
# end
|
110
|
+
# }
|
111
|
+
# x.report('Lambdas') {
|
112
|
+
# lambdas.inject('') do |val, item|
|
113
|
+
# item.call(val, instance)
|
114
|
+
# end
|
115
|
+
# }
|
116
|
+
# x.report('Modules') {
|
117
|
+
# modules.inject('') do |val, item|
|
118
|
+
# item.call(val, instance)
|
119
|
+
# end
|
120
|
+
# }
|
121
|
+
# x.report('Classes') {
|
122
|
+
# classes.inject('') do |val, item|
|
123
|
+
# item.new.call(val, instance)
|
124
|
+
# end
|
125
|
+
# }
|
126
|
+
# x.report('Middleware Gem') {
|
127
|
+
# mid.call({val: '', instance: instance})[:val]
|
128
|
+
# }
|
129
|
+
x.compare!
|
130
|
+
end
|
data/test/assertions.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
module Minitest::Assertions
|
2
|
+
def assert_instance_method_call_count(count, klass, method, &blk)
|
3
|
+
actual_count = instance_method_call_count(count, klass, method, &blk)
|
4
|
+
assert actual_count == count,
|
5
|
+
"Expected #{count} calls to method #{method} on klass #{klass} but registered #{actual_count}"
|
6
|
+
end
|
7
|
+
|
8
|
+
private
|
9
|
+
|
10
|
+
def instance_method_call_count(count, klass, method)
|
11
|
+
registered_counts = 0
|
12
|
+
klass.class_exec do
|
13
|
+
alias_method "old_#{method}", method
|
14
|
+
define_method(method) do |*args|
|
15
|
+
registered_counts += 1
|
16
|
+
send("old_#{method}", *args)
|
17
|
+
end
|
18
|
+
end
|
19
|
+
yield
|
20
|
+
registered_counts
|
21
|
+
end
|
22
|
+
end
|
data/test/test_helper.rb
ADDED
@@ -0,0 +1,37 @@
|
|
1
|
+
require 'simplecov'
|
2
|
+
SimpleCov.start do
|
3
|
+
# TODO: Figure out a way to include these files in the report. Fork is used.
|
4
|
+
add_filter 'test/unit/plugins/json_initializer_test.rb'
|
5
|
+
add_filter 'lib/wardrobe/plugins/json_initializer.rb'
|
6
|
+
end
|
7
|
+
|
8
|
+
require 'pry'
|
9
|
+
require 'pry-byebug'
|
10
|
+
|
11
|
+
require 'minitest/autorun'
|
12
|
+
require 'assertions'
|
13
|
+
require 'wardrobe'
|
14
|
+
|
15
|
+
|
16
|
+
LOG_MESSAGES = []
|
17
|
+
|
18
|
+
class TestBase < Minitest::Test
|
19
|
+
def log_messages
|
20
|
+
LOG_MESSAGES
|
21
|
+
end
|
22
|
+
|
23
|
+
def teardown
|
24
|
+
LOG_MESSAGES.clear
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
class TestLogger < Logger
|
29
|
+
def format_message(severity, datetime, progname, msg)
|
30
|
+
LOG_MESSAGES << [severity, datetime, progname, msg]
|
31
|
+
super
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
Wardrobe.configure do |c|
|
36
|
+
c.logger = TestLogger.new(File.open(File::NULL, "w"))
|
37
|
+
end
|
@@ -0,0 +1,33 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require 'test_helper'
|
4
|
+
|
5
|
+
class WardrobeConfigTest < TestBase
|
6
|
+
CUSTOM_ATRS_MODULE = Wardrobe()
|
7
|
+
CUSTOM_ATRS_MODULE.configure do |config|
|
8
|
+
config.register_default_plugin :default
|
9
|
+
end
|
10
|
+
|
11
|
+
class Person
|
12
|
+
include CUSTOM_ATRS_MODULE
|
13
|
+
attribute :name, String, default: 'Example Person'
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_plugin_registered_in_module
|
17
|
+
assert CUSTOM_ATRS_MODULE.config.default_plugins.include?(:default)
|
18
|
+
end
|
19
|
+
|
20
|
+
def test_plugin_added_to_class
|
21
|
+
assert Person.plugin_store[:default]
|
22
|
+
assert Person.option_store[:default]
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_correct_plugin_and_option_count
|
26
|
+
assert_equal 2, Person.option_store.store.count
|
27
|
+
assert_equal 2, Person.plugin_store.store.count
|
28
|
+
end
|
29
|
+
|
30
|
+
def test_one
|
31
|
+
assert_equal 'Example Person', Person.new.name
|
32
|
+
end
|
33
|
+
end
|