kwattr 0.2.0 → 0.3.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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: f3f52b74e112e1a8cd7ee56f91323339731eafd4
4
- data.tar.gz: a763e6223e15158fe8062a801b2cfe78309adb54
3
+ metadata.gz: 7a5f6547c53d33b561a7706e2f35f265cdfc47b9
4
+ data.tar.gz: 519b1520e6d69054a81c8de80529982a0bc3c066
5
5
  SHA512:
6
- metadata.gz: 2dc7f95df0dd1ef9dbe54f4d4900194ab11c85b6374811df4157c0a09aeb073a4a34409fcdf2ba4cfad48f373f916fb1cd608ab74ce4a157c0e276078b891251
7
- data.tar.gz: d63c3abdfc609d1441847176aac5ee6ee0f8169fe741b68de74c10f2489657602f29d794f2968179c5914a2435ffa4be2614630130c9a3cec714776d7510676a
6
+ metadata.gz: 1c81b0f64cb6875c4dd96582199348b8580e490d2e77524640ec1b4b6e1dea265bb660387ed9389dfc09be630c68cce22f3616c2cc0512d19c698e54ad09a26c
7
+ data.tar.gz: 34975ee6fac582fc340b9d937ca432e8f35ac8d1d88b1996bf432370f9e6e814a1b31a501177a82e018e88b4a4cc47f1071cbf63b2b58be1d18342368d92450e
data/README.md CHANGED
@@ -57,11 +57,15 @@ FooProtected.protected_instance_methods # => [:foo]
57
57
  ### subclass
58
58
 
59
59
  ```ruby
60
- class Bar < Foo
60
+ class Foo
61
+ kwattr :foo
62
+ end
63
+
64
+ class FooWithBar < Foo
61
65
  kwattr :bar
62
66
  end
63
67
 
64
- Bar.new(bar: 42) # => #<Bar @foo=42, @bar=42>
68
+ FooWithBar.new(foo: 42, bar: 21) # => #<FooWithBar @foo=42, @bar=21>
65
69
  ```
66
70
 
67
71
  ### include
data/Rakefile CHANGED
@@ -13,4 +13,8 @@ task :examples do
13
13
  ruby "test.rb"
14
14
  end
15
15
 
16
- task :default => [:examples, :spec]
16
+ task :benchmark do
17
+ ruby "benchmark.rb"
18
+ end
19
+
20
+ task :default => [:examples, :spec, :benchmark]
@@ -0,0 +1,124 @@
1
+ require 'benchmark/ips'
2
+ require 'kwattr'
3
+ require_relative 'spec/examples'
4
+
5
+ class ROneAttr
6
+ attr_reader :foo
7
+
8
+ def initialize(foo:)
9
+ @foo = foo
10
+ end
11
+ end
12
+
13
+ class ROneAttrDefault
14
+ DEFAULT_FOO = 42
15
+
16
+ attr_reader :foo
17
+
18
+ def initialize(foo: DEFAULT_FOO)
19
+ @foo = foo
20
+ end
21
+ end
22
+
23
+ class ROneAttrOnePositional
24
+ attr_reader :foo, :bar
25
+
26
+ def initialize(bar, foo:)
27
+ @foo = foo
28
+ @bar = bar
29
+ end
30
+ end
31
+
32
+ class RTwoAttrs
33
+ attr_reader :foo, :bar
34
+
35
+ def initialize(foo:, bar:)
36
+ @foo = foo
37
+ @bar = bar
38
+ end
39
+ end
40
+
41
+ class RTwoAttrsDefaults
42
+ DEFAULT_FOO = 42
43
+ DEFAULT_BAR = 21
44
+
45
+ attr_reader :foo, :bar
46
+
47
+ def initialize(foo: DEFAULT_FOO, bar: DEFAULT_BAR)
48
+ @foo = foo
49
+ @bar = bar
50
+ end
51
+ end
52
+
53
+ class RTwoAttrsOneDefault
54
+ DEFAULT_BAR = 21
55
+
56
+ attr_reader :foo, :bar
57
+
58
+ def initialize(foo:, bar: DEFAULT_BAR)
59
+ @foo = foo
60
+ @bar = bar
61
+ end
62
+ end
63
+
64
+ class RTwoAttrsOnePos
65
+ attr_reader :foo, :bar, :baz
66
+
67
+ def initialize(baz, foo:, bar:)
68
+ @foo = foo
69
+ @bar = bar
70
+ @baz = baz
71
+ end
72
+ end
73
+
74
+ class RTwoAttrsInheritsOneAttr < ROneAttr
75
+ attr_reader :bar
76
+
77
+ def initialize(foo:, bar:)
78
+ super(foo: foo)
79
+ @bar = bar
80
+ end
81
+ end
82
+
83
+ module ROneAttrModule
84
+ attr_reader :foo
85
+
86
+ def initialize(foo:)
87
+ @foo = foo
88
+ end
89
+ end
90
+
91
+ class ROneAttrViaModule
92
+ include ROneAttrModule
93
+ end
94
+
95
+ Benchmark.ips do |b|
96
+ b.warmup = 0.1
97
+ b.time = 1
98
+
99
+ b.report "KWAttr classes" do
100
+ OneAttr.new foo: 42
101
+ OneAttrDefault.new
102
+ OneAttrOnePositional.new 42, foo: 21
103
+ TwoAttrs.new foo: 42, bar: 21
104
+ TwoAttrsDefaults.new
105
+ TwoAttrsOneDefault.new foo: 42
106
+ TwoAttrsOnePos.new 42, foo: 21, bar: 14
107
+ TwoAttrsInheritsOneAttr.new foo: 42, bar: 21
108
+ OneAttrViaModule.new foo: 42
109
+ end
110
+
111
+ b.report "Plain classes" do
112
+ ROneAttr.new foo: 42
113
+ ROneAttrDefault.new
114
+ ROneAttrOnePositional.new 42, foo: 21
115
+ RTwoAttrs.new foo: 42, bar: 21
116
+ RTwoAttrsDefaults.new
117
+ RTwoAttrsOneDefault.new foo: 42
118
+ RTwoAttrsOnePos.new 42, foo: 21, bar: 14
119
+ RTwoAttrsInheritsOneAttr.new foo: 42, bar: 21
120
+ ROneAttrViaModule.new foo: 42
121
+ end
122
+
123
+ b.compare!
124
+ end
@@ -1,11 +1,9 @@
1
1
  # coding: utf-8
2
- lib = File.expand_path('../lib', __FILE__)
3
- $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
- require 'kwattr/version'
2
+ require_relative 'lib/kwattr'
5
3
 
6
4
  Gem::Specification.new do |spec|
7
5
  spec.name = "kwattr"
8
- spec.version = KWattr::VERSION
6
+ spec.version = KWAttr::VERSION
9
7
  spec.authors = ["Étienne Barrié"]
10
8
  spec.email = ["etienne.barrie@gmail.com"]
11
9
 
@@ -19,4 +17,5 @@ Gem::Specification.new do |spec|
19
17
  spec.add_development_dependency "bundler", "~> 1.9"
20
18
  spec.add_development_dependency "rake", "~> 10.0"
21
19
  spec.add_development_dependency "rspec", "~> 3.2"
20
+ spec.add_development_dependency "benchmark-ips", "~> 2.2"
22
21
  end
@@ -1,57 +1,57 @@
1
- require "kwattr/version"
1
+ class KWAttr < Module
2
+ VERSION = "0.3.0"
2
3
 
3
- module KWAttr
4
+ attr_reader :required_attrs, :defaults
4
5
 
5
- def kwattr(*attrs, **opts)
6
- names = [*attrs, *opts.keys]
7
- attr_reader(*names)
8
- prepend Initializer
9
- extend Heritable
10
- required, defaults = kwattrs
11
- attrs.each { |attr| required << attr unless required.include?(attr) }
12
- defaults.merge!(opts)
13
- names
6
+ def initialize
7
+ @required_attrs = []
8
+ @defaults = {}
14
9
  end
15
10
 
16
- def kwattrs
17
- @kwattrs ||= [[], {}]
18
- end
19
-
20
- module Heritable
21
- def inherited(subclass)
22
- required, defaults = kwattrs
23
- subclass.kwattr(*required, **defaults)
24
- end
25
-
26
- alias_method :included, :inherited
27
- end
11
+ def initializer(attrs, opts)
12
+ required_attrs = self.required_attrs
13
+ defaults = self.defaults
14
+ required_attrs.concat(attrs).uniq!
15
+ defaults.merge!(opts)
28
16
 
29
- module Initializer
30
- def initialize(*args, **kwargs)
31
- required, defaults = self.class.kwattrs
32
- required = required.dup
17
+ $VERBOSE = false
18
+ define_method :initialize do |*args, **kwargs|
19
+ required = required_attrs.dup
33
20
  defaults.merge(kwargs).each_pair do |key, value|
34
21
  next unless required.delete(key) || defaults.key?(key)
35
22
  kwargs.delete(key)
36
23
  instance_variable_set "@#{key}", value
37
24
  end
25
+
38
26
  unless required.empty?
27
+ method(:initialize).super_method.parameters.each do |type, name|
28
+ required << name if type == :keyreq && !kwargs.key?(name)
29
+ end
39
30
  raise ArgumentError,
40
31
  "missing keyword#{'s' if required.size > 1}: #{required.join(', ')}"
41
32
  end
42
- if method(:initialize).super_method.arity == args.size && !kwargs.empty?
43
- raise ArgumentError,
44
- "unknown keyword#{'s' if kwargs.size > 1}: #{kwargs.keys.join(', ')}"
33
+ unless kwargs.empty?
34
+ arity = method(:initialize).super_method.arity
35
+ if arity != -1 && arity == args.size
36
+ raise ArgumentError,
37
+ "unknown keyword#{'s' if kwargs.size > 1}: #{kwargs.keys.join(', ')}"
38
+ end
39
+ args << kwargs
45
40
  end
46
- args << kwargs unless kwargs.empty?
41
+
47
42
  super(*args)
48
43
  end
44
+ $VERBOSE = true
49
45
  end
50
46
 
51
47
  end
52
48
 
53
- public def kwattr(*args)
54
- raise TypeError, "wrong type #{self.class} (expected Module)" unless Module === self
55
- extend KWAttr
56
- kwattr(*args)
49
+ class Module
50
+ def kwattr(*attrs, **opts)
51
+ names = [*attrs, *opts.keys]
52
+ attr_reader(*names)
53
+ prepend @kwattrs ||= KWAttr.new
54
+ @kwattrs.initializer(attrs, opts)
55
+ names
56
+ end
57
57
  end
data/test.rb CHANGED
@@ -15,8 +15,6 @@ rescue exception_class
15
15
  return p $!
16
16
  end
17
17
 
18
- fail unless raises?(TypeError) { kwattr }
19
-
20
18
  fail unless raises?(ArgumentError) { Test.new }
21
19
  fail unless raises?(ArgumentError) { Test.new(foo: 42) }
22
20
  fail unless raises?(ArgumentError) { Test.new(foo: 42, bar: 21, baz: 43) }
@@ -49,7 +47,6 @@ fail unless p(test.titi) == 1
49
47
  fail unless p(test.toto) == 2
50
48
 
51
49
  class TestDescendant < Test
52
- kwattr :bar
53
50
  kwattr :baz
54
51
  end
55
52
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: kwattr
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.2.0
4
+ version: 0.3.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - "Étienne Barrié"
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2015-04-07 00:00:00.000000000 Z
11
+ date: 2015-06-01 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -52,6 +52,20 @@ dependencies:
52
52
  - - "~>"
53
53
  - !ruby/object:Gem::Version
54
54
  version: '3.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: benchmark-ips
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - "~>"
60
+ - !ruby/object:Gem::Version
61
+ version: '2.2'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - "~>"
67
+ - !ruby/object:Gem::Version
68
+ version: '2.2'
55
69
  description: ''
56
70
  email:
57
71
  - etienne.barrie@gmail.com
@@ -66,11 +80,11 @@ files:
66
80
  - Gemfile
67
81
  - README.md
68
82
  - Rakefile
83
+ - benchmark.rb
69
84
  - bin/console
70
85
  - bin/setup
71
86
  - kwattr.gemspec
72
87
  - lib/kwattr.rb
73
- - lib/kwattr/version.rb
74
88
  - test.rb
75
89
  homepage: https://github.com/etiennebarrie/kwattr
76
90
  licenses: []
@@ -1,3 +0,0 @@
1
- module KWattr
2
- VERSION = "0.2.0"
3
- end