dry-initializer 0.0.1

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 (47) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +15 -0
  3. data/.gitignore +9 -0
  4. data/.rspec +3 -0
  5. data/.rubocop.yml +91 -0
  6. data/.travis.yml +16 -0
  7. data/CHANGELOG.md +3 -0
  8. data/Gemfile +25 -0
  9. data/Guardfile +5 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +444 -0
  12. data/Rakefile +47 -0
  13. data/benchmarks/options.rb +54 -0
  14. data/benchmarks/params.rb +73 -0
  15. data/benchmarks/params_vs_options.rb +35 -0
  16. data/benchmarks/several_defaults.rb +82 -0
  17. data/benchmarks/with_defaults.rb +55 -0
  18. data/benchmarks/with_types.rb +62 -0
  19. data/benchmarks/with_types_and_defaults.rb +48 -0
  20. data/benchmarks/without_options.rb +52 -0
  21. data/dry-initializer.gemspec +19 -0
  22. data/lib/dry-initializer.rb +1 -0
  23. data/lib/dry/initializer.rb +53 -0
  24. data/lib/dry/initializer/argument.rb +96 -0
  25. data/lib/dry/initializer/arguments.rb +85 -0
  26. data/lib/dry/initializer/builder.rb +33 -0
  27. data/lib/dry/initializer/errors.rb +13 -0
  28. data/lib/dry/initializer/errors/existing_argument_error.rb +5 -0
  29. data/lib/dry/initializer/errors/invalid_default_value_error.rb +6 -0
  30. data/lib/dry/initializer/errors/invalid_type_error.rb +6 -0
  31. data/lib/dry/initializer/errors/key_error.rb +5 -0
  32. data/lib/dry/initializer/errors/missed_default_value_error.rb +5 -0
  33. data/lib/dry/initializer/errors/type_error.rb +5 -0
  34. data/spec/dry/base_spec.rb +21 -0
  35. data/spec/dry/default_nil_spec.rb +17 -0
  36. data/spec/dry/default_values_spec.rb +39 -0
  37. data/spec/dry/dry_type_spec.rb +25 -0
  38. data/spec/dry/invalid_default_spec.rb +13 -0
  39. data/spec/dry/invalid_type_spec.rb +13 -0
  40. data/spec/dry/missed_default_spec.rb +14 -0
  41. data/spec/dry/poro_type_spec.rb +33 -0
  42. data/spec/dry/proc_type_spec.rb +25 -0
  43. data/spec/dry/reader_spec.rb +22 -0
  44. data/spec/dry/repetitive_definitions_spec.rb +49 -0
  45. data/spec/dry/subclassing_spec.rb +24 -0
  46. data/spec/spec_helper.rb +15 -0
  47. metadata +149 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9c8a4ecc08b8c494713d17b0af1191257c6eae96
4
+ data.tar.gz: 5019f46f22eb9c37904b42f67620d2f5d2ee747f
5
+ SHA512:
6
+ metadata.gz: 278434f8949064eb547f6c481e94bff71080eda6c6ff95586cc647259ba842301dc850022c6fd88af80ac37985394829a9c93788917b7755ef6011a0c595c1bb
7
+ data.tar.gz: 6afa297f5e3a180d79366fb14750b787a7dc9b920118da9a0f806f37f1c3dcec1d0d6e14767b23dae284ff962099ea5aba0bd486607352a8825f1298f59eb204
data/.codeclimate.yml ADDED
@@ -0,0 +1,15 @@
1
+ ---
2
+ engines:
3
+ rubocop:
4
+ enabled: true
5
+ duplication:
6
+ enabled: true
7
+ config:
8
+ languages:
9
+ - ruby
10
+ exclude_paths:
11
+ - "benchmarks/**/*"
12
+ - "spec/**/*"
13
+ ratings:
14
+ paths:
15
+ - "lib/**/*"
data/.gitignore ADDED
@@ -0,0 +1,9 @@
1
+ /.bundle/
2
+ /.yardoc
3
+ /Gemfile.lock
4
+ /_yardoc/
5
+ /coverage/
6
+ /doc/
7
+ /pkg/
8
+ /spec/reports/
9
+ /tmp/
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --format documentation
2
+ --color
3
+ --require spec_helper
data/.rubocop.yml ADDED
@@ -0,0 +1,91 @@
1
+ ---
2
+ AllCops:
3
+ DisplayCopNames: true
4
+ DisplayStyleGuide: true
5
+ StyleGuideCopsOnly: true
6
+ TargetRubyVersion: 2.2
7
+
8
+ Lint/HandleExceptions:
9
+ Exclude:
10
+ - '**/*_spec.rb'
11
+
12
+ Lint/RescueException:
13
+ Exclude:
14
+ - '**/*_spec.rb'
15
+
16
+ Metrics/LineLength:
17
+ Max: 80
18
+ Exclude:
19
+ - 'spec/**/*.rb'
20
+
21
+ Style/AccessorMethodName:
22
+ Exclude:
23
+ - '**/*_spec.rb'
24
+
25
+ Style/Alias:
26
+ EnforcedStyle: prefer_alias_method
27
+
28
+ Style/AsciiComments:
29
+ Enabled: false
30
+
31
+ Style/CaseEquality:
32
+ Enabled: false
33
+
34
+ Style/ClassAndModuleChildren:
35
+ Enabled: false
36
+
37
+ Style/Documentation:
38
+ Enabled: false
39
+
40
+ Style/DoubleNegation:
41
+ Enabled: false
42
+
43
+ Style/EmptyLinesAroundClassBody:
44
+ Enabled: false
45
+
46
+ Style/EmptyLinesAroundModuleBody:
47
+ Enabled: false
48
+
49
+ Style/EmptyLineBetweenDefs:
50
+ Enabled: false
51
+
52
+ Style/FileName:
53
+ Enabled: false
54
+
55
+ Style/ModuleFunction:
56
+ Enabled: false
57
+
58
+ Style/RaiseArgs:
59
+ EnforcedStyle: compact
60
+
61
+ Style/Semicolon:
62
+ Exclude:
63
+ - '**/*_spec.rb'
64
+
65
+ Style/SignalException:
66
+ EnforcedStyle: semantic
67
+
68
+ Style/SingleLineBlockParams:
69
+ Enabled: false
70
+
71
+ Style/SingleLineMethods:
72
+ Exclude:
73
+ - '**/*_spec.rb'
74
+
75
+ Style/SpaceBeforeFirstArg:
76
+ Enabled: false
77
+
78
+ Style/SpecialGlobalVars:
79
+ Exclude:
80
+ - '**/Gemfile'
81
+ - '**/*.gemspec'
82
+
83
+ Style/StringLiterals:
84
+ EnforcedStyle: double_quotes
85
+
86
+ Style/StringLiteralsInInterpolation:
87
+ EnforcedStyle: double_quotes
88
+
89
+ Style/TrivialAccessors:
90
+ Exclude:
91
+ - '**/*_spec.rb'
data/.travis.yml ADDED
@@ -0,0 +1,16 @@
1
+ ---
2
+ language: ruby
3
+ before_install: gem install bundler -v 1.11.2
4
+ cache: bundler
5
+ script: bundle exec rspec
6
+ rvm:
7
+ - '2.2'
8
+ - '2.3.0'
9
+ - rbx-2
10
+ - ruby-head
11
+ # - jruby-9
12
+ # - jruby-head
13
+ matrix:
14
+ allow_failures:
15
+ - rvm: ruby-head
16
+ # - rvm: jruby-head
data/CHANGELOG.md ADDED
@@ -0,0 +1,3 @@
1
+ ## v0.0.1 2016-04-09
2
+
3
+ First public release
data/Gemfile ADDED
@@ -0,0 +1,25 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem"s dependencies in dry-initializer.gemspec
4
+ gemspec
5
+
6
+ gem "dry-types", git: "https://github.com/dryrb/dry-types", branch: "master"
7
+
8
+ group :benchmarks do
9
+ gem "benchmark-ips", "~> 2.5"
10
+
11
+ gem "active_attr"
12
+ gem "anima"
13
+ gem "attr_extras"
14
+ gem "concord"
15
+ gem "fast_attributes"
16
+ gem "kwattr"
17
+ gem "value_struct"
18
+ gem "values"
19
+ gem "virtus"
20
+ end
21
+
22
+ group :development, :test do
23
+ gem "pry", platform: :mri
24
+ gem "pry-byebug", platform: :mri
25
+ end
data/Guardfile ADDED
@@ -0,0 +1,5 @@
1
+ guard :rspec, cmd: "bundle exec rspec" do
2
+ watch(%r{^spec/.+_spec\.rb$})
3
+ watch(%r{^spec/(spec_helper|support)}) { "spec" }
4
+ watch(%r{^lib/.+}) { "spec" }
5
+ end
data/LICENSE.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016 Andrew Kozin (aka nepalez)
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in
13
+ all copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
21
+ THE SOFTWARE.
data/README.md ADDED
@@ -0,0 +1,444 @@
1
+ # dry-initializer [![Join the chat at https://gitter.im/dry-rb/chat](https://badges.gitter.im/Join%20Chat.svg)](https://gitter.im/dry-rb/chat)
2
+
3
+ [![Gem Version](https://badge.fury.io/rb/dry-initializer.svg)][gem]
4
+ [![Build Status](https://travis-ci.org/dry-rb/dry-initializer.svg?branch=master)][travis]
5
+ [![Dependency Status](https://gemnasium.com/dry-rb/dry-initializer.svg)][gemnasium]
6
+ [![Code Climate](https://codeclimate.com/github/dry-rb/dry-initializer/badges/gpa.svg)][codeclimate]
7
+ [![Test Coverage](https://codeclimate.com/github/dry-rb/dry-initializer/badges/coverage.svg)][coveralls]
8
+ [![Inline docs](http://inch-ci.org/github/dry-rb/dry-initializer.svg?branch=master)][inchpages]
9
+
10
+ [gem]: https://rubygems.org/gems/dry-initializer
11
+ [travis]: https://travis-ci.org/dry-rb/dry-initializer
12
+ [gemnasium]: https://gemnasium.com/dry-rb/dry-initializer
13
+ [codeclimate]: https://codeclimate.com/github/dry-rb/dry-initializer
14
+ [coveralls]: https://coveralls.io/r/dry-rb/dry-initializer
15
+ [inchpages]: http://inch-ci.org/github/dry-rb/dry-initializer
16
+
17
+ DSL for building class initializer with params and options.
18
+
19
+ ## Installation
20
+
21
+ Add this line to your application's Gemfile:
22
+
23
+ ```ruby
24
+ gem 'dry-initializer'
25
+ ```
26
+
27
+ And then execute:
28
+
29
+ ```shell
30
+ $ bundle
31
+ ```
32
+
33
+ Or install it yourself as:
34
+
35
+ ```shell
36
+ $ gem install dry-initializer
37
+ ```
38
+
39
+ ## Synopsis
40
+
41
+ ```ruby
42
+ require 'dry-initializer'
43
+
44
+ class User
45
+ extend Dry::Initializer
46
+
47
+ # Params of the initializer along with corresponding readers
48
+ param :name, type: String
49
+ param :role, default: proc { 'customer' }
50
+ # Options of the initializer along with corresponding readers
51
+ option :admin, default: proc { false }
52
+ end
53
+
54
+ # Defines the initializer with params and options
55
+ user = User.new 'Vladimir', 'admin', admin: true
56
+
57
+ # Defines readers for single attributes
58
+ user.name # => 'Vladimir'
59
+ user.role # => 'admin'
60
+ user.admin # => true
61
+ ```
62
+
63
+ This is pretty the same as:
64
+
65
+ ```ruby
66
+ class User
67
+ attr_reader :name, :type, :admin
68
+
69
+ def initializer(name, type = 'customer', admin: false)
70
+ @name = name
71
+ @type = type
72
+ @admin = admin
73
+
74
+ fail TypeError unless String === @name
75
+ end
76
+ end
77
+ ```
78
+
79
+ ### Params and Options
80
+
81
+ Use `param` to define plain argument:
82
+
83
+ ```ruby
84
+ class User
85
+ extend Dry::Initializer
86
+
87
+ param :name
88
+ param :email
89
+ end
90
+
91
+ user = User.new 'Andrew', 'andrew@email.com'
92
+ user.name # => 'Andrew'
93
+ user.email # => 'andrew@email.com'
94
+ ```
95
+
96
+ Use `option` to define named (hash) argument:
97
+
98
+ ```ruby
99
+ class User
100
+ extend Dry::Initializer
101
+
102
+ option :name
103
+ option :email
104
+ end
105
+
106
+ user = User.new email: 'andrew@email.com', name: 'Andrew'
107
+ user.name # => 'Andrew'
108
+ user.email # => 'andrew@email.com'
109
+ ```
110
+
111
+ All names should be unique:
112
+
113
+ ```ruby
114
+ class User
115
+ extend Dry::Initializer
116
+
117
+ param :name
118
+ option :name # => raises #<SyntaxError ...>
119
+ end
120
+ ```
121
+
122
+ ### Default Values
123
+
124
+ By default both params and options are mandatory. Use `:default` key to make them optional:
125
+
126
+ ```ruby
127
+ class User
128
+ extend Dry::Initializer
129
+
130
+ param :name, default: proc { 'Unknown user' }
131
+ option :email, default: proc { 'unknown@example.com' }
132
+ end
133
+
134
+ user = User.new
135
+ user.name # => 'Unknown user'
136
+ user.email # => 'unknown@example.com'
137
+
138
+ user = User.new 'Vladimir', email: 'vladimir@example.com'
139
+ user.name # => 'Vladimir'
140
+ user.email # => 'vladimir@example.com'
141
+ ```
142
+
143
+ Set `nil` as a default value explicitly:
144
+
145
+ ```ruby
146
+ class User
147
+ extend Dry::Initializer
148
+
149
+ param :name
150
+ option :email, default: proc { nil }
151
+ end
152
+
153
+ user = User.new 'Andrew'
154
+ user.email # => nil
155
+
156
+ user = User.new
157
+ # => #<ArgumentError ...>
158
+ ```
159
+
160
+ You **must** wrap default values into procs.
161
+
162
+ If you need to **assign** proc as a default value, wrap it to another one:
163
+
164
+ ```ruby
165
+ class User
166
+ extend Dry::Initializer
167
+
168
+ param :name_proc, default: proc { proc { 'Unknown user' } }
169
+ end
170
+
171
+ user = User.new
172
+ user.name_proc.call # => 'Unknown user'
173
+ ```
174
+
175
+ Proc will be executed in a scope of new instance. You can refer to other arguments:
176
+
177
+ ```ruby
178
+ class User
179
+ extend Dry::Initializer
180
+
181
+ param :name
182
+ param :email, default: proc { "#{name.downcase}@example.com" }
183
+ end
184
+
185
+ user = User.new 'Andrew'
186
+ user.email # => 'andrew@example.com'
187
+ ```
188
+
189
+ **Warning**: when using lambdas instead of procs, don't forget an argument, required by [instance_eval][instance_eval] (you can skip in in a proc).
190
+
191
+ ```ruby
192
+ class User
193
+ extend Dry::Initializer
194
+
195
+ param :name, default: -> (obj) { 'Dude' }
196
+ end
197
+ ```
198
+
199
+ [instance_eval]: http://ruby-doc.org/core-2.2.0/BasicObject.html#method-i-instance_eval
200
+
201
+ ### Order of Declarations
202
+
203
+ You cannot define required parameter after optional ones. The following example raises `SyntaxError` exception:
204
+
205
+ ```ruby
206
+ class User
207
+ extend Dry::Initializer
208
+
209
+ param :name, default: proc { 'Unknown name' }
210
+ param :email # => #<SyntaxError ...>
211
+ end
212
+ ```
213
+
214
+ ### Type Constraints
215
+
216
+ To set type constraint use `:type` key:
217
+
218
+ ```ruby
219
+ class User
220
+ extend Dry::Initializer
221
+
222
+ param :name, type: String
223
+ end
224
+
225
+ user = User.new 'Andrew'
226
+ user.name # => 'Andrew'
227
+
228
+ user = User.new :andrew
229
+ # => #<TypeError ...>
230
+ ```
231
+
232
+ You can use plain Ruby classes and modules as type constraint (see above), or use [dry-types][dry-types]:
233
+
234
+ ```ruby
235
+ class User
236
+ extend Dry::Initializer
237
+
238
+ param :name, type: Dry::Types::Coercion::String
239
+ end
240
+ ```
241
+
242
+ Or you can define custom constraint as a proc:
243
+
244
+ ```ruby
245
+ class User
246
+ extend Dry::Initializer
247
+
248
+ param :name, type: proc { |v| raise TypeError if String === v }
249
+ end
250
+
251
+ user = User.new name: 'Andrew'
252
+ # => #<TypeError ...>
253
+ ```
254
+
255
+ [dry-types]: https://github.com/dryrb/dry-types
256
+
257
+ ### Reader
258
+
259
+ By default `attr_reader` is defined for every param and option.
260
+
261
+ To skip the reader, use `reader: false`:
262
+
263
+ ```ruby
264
+ class User
265
+ extend Dry::Initializer
266
+
267
+ param :name
268
+ param :email, reader: false
269
+ end
270
+
271
+ user = User.new 'Luke', 'luke@example.com'
272
+ user.name # => 'Luke'
273
+
274
+ user.email # => #<NoMethodError ...>
275
+ user.instance_variable_get :@email # => 'luke@example.com'
276
+ ```
277
+
278
+ No writers are defined. Define them using pure ruby `attr_writer` when necessary.
279
+
280
+ ### Subclassing
281
+
282
+ Subclassing preserves all definitions being made inside a superclass:
283
+
284
+ ```ruby
285
+ class User
286
+ extend Dry::Initializer
287
+
288
+ param :name
289
+ end
290
+
291
+ class Employee < User
292
+ param :position
293
+ end
294
+
295
+ employee = Employee.new('John', 'supercargo')
296
+ employee.name # => 'John'
297
+ employee.position # => 'supercargo'
298
+ ```
299
+
300
+ ## Benchmarks
301
+
302
+ ### Various usages of Dry::Initializer
303
+
304
+ [At first][benchmark-options] we compared initializers for case of no-opts with those with default values and time constraints (for every single argument):
305
+
306
+ ```
307
+ no opts: 1186020.0 i/s
308
+ with 2 types: 744825.4 i/s - 1.59x slower
309
+ with 2 defaults: 644170.0 i/s - 1.84x slower
310
+ with defaults and types: 534200.0 i/s - 2.22x slower
311
+ ```
312
+
313
+ Defaults are slow. The more defaults you add the slower the instantiation. Let's [add details][benchmark_several_defaults]:
314
+
315
+ ```
316
+ without defaults: 3412165.6 i/s
317
+ with 0 of 1 default used: 1816946.6 i/s - 1.88x slower
318
+ with 0 of 2 defaults used: 1620908.5 i/s - 2.11x slower
319
+ with 0 of 3 defaults used: 1493410.6 i/s - 2.28x slower
320
+ with 1 of 1 default used: 797438.8 i/s - 4.28x slower
321
+ with 1 of 2 defaults used: 754533.4 i/s - 4.52x slower
322
+ with 1 of 3 defaults used: 716828.9 i/s - 4.76x slower
323
+ with 2 of 2 defaults used: 622569.8 i/s - 5.48x slower
324
+ with 2 of 3 defaults used: 604062.1 i/s - 5.65x slower
325
+ with 3 of 3 defaults used: 533233.4 i/s - 6.40x slower
326
+ ```
327
+
328
+ A single declaration of default values costs about 90% additional time. Its usage costs full 300%, and every next default adds 80% more.
329
+
330
+ Avoid defaults when possible!
331
+
332
+ ### Comparison to Other Gems
333
+
334
+ We also compared initializers provided by gems from the [post 'Con-Struct Attibutes' by Jan Lelis][con-struct]:
335
+
336
+ * [active_attr][active_attr]
337
+ * [anima][anima]
338
+ * [attr_extras][attr_extras]
339
+ * [concord][concord]
340
+ * [fast_attr][fast_attr]
341
+ * [kwattr][kwattr]
342
+ * [value_struct][value_struct]
343
+ * [values][values]
344
+ * [virtus][virtus]
345
+
346
+ [con-struct]: http://idiosyncratic-ruby.com/18-con-struct-attributes.html
347
+ [active_attr]: https://github.com/cgriego/active_attr
348
+ [anima]: https://github.com/mbj/anima
349
+ [attr_extras]: https://github.com/barsoom/attr_extras
350
+ [concord]: https://github.com/mbj/concord
351
+ [fast_attr]: https://github.com/applift/fast_attributes
352
+ [kwattr]: https://github.com/etiennebarrie/kwattr
353
+ [value_struct]: https://github.com/janlelis/value_struct
354
+ [values]: https://github.com/tcrayford/values
355
+ [virtus]: https://github.com/solnic/virtus
356
+
357
+ Because the gems has their restrictions, in benchmarks we tested only comparable examples.
358
+ A corresponding code in plain Ruby was taken for comparison.
359
+
360
+ ### Without Options
361
+
362
+ Results for [the examples][benchmark_without_options]
363
+
364
+ Benchmark for instantiation of plain arguments (params):
365
+
366
+ ```
367
+ Core Struct: 4520294.5 i/s
368
+ value_struct: 4479181.2 i/s - same-ish: difference falls within error
369
+ plain Ruby: 4161762.2 i/s - 1.09x slower
370
+ dry-initializer: 3981426.3 i/s - 1.14x slower
371
+ concord: 1372696.9 i/s - 3.29x slower
372
+ values: 637396.9 i/s - 7.09x slower
373
+ attr_extras: 556342.9 i/s - 8.13x slower
374
+ ```
375
+
376
+ Benchmark for instantiation of named arguments (options)
377
+
378
+ ```
379
+ dry-initializer: 1020257.3 i/s
380
+ plain Ruby: 1009705.8 i/s - same-ish: difference falls within error
381
+ kwattr: 394574.0 i/s - 2.59x slower
382
+ anima: 377387.8 i/s - 2.70x slower
383
+ ```
384
+
385
+ ### With Default Values
386
+
387
+ Results for [the examples][benchmark_with_defaults]
388
+
389
+ ```
390
+ plain Ruby: 3534979.5 i/s
391
+ dry-initializer: 657308.4 i/s - 5.38x slower
392
+ kwattr: 581691.0 i/s - 6.08x slower
393
+ active_attr: 309211.0 i/s - 11.43x slower
394
+ ```
395
+
396
+ ### With Type Constraints
397
+
398
+ Results for [the examples][benchmark_with_types]
399
+
400
+ ```
401
+ plain Ruby: 951574.7 i/s
402
+ dry-initializer: 701676.7 i/s - 1.36x slower
403
+ fast_attributes: 562646.4 i/s - 1.69x slower
404
+ virtus: 143113.3 i/s - 6.65x slower
405
+ ```
406
+
407
+ ### With Default Values and Type Constraints
408
+
409
+ Results for [the examples][benchmark_with_types_and_defaults]
410
+
411
+ ```
412
+ plain Ruby: 2887933.4 i/s
413
+ dry-initializer: 532508.0 i/s - 5.42x slower
414
+ virtus: 183347.1 i/s - 15.75x slower
415
+ ```
416
+
417
+ To recap, `dry-initializer` is a fastest DSL for rubies 2.2+ except for cases when core `Struct` is sufficient.
418
+
419
+ [benchmark-options]: https://github.com/dryrb/dry-initializer/blob/master/benchmarks/options.rb
420
+ [benchmark_several_defaults]: https://github.com/dryrb/dry-initializer/blob/master/benchmarks/several_defaults.rb
421
+ [benchmark_without_options]: https://github.com/dryrb/dry-initializer/blob/master/benchmarks/without_options.rb
422
+ [benchmark_with_defaults]: https://github.com/dryrb/dry-initializer/blob/master/benchmarks/with_defaults.rb
423
+ [benchmark_with_types]: https://github.com/dryrb/dry-initializer/blob/master/benchmarks/with_types.rb
424
+ [benchmark_with_types_and_defaults]: https://github.com/dryrb/dry-initializer/blob/master/benchmarks/with_types_and_defaults.rb
425
+ [benchmark_params]: https://github.com/dryrb/dry-initializer/blob/master/benchmarks/params.rb
426
+
427
+ ## Compatibility
428
+
429
+ Tested under rubies [compatible to MRI 2.2+](.travis.yml).
430
+
431
+ ## Contributing
432
+
433
+ * Read the [STYLEGUIDE](config/metrics/STYLEGUIDE)
434
+ * [Fork the project](https://github.com/nepalez/query_builder)
435
+ * Create your feature branch (`git checkout -b my-new-feature`)
436
+ * Add tests for it
437
+ * Commit your changes (`git commit -am '[UPDATE] Add some feature'`)
438
+ * Push to the branch (`git push origin my-new-feature`)
439
+ * Create a new Pull Request
440
+
441
+ ## License
442
+
443
+ The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
444
+