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.
Files changed (165) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +10 -0
  3. data/.gitignore +19 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +11 -0
  6. data/CHANGELOG.md +5 -0
  7. data/Gemfile +18 -0
  8. data/Guardfile +42 -0
  9. data/LICENSE +19 -0
  10. data/README.md +227 -0
  11. data/Rakefile +20 -0
  12. data/examples/new_york_times_article.rb +55 -0
  13. data/lib/wardrobe/attribute.rb +76 -0
  14. data/lib/wardrobe/attribute_store.rb +16 -0
  15. data/lib/wardrobe/block_setup.rb +124 -0
  16. data/lib/wardrobe/boolean.rb +6 -0
  17. data/lib/wardrobe/class_methods.rb +127 -0
  18. data/lib/wardrobe/getter_setter.rb +48 -0
  19. data/lib/wardrobe/instance_methods.rb +56 -0
  20. data/lib/wardrobe/module_methods.rb +51 -0
  21. data/lib/wardrobe/option.rb +30 -0
  22. data/lib/wardrobe/option_store.rb +22 -0
  23. data/lib/wardrobe/plugin.rb +39 -0
  24. data/lib/wardrobe/plugin_store.rb +28 -0
  25. data/lib/wardrobe/plugins/alias_setters.rb +35 -0
  26. data/lib/wardrobe/plugins/coercible/refinements/array.rb +63 -0
  27. data/lib/wardrobe/plugins/coercible/refinements/boolean.rb +36 -0
  28. data/lib/wardrobe/plugins/coercible/refinements/date.rb +31 -0
  29. data/lib/wardrobe/plugins/coercible/refinements/date_time.rb +29 -0
  30. data/lib/wardrobe/plugins/coercible/refinements/float.rb +23 -0
  31. data/lib/wardrobe/plugins/coercible/refinements/hash.rb +65 -0
  32. data/lib/wardrobe/plugins/coercible/refinements/integer.rb +23 -0
  33. data/lib/wardrobe/plugins/coercible/refinements/object.rb +15 -0
  34. data/lib/wardrobe/plugins/coercible/refinements/set.rb +33 -0
  35. data/lib/wardrobe/plugins/coercible/refinements/string.rb +21 -0
  36. data/lib/wardrobe/plugins/coercible/refinements/symbol.rb +21 -0
  37. data/lib/wardrobe/plugins/coercible/refinements/time.rb +30 -0
  38. data/lib/wardrobe/plugins/coercible/refinements/unsupported_error.rb +11 -0
  39. data/lib/wardrobe/plugins/coercible.rb +52 -0
  40. data/lib/wardrobe/plugins/configurable/configurable_store.rb +26 -0
  41. data/lib/wardrobe/plugins/configurable.rb +40 -0
  42. data/lib/wardrobe/plugins/default.rb +33 -0
  43. data/lib/wardrobe/plugins/dirty_tracker.rb +66 -0
  44. data/lib/wardrobe/plugins/equality.rb +19 -0
  45. data/lib/wardrobe/plugins/html_initializer.rb +38 -0
  46. data/lib/wardrobe/plugins/immutable.rb +164 -0
  47. data/lib/wardrobe/plugins/ivy_presenter.rb +42 -0
  48. data/lib/wardrobe/plugins/json_initializer.rb +41 -0
  49. data/lib/wardrobe/plugins/nil_if_empty.rb +27 -0
  50. data/lib/wardrobe/plugins/nil_if_zero.rb +19 -0
  51. data/lib/wardrobe/plugins/optional_getter.rb +21 -0
  52. data/lib/wardrobe/plugins/optional_setter.rb +24 -0
  53. data/lib/wardrobe/plugins/presenter/refinements/array.rb +15 -0
  54. data/lib/wardrobe/plugins/presenter/refinements/hash.rb +15 -0
  55. data/lib/wardrobe/plugins/presenter/refinements/object.rb +15 -0
  56. data/lib/wardrobe/plugins/presenter/refinements/time.rb +19 -0
  57. data/lib/wardrobe/plugins/presenter/refinements.rb +6 -0
  58. data/lib/wardrobe/plugins/presenter.rb +25 -0
  59. data/lib/wardrobe/plugins/validation/block_handler.rb +83 -0
  60. data/lib/wardrobe/plugins/validation/class_methods.rb +13 -0
  61. data/lib/wardrobe/plugins/validation/deep_merge.rb +27 -0
  62. data/lib/wardrobe/plugins/validation/error_store.rb +27 -0
  63. data/lib/wardrobe/plugins/validation/instance_methods.rb +39 -0
  64. data/lib/wardrobe/plugins/validation/refinements/_size.rb +30 -0
  65. data/lib/wardrobe/plugins/validation/refinements/array.rb +26 -0
  66. data/lib/wardrobe/plugins/validation/refinements/date.rb +15 -0
  67. data/lib/wardrobe/plugins/validation/refinements/hash.rb +27 -0
  68. data/lib/wardrobe/plugins/validation/refinements/integer.rb +21 -0
  69. data/lib/wardrobe/plugins/validation/refinements/nil_class.rb +19 -0
  70. data/lib/wardrobe/plugins/validation/refinements/numeric.rb +31 -0
  71. data/lib/wardrobe/plugins/validation/refinements/object.rb +35 -0
  72. data/lib/wardrobe/plugins/validation/refinements/set.rb +25 -0
  73. data/lib/wardrobe/plugins/validation/refinements/string.rb +55 -0
  74. data/lib/wardrobe/plugins/validation/refinements/symbol.rb +26 -0
  75. data/lib/wardrobe/plugins/validation/refinements.rb +13 -0
  76. data/lib/wardrobe/plugins/validation/validation.rb +63 -0
  77. data/lib/wardrobe/plugins/validation/validation_error.rb +19 -0
  78. data/lib/wardrobe/plugins/validation/validaton_runner.rb +38 -0
  79. data/lib/wardrobe/plugins/validation/validator.rb +119 -0
  80. data/lib/wardrobe/plugins/validation.rb +28 -0
  81. data/lib/wardrobe/root_config.rb +31 -0
  82. data/lib/wardrobe/store.rb +62 -0
  83. data/lib/wardrobe/stores.rb +106 -0
  84. data/lib/wardrobe/version.rb +5 -0
  85. data/lib/wardrobe.rb +34 -0
  86. data/sandbox/Gemfile +5 -0
  87. data/sandbox/Gemfile.lock +52 -0
  88. data/sandbox/bench_mutable_coercion.rb +91 -0
  89. data/sandbox/bench_test_1.rb +50 -0
  90. data/sandbox/bench_test_2.rb +48 -0
  91. data/sandbox/bench_test_3.rb +92 -0
  92. data/sandbox/cnn_article_find.rb +20 -0
  93. data/sandbox/define_method_procs.rb +139 -0
  94. data/sandbox/hanami_validations.rb +40 -0
  95. data/sandbox/middleware_bench_test.rb +97 -0
  96. data/sandbox/middleware_bench_v2_test.rb +130 -0
  97. data/test/assertions.rb +22 -0
  98. data/test/test_helper.rb +37 -0
  99. data/test/unit/atrs_config_test.rb +33 -0
  100. data/test/unit/atrs_root_module_test.rb +19 -0
  101. data/test/unit/attribute_test.rb +44 -0
  102. data/test/unit/block_runner/array_test.rb +29 -0
  103. data/test/unit/block_setup_test.rb +41 -0
  104. data/test/unit/class_methods_test.rb +92 -0
  105. data/test/unit/create_class_from_hash_test.rb +28 -0
  106. data/test/unit/define_getter_test.rb +94 -0
  107. data/test/unit/define_setter_test.rb +0 -0
  108. data/test/unit/disable_coercion_test.rb +19 -0
  109. data/test/unit/inheritance_composition_test.rb +36 -0
  110. data/test/unit/method_override_test.rb +18 -0
  111. data/test/unit/method_polution_test.rb +48 -0
  112. data/test/unit/option_test.rb +17 -0
  113. data/test/unit/plugin_test.rb +12 -0
  114. data/test/unit/plugins/alias_setters_test.rb +24 -0
  115. data/test/unit/plugins/coercible/array_test.rb +79 -0
  116. data/test/unit/plugins/coercible/boolean_test.rb +68 -0
  117. data/test/unit/plugins/coercible/custom_class_test.rb +61 -0
  118. data/test/unit/plugins/coercible/date_test.rb +38 -0
  119. data/test/unit/plugins/coercible/date_time_test.rb +44 -0
  120. data/test/unit/plugins/coercible/float_test.rb +42 -0
  121. data/test/unit/plugins/coercible/hash_test.rb +62 -0
  122. data/test/unit/plugins/coercible/integer_test.rb +42 -0
  123. data/test/unit/plugins/coercible/nested_wardrobe_test.rb +63 -0
  124. data/test/unit/plugins/coercible/set_test.rb +49 -0
  125. data/test/unit/plugins/coercible/string_test.rb +36 -0
  126. data/test/unit/plugins/coercible/symbol_test.rb +30 -0
  127. data/test/unit/plugins/coercible/time_test.rb +43 -0
  128. data/test/unit/plugins/configurable_test.rb +64 -0
  129. data/test/unit/plugins/default_value_test.rb +78 -0
  130. data/test/unit/plugins/dirty_tracker_test.rb +78 -0
  131. data/test/unit/plugins/equality_test.rb +36 -0
  132. data/test/unit/plugins/html_initializer_test.rb +19 -0
  133. data/test/unit/plugins/immutable_test.rb +149 -0
  134. data/test/unit/plugins/ivy_presenter_test.rb +57 -0
  135. data/test/unit/plugins/json_initializer_test.rb +67 -0
  136. data/test/unit/plugins/nil_if_empty_test.rb +39 -0
  137. data/test/unit/plugins/nil_if_zero_test.rb +26 -0
  138. data/test/unit/plugins/presenter_test.rb +68 -0
  139. data/test/unit/plugins/validate/inheritance_test.rb +36 -0
  140. data/test/unit/plugins/validate/nested_model_test.rb +40 -0
  141. data/test/unit/plugins/validate/predicates/each_key_each_value_test.rb +34 -0
  142. data/test/unit/plugins/validate/predicates/each_test.rb +33 -0
  143. data/test/unit/plugins/validate/predicates/empty_test.rb +37 -0
  144. data/test/unit/plugins/validate/predicates/even_test.rb +33 -0
  145. data/test/unit/plugins/validate/predicates/excluded_from_test.rb +55 -0
  146. data/test/unit/plugins/validate/predicates/filled_test.rb +49 -0
  147. data/test/unit/plugins/validate/predicates/format_test.rb +28 -0
  148. data/test/unit/plugins/validate/predicates/gt_test.rb +36 -0
  149. data/test/unit/plugins/validate/predicates/gteq_test.rb +36 -0
  150. data/test/unit/plugins/validate/predicates/included_in_test.rb +55 -0
  151. data/test/unit/plugins/validate/predicates/lt_test.rb +36 -0
  152. data/test/unit/plugins/validate/predicates/lteq_test.rb +36 -0
  153. data/test/unit/plugins/validate/predicates/max_size_test.rb +43 -0
  154. data/test/unit/plugins/validate/predicates/min_size_test.rb +43 -0
  155. data/test/unit/plugins/validate/predicates/none_test.rb +49 -0
  156. data/test/unit/plugins/validate/predicates/odd_test.rb +33 -0
  157. data/test/unit/plugins/validate/predicates/size_range_test.rb +43 -0
  158. data/test/unit/plugins/validate/predicates/size_test.rb +43 -0
  159. data/test/unit/plugins/validate/predicates/type_test.rb +77 -0
  160. data/test/unit/plugins/validate/predicates_test.rb +73 -0
  161. data/test/unit/plugins/validate/validate_bang_test.rb +30 -0
  162. data/test/unit/store_test.rb +15 -0
  163. data/test/unit/stores_test.rb +18 -0
  164. data/wardrobe.gemspec +26 -0
  165. 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
@@ -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
@@ -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