dry-initializer 3.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/.codeclimate.yml +23 -0
  3. data/.gitignore +10 -0
  4. data/.rspec +4 -0
  5. data/.rubocop.yml +51 -0
  6. data/.travis.yml +28 -0
  7. data/CHANGELOG.md +883 -0
  8. data/Gemfile +29 -0
  9. data/Guardfile +5 -0
  10. data/LICENSE.txt +21 -0
  11. data/README.md +90 -0
  12. data/Rakefile +8 -0
  13. data/benchmarks/compare_several_defaults.rb +82 -0
  14. data/benchmarks/plain_options.rb +63 -0
  15. data/benchmarks/plain_params.rb +84 -0
  16. data/benchmarks/with_coercion.rb +71 -0
  17. data/benchmarks/with_defaults.rb +66 -0
  18. data/benchmarks/with_defaults_and_coercion.rb +59 -0
  19. data/dry-initializer.gemspec +20 -0
  20. data/lib/dry-initializer.rb +1 -0
  21. data/lib/dry/initializer.rb +61 -0
  22. data/lib/dry/initializer/builders.rb +7 -0
  23. data/lib/dry/initializer/builders/attribute.rb +81 -0
  24. data/lib/dry/initializer/builders/initializer.rb +61 -0
  25. data/lib/dry/initializer/builders/reader.rb +50 -0
  26. data/lib/dry/initializer/builders/signature.rb +32 -0
  27. data/lib/dry/initializer/config.rb +184 -0
  28. data/lib/dry/initializer/definition.rb +65 -0
  29. data/lib/dry/initializer/dispatchers.rb +112 -0
  30. data/lib/dry/initializer/dispatchers/build_nested_type.rb +59 -0
  31. data/lib/dry/initializer/dispatchers/check_type.rb +43 -0
  32. data/lib/dry/initializer/dispatchers/prepare_default.rb +40 -0
  33. data/lib/dry/initializer/dispatchers/prepare_ivar.rb +12 -0
  34. data/lib/dry/initializer/dispatchers/prepare_optional.rb +13 -0
  35. data/lib/dry/initializer/dispatchers/prepare_reader.rb +30 -0
  36. data/lib/dry/initializer/dispatchers/prepare_source.rb +28 -0
  37. data/lib/dry/initializer/dispatchers/prepare_target.rb +44 -0
  38. data/lib/dry/initializer/dispatchers/unwrap_type.rb +22 -0
  39. data/lib/dry/initializer/dispatchers/wrap_type.rb +27 -0
  40. data/lib/dry/initializer/dsl.rb +43 -0
  41. data/lib/dry/initializer/mixin.rb +15 -0
  42. data/lib/dry/initializer/mixin/local.rb +19 -0
  43. data/lib/dry/initializer/mixin/root.rb +10 -0
  44. data/lib/dry/initializer/struct.rb +40 -0
  45. data/lib/dry/initializer/undefined.rb +2 -0
  46. data/lib/tasks/benchmark.rake +41 -0
  47. data/lib/tasks/profile.rake +78 -0
  48. data/spec/attributes_spec.rb +38 -0
  49. data/spec/coercion_of_nil_spec.rb +25 -0
  50. data/spec/custom_dispatchers_spec.rb +35 -0
  51. data/spec/custom_initializer_spec.rb +30 -0
  52. data/spec/default_values_spec.rb +83 -0
  53. data/spec/definition_spec.rb +111 -0
  54. data/spec/invalid_default_spec.rb +13 -0
  55. data/spec/list_type_spec.rb +32 -0
  56. data/spec/missed_default_spec.rb +14 -0
  57. data/spec/nested_type_spec.rb +44 -0
  58. data/spec/optional_spec.rb +71 -0
  59. data/spec/options_tolerance_spec.rb +11 -0
  60. data/spec/public_attributes_utility_spec.rb +22 -0
  61. data/spec/reader_spec.rb +87 -0
  62. data/spec/repetitive_definitions_spec.rb +69 -0
  63. data/spec/several_assignments_spec.rb +41 -0
  64. data/spec/spec_helper.rb +22 -0
  65. data/spec/subclassing_spec.rb +49 -0
  66. data/spec/type_argument_spec.rb +35 -0
  67. data/spec/type_constraint_spec.rb +78 -0
  68. data/spec/value_coercion_via_dry_types_spec.rb +29 -0
  69. metadata +189 -0
data/Gemfile ADDED
@@ -0,0 +1,29 @@
1
+ source "https://rubygems.org"
2
+
3
+ # Specify your gem"s dependencies in dry-initializer.gemspec
4
+ gemspec
5
+
6
+ group :benchmarks do
7
+ if RUBY_VERSION < "2.4"
8
+ gem "activesupport", "< 5"
9
+ else
10
+ gem "activesupport"
11
+ end
12
+
13
+ gem "active_attr"
14
+ gem "anima"
15
+ gem "attr_extras"
16
+ gem "benchmark-ips", "~> 2.5"
17
+ gem "concord"
18
+ gem "fast_attributes"
19
+ gem "kwattr"
20
+ gem "ruby-prof", platform: :mri
21
+ gem "value_struct"
22
+ gem "values"
23
+ gem "virtus"
24
+ end
25
+
26
+ group :development, :test do
27
+ gem "pry", platform: :mri
28
+ gem "pry-byebug", platform: :mri
29
+ end
@@ -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
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2016-2017 Andrew Kozin (nepalez), Vladimir Kochnev (marshall-lee)
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.
@@ -0,0 +1,90 @@
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
+ [![Code Climate](https://codeclimate.com/github/dry-rb/dry-initializer/badges/gpa.svg)][codeclimate]
6
+ [![Test Coverage](https://codeclimate.com/github/dry-rb/dry-initializer/badges/coverage.svg)][coveralls]
7
+ [![Inline docs](http://inch-ci.org/github/dry-rb/dry-initializer.svg?branch=master)][inchpages]
8
+
9
+ [gem]: https://rubygems.org/gems/dry-initializer
10
+ [travis]: https://travis-ci.org/dry-rb/dry-initializer
11
+ [gemnasium]: https://gemnasium.com/dry-rb/dry-initializer
12
+ [codeclimate]: https://codeclimate.com/github/dry-rb/dry-initializer
13
+ [coveralls]: https://coveralls.io/r/dry-rb/dry-initializer
14
+ [inchpages]: http://inch-ci.org/github/dry-rb/dry-initializer
15
+ [docs]: http://dry-rb.org/gems/dry-initializer/
16
+ [benchmarks]: https://github.com/dry-rb/dry-initializer/wiki
17
+ [license]: http://opensource.org/licenses/MIT
18
+
19
+ DSL for building class initializer with params and options.
20
+
21
+ ## Installation
22
+
23
+ Add this line to your application's Gemfile:
24
+
25
+ ```ruby
26
+ gem 'dry-initializer'
27
+ ```
28
+
29
+ And then execute:
30
+
31
+ ```shell
32
+ $ bundle
33
+ ```
34
+
35
+ Or install it yourself as:
36
+
37
+ ```shell
38
+ $ gem install dry-initializer
39
+ ```
40
+
41
+ ## Synopsis
42
+
43
+ ```ruby
44
+ require 'dry-initializer'
45
+ require 'dry-types'
46
+
47
+ class User
48
+ extend Dry::Initializer
49
+
50
+ # Params of the initializer along with corresponding readers
51
+ param :name, proc(&:to_s)
52
+ param :role, default: -> { 'customer' }
53
+ # Options of the initializer along with corresponding readers
54
+ option :admin, default: -> { false }
55
+ option :vip, optional: true
56
+ end
57
+
58
+ # Defines the initializer with params and options
59
+ user = User.new 'Vladimir', 'admin', admin: true
60
+
61
+ # Defines readers for single attributes
62
+ user.name # => 'Vladimir'
63
+ user.role # => 'admin'
64
+ user.admin # => true
65
+ user.vip # => Dry::Initializer::UNDEFINED
66
+ ```
67
+
68
+ See full documentation on the [Dry project official site][docs]
69
+
70
+ ## Benchmarks
71
+
72
+ The `dry-initializer` is pretty fast for rubies 2.3+ [comparing to other libraries][benchmarks].
73
+
74
+ ## Compatibility
75
+
76
+ Tested under rubies [compatible to MRI 2.3+](.travis.yml).
77
+
78
+ ## Contributing
79
+
80
+ * [Fork the project](https://github.com/dry-rb/dry-initializer)
81
+ * Create your feature branch (`git checkout -b my-new-feature`)
82
+ * Add tests for it
83
+ * Commit your changes (`git commit -am '[UPDATE] Add some feature'`)
84
+ * Push to the branch (`git push origin my-new-feature`)
85
+ * Create a new Pull Request
86
+
87
+ ## License
88
+
89
+ The gem is available as open source under the terms of the [MIT License][license].
90
+
@@ -0,0 +1,8 @@
1
+ require "bundler/setup"
2
+ Bundler::GemHelper.install_tasks
3
+
4
+ require "rspec/core/rake_task"
5
+ RSpec::Core::RakeTask.new :default
6
+
7
+ load "lib/tasks/benchmark.rake"
8
+ load "lib/tasks/profile.rake"
@@ -0,0 +1,82 @@
1
+ Bundler.require(:benchmarks)
2
+
3
+ require "dry-initializer"
4
+ class WithoutDefaults
5
+ extend Dry::Initializer
6
+
7
+ param :foo
8
+ param :bar
9
+ param :baz
10
+ end
11
+
12
+ class WithOneDefault
13
+ extend Dry::Initializer
14
+
15
+ param :foo
16
+ param :bar
17
+ param :baz, default: proc { "BAZ" }
18
+ end
19
+
20
+ class WithTwoDefaults
21
+ extend Dry::Initializer
22
+
23
+ param :foo
24
+ param :bar, default: proc { "BAR" }
25
+ param :baz, default: proc { "BAZ" }
26
+ end
27
+
28
+ class WithThreeDefaults
29
+ extend Dry::Initializer
30
+
31
+ param :foo, default: proc { "FOO" }
32
+ param :bar, default: proc { "BAR" }
33
+ param :baz, default: proc { "BAZ" }
34
+ end
35
+
36
+ puts "Benchmark for various options"
37
+
38
+ Benchmark.ips do |x|
39
+ x.config time: 15, warmup: 10
40
+
41
+ x.report("without defaults") do
42
+ WithoutDefaults.new "FOO", "BAR", "BAZ"
43
+ end
44
+
45
+ x.report("with 0 of 1 default used") do
46
+ WithOneDefault.new "FOO", "BAR", "BAZ"
47
+ end
48
+
49
+ x.report("with 1 of 1 default used") do
50
+ WithOneDefault.new "FOO", "BAR"
51
+ end
52
+
53
+ x.report("with 0 of 2 defaults used") do
54
+ WithTwoDefaults.new "FOO", "BAR", "BAZ"
55
+ end
56
+
57
+ x.report("with 1 of 2 defaults used") do
58
+ WithTwoDefaults.new "FOO", "BAR"
59
+ end
60
+
61
+ x.report("with 2 of 2 defaults used") do
62
+ WithTwoDefaults.new "FOO"
63
+ end
64
+
65
+ x.report("with 0 of 3 defaults used") do
66
+ WithThreeDefaults.new "FOO", "BAR", "BAZ"
67
+ end
68
+
69
+ x.report("with 1 of 3 defaults used") do
70
+ WithThreeDefaults.new "FOO", "BAR"
71
+ end
72
+
73
+ x.report("with 2 of 3 defaults used") do
74
+ WithThreeDefaults.new "FOO"
75
+ end
76
+
77
+ x.report("with 3 of 3 defaults used") do
78
+ WithThreeDefaults.new
79
+ end
80
+
81
+ x.compare!
82
+ end
@@ -0,0 +1,63 @@
1
+ Bundler.require(:benchmarks)
2
+
3
+ require "dry-initializer"
4
+ class DryTest
5
+ extend Dry::Initializer[undefined: false]
6
+
7
+ option :foo
8
+ option :bar
9
+ end
10
+
11
+ class DryTestUndefined
12
+ extend Dry::Initializer
13
+
14
+ option :foo
15
+ option :bar
16
+ end
17
+
18
+ class PlainRubyTest
19
+ attr_reader :foo, :bar
20
+
21
+ def initialize(options = {})
22
+ @foo = options[:foo]
23
+ @bar = options[:bar]
24
+ end
25
+ end
26
+
27
+ require "anima"
28
+ class AnimaTest
29
+ include Anima.new(:foo, :bar)
30
+ end
31
+
32
+ require "kwattr"
33
+ class KwattrTest
34
+ kwattr :foo, :bar
35
+ end
36
+
37
+ puts "Benchmark for instantiation with plain options"
38
+
39
+ Benchmark.ips do |x|
40
+ x.config time: 15, warmup: 10
41
+
42
+ x.report("plain Ruby") do
43
+ PlainRubyTest.new foo: "FOO", bar: "BAR"
44
+ end
45
+
46
+ x.report("dry-initializer") do
47
+ DryTest.new foo: "FOO", bar: "BAR"
48
+ end
49
+
50
+ x.report("dry-initializer (with UNDEFINED)") do
51
+ DryTestUndefined.new foo: "FOO", bar: "BAR"
52
+ end
53
+
54
+ x.report("anima") do
55
+ AnimaTest.new foo: "FOO", bar: "BAR"
56
+ end
57
+
58
+ x.report("kwattr") do
59
+ KwattrTest.new foo: "FOO", bar: "BAR"
60
+ end
61
+
62
+ x.compare!
63
+ end
@@ -0,0 +1,84 @@
1
+ Bundler.require(:benchmarks)
2
+
3
+ require "dry-initializer"
4
+ class DryTest
5
+ extend Dry::Initializer[undefined: false]
6
+
7
+ param :foo
8
+ param :bar
9
+ end
10
+
11
+ class DryTestUndefined
12
+ extend Dry::Initializer
13
+
14
+ param :foo
15
+ param :bar
16
+ end
17
+
18
+ class PlainRubyTest
19
+ attr_reader :foo, :bar
20
+
21
+ def initialize(foo, bar)
22
+ @foo = foo
23
+ @bar = bar
24
+ end
25
+ end
26
+
27
+ StructTest = Struct.new(:foo, :bar)
28
+
29
+ require "concord"
30
+ class ConcordTest
31
+ include Concord.new(:foo, :bar)
32
+ end
33
+
34
+ require "values"
35
+ ValueTest = Value.new(:foo, :bar)
36
+
37
+ require "value_struct"
38
+ ValueStructTest = ValueStruct.new(:foo, :bar)
39
+
40
+ require "attr_extras"
41
+ class AttrExtrasText
42
+ attr_initialize :foo, :bar
43
+ attr_reader :foo, :bar
44
+ end
45
+
46
+ puts "Benchmark for instantiation with plain params"
47
+
48
+ Benchmark.ips do |x|
49
+ x.config time: 15, warmup: 10
50
+
51
+ x.report("plain Ruby") do
52
+ PlainRubyTest.new "FOO", "BAR"
53
+ end
54
+
55
+ x.report("Core Struct") do
56
+ StructTest.new "FOO", "BAR"
57
+ end
58
+
59
+ x.report("values") do
60
+ ValueTest.new "FOO", "BAR"
61
+ end
62
+
63
+ x.report("value_struct") do
64
+ ValueStructTest.new "FOO", "BAR"
65
+ end
66
+
67
+ x.report("dry-initializer") do
68
+ DryTest.new "FOO", "BAR"
69
+ end
70
+
71
+ x.report("dry-initializer (with UNDEFINED)") do
72
+ DryTestUndefined.new "FOO", "BAR"
73
+ end
74
+
75
+ x.report("concord") do
76
+ ConcordTest.new "FOO", "BAR"
77
+ end
78
+
79
+ x.report("attr_extras") do
80
+ AttrExtrasText.new "FOO", "BAR"
81
+ end
82
+
83
+ x.compare!
84
+ end
@@ -0,0 +1,71 @@
1
+ Bundler.require(:benchmarks)
2
+
3
+ require "dry-initializer"
4
+ class DryTest
5
+ extend Dry::Initializer[undefined: false]
6
+
7
+ option :foo, proc(&:to_s)
8
+ option :bar, proc(&:to_s)
9
+ end
10
+
11
+ class DryTestUndefined
12
+ extend Dry::Initializer
13
+
14
+ option :foo, proc(&:to_s)
15
+ option :bar, proc(&:to_s)
16
+ end
17
+
18
+ class PlainRubyTest
19
+ attr_reader :foo, :bar
20
+
21
+ def initialize(options)
22
+ @foo = options[:foo].to_s
23
+ @bar = options[:bar].to_s
24
+ end
25
+ end
26
+
27
+ require "virtus"
28
+ class VirtusTest
29
+ include Virtus.model
30
+
31
+ attribute :foo, String
32
+ attribute :bar, String
33
+ end
34
+
35
+ require "fast_attributes"
36
+ class FastAttributesTest
37
+ extend FastAttributes
38
+
39
+ define_attributes initialize: true do
40
+ attribute :foo, String
41
+ attribute :bar, String
42
+ end
43
+ end
44
+
45
+ puts "Benchmark for instantiation with coercion"
46
+
47
+ Benchmark.ips do |x|
48
+ x.config time: 15, warmup: 10
49
+
50
+ x.report("plain Ruby") do
51
+ PlainRubyTest.new foo: "FOO", bar: "BAR"
52
+ end
53
+
54
+ x.report("dry-initializer") do
55
+ DryTest.new foo: "FOO", bar: "BAR"
56
+ end
57
+
58
+ x.report("dry-initializer (with UNDEFINED)") do
59
+ DryTestUndefined.new foo: "FOO", bar: "BAR"
60
+ end
61
+
62
+ x.report("virtus") do
63
+ VirtusTest.new foo: "FOO", bar: "BAR"
64
+ end
65
+
66
+ x.report("fast_attributes") do
67
+ FastAttributesTest.new foo: "FOO", bar: "BAR"
68
+ end
69
+
70
+ x.compare!
71
+ end