attire 0.1.4 → 1.0.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 +4 -4
- data/README.md +107 -93
- data/lib/attire/attr_init/arguments.rb +57 -0
- data/lib/attire/attr_init/arguments_checker.rb +66 -0
- data/lib/attire/attr_init/initializer.rb +30 -0
- data/lib/attire/attr_init/values_matcher.rb +42 -0
- data/lib/attire/attr_init.rb +26 -82
- data/lib/attire.rb +24 -24
- metadata +7 -4
- data/lib/attire/initializer.rb +0 -92
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: b1e1fc1f22a2213695656d10b09d2de54e340910
|
4
|
+
data.tar.gz: 0e10d06cf3402de661391eb894c5127f6a9f56fe
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 8878fced254c26d7f4520bb99547d88c96b5355b79200b8e3ace0c47e03c3c1e26c64b4ecfc435184c209138ffecb1f11c38876f249f33417a03abce178f7def
|
7
|
+
data.tar.gz: 76646d629df750287941eaad2e57a3884f236be29a0c77bc66eb7bd0bcc08730def009c0dbccefb66b9c0e32350cab641c07d176ee7b7e294b276f93dd427421
|
data/README.md
CHANGED
@@ -1,93 +1,107 @@
|
|
1
|
-
# Attire
|
2
|
-
|
3
|
-
[](https://travis-ci.org/mushishi78/attire)
|
4
|
-
[](http://badge.fury.io/rb/attire)
|
5
|
-
|
6
|
-
Convenience methods to remove some boiler plate in defining classes. Inspired by [attr_extras](https://github.com/barsoom/attr_extras).
|
7
|
-
|
8
|
-
##
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
@
|
19
|
-
@
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
```
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
``` ruby
|
36
|
-
attr_init :
|
37
|
-
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
```
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
```
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
``` ruby
|
56
|
-
|
57
|
-
|
58
|
-
|
59
|
-
|
60
|
-
|
61
|
-
|
62
|
-
|
63
|
-
|
64
|
-
|
65
|
-
|
66
|
-
CheeseSpreader
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
```
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
|
83
|
-
```
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
##
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
1
|
+
# Attire
|
2
|
+
|
3
|
+
[](https://travis-ci.org/mushishi78/attire)
|
4
|
+
[](http://badge.fury.io/rb/attire)
|
5
|
+
|
6
|
+
Convenience methods to remove some boiler plate in defining classes. Inspired by [attr_extras](https://github.com/barsoom/attr_extras).
|
7
|
+
|
8
|
+
## attr_init
|
9
|
+
|
10
|
+
``` ruby
|
11
|
+
attr_init :foo, :bar, fizz: 15, pop: nil
|
12
|
+
```
|
13
|
+
|
14
|
+
Defines the following:
|
15
|
+
|
16
|
+
``` ruby
|
17
|
+
def initialize(foo, bar, opts = {})
|
18
|
+
@foo = foo
|
19
|
+
@bar = bar
|
20
|
+
@fizz = opts[:fizz]
|
21
|
+
@pop = opts[:pop]
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
attr_reader :foo, :bar, :pop
|
27
|
+
|
28
|
+
def fizz
|
29
|
+
@fizz ||= 15
|
30
|
+
end
|
31
|
+
```
|
32
|
+
|
33
|
+
Optional, splat and blocks arguments can also be defined:
|
34
|
+
|
35
|
+
``` ruby
|
36
|
+
attr_init :'opts = {}', :'*args', :'&block'
|
37
|
+
```
|
38
|
+
|
39
|
+
If a block is provided, it will be evaluated after initialization:
|
40
|
+
|
41
|
+
``` ruby
|
42
|
+
attr_init :foo do
|
43
|
+
@foo = foo ** 2
|
44
|
+
end
|
45
|
+
```
|
46
|
+
|
47
|
+
## attr_method
|
48
|
+
|
49
|
+
``` ruby
|
50
|
+
attr_method :select, :bar
|
51
|
+
```
|
52
|
+
|
53
|
+
Defines the following:
|
54
|
+
|
55
|
+
``` ruby
|
56
|
+
def self.select(*args, &block)
|
57
|
+
new(*args, &block).select
|
58
|
+
end
|
59
|
+
|
60
|
+
attr_init :bar
|
61
|
+
```
|
62
|
+
|
63
|
+
This is useful for method objects/use cases:
|
64
|
+
|
65
|
+
``` ruby
|
66
|
+
class CheeseSpreader
|
67
|
+
attr_method :spread, :cheese, crackers_class: Jacobs
|
68
|
+
|
69
|
+
def spread
|
70
|
+
cracker = crackers_class.new
|
71
|
+
cracker.spreads << cheese
|
72
|
+
cracker
|
73
|
+
end
|
74
|
+
end
|
75
|
+
|
76
|
+
CheeseSpreader.spread(roquefort)
|
77
|
+
```
|
78
|
+
|
79
|
+
## attr_query
|
80
|
+
|
81
|
+
``` ruby
|
82
|
+
attr_query :foo?
|
83
|
+
```
|
84
|
+
|
85
|
+
Defines query `#foo?`, which is true if `foo` is truthy.
|
86
|
+
|
87
|
+
## Installation
|
88
|
+
|
89
|
+
Add to Gemfile:
|
90
|
+
|
91
|
+
```ruby
|
92
|
+
gem 'attire'
|
93
|
+
```
|
94
|
+
|
95
|
+
Require library:
|
96
|
+
|
97
|
+
``` ruby
|
98
|
+
require 'attire'
|
99
|
+
```
|
100
|
+
|
101
|
+
## Contributing
|
102
|
+
|
103
|
+
1. Fork it ( https://github.com/[my-github-username]/attire/fork )
|
104
|
+
2. Create your feature branch (`git checkout -b my-new-feature`)
|
105
|
+
3. Commit your changes (`git commit -am 'Add some feature'`)
|
106
|
+
4. Push to the branch (`git push origin my-new-feature`)
|
107
|
+
5. Create a new Pull Request
|
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'attire/core_ext/duplicable'
|
2
|
+
require_relative 'arguments_checker'
|
3
|
+
|
4
|
+
module Attire
|
5
|
+
module AttrInit
|
6
|
+
class Arguments
|
7
|
+
def initialize(arguments)
|
8
|
+
ArgumentsChecker.check(arguments)
|
9
|
+
@block = last_argument_with_prefix(arguments, '&')
|
10
|
+
@splat = last_argument_with_prefix(arguments, '*')
|
11
|
+
@names, @defaults = [], {}
|
12
|
+
arguments.each { |arg| extract_argument(arg) }
|
13
|
+
@arity_range = (min_arity..max_arity)
|
14
|
+
@getter_names = (names.flatten + [splat, block]).compact
|
15
|
+
end
|
16
|
+
|
17
|
+
attr_reader :names, :splat, :block, :defaults, :arity_range, :getter_names
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def last_argument_with_prefix(arguments, prefix)
|
22
|
+
return unless arguments.last.to_s.start_with?(prefix)
|
23
|
+
arguments.pop.to_s[1..-1]
|
24
|
+
end
|
25
|
+
|
26
|
+
def extract_argument(arg)
|
27
|
+
return extract_hash(arg) if arg.is_a?(Hash)
|
28
|
+
return extract_optional(arg) if arg.to_s.include?('=')
|
29
|
+
extract_required(arg)
|
30
|
+
end
|
31
|
+
|
32
|
+
def extract_hash(hash)
|
33
|
+
names << hash.keys
|
34
|
+
defaults.merge!(hash)
|
35
|
+
end
|
36
|
+
|
37
|
+
def extract_optional(arg)
|
38
|
+
name, default = arg.to_s.split('=').map(&:strip)
|
39
|
+
names << name
|
40
|
+
defaults[name] = eval(default)
|
41
|
+
end
|
42
|
+
|
43
|
+
def extract_required(arg)
|
44
|
+
names << arg
|
45
|
+
@min_arity = names.length
|
46
|
+
end
|
47
|
+
|
48
|
+
def min_arity
|
49
|
+
@min_arity ||= 0
|
50
|
+
end
|
51
|
+
|
52
|
+
def max_arity
|
53
|
+
splat ? Float::INFINITY : names.length
|
54
|
+
end
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
module Attire
|
2
|
+
module AttrInit
|
3
|
+
class ArgumentsChecker
|
4
|
+
def self.check(arguments)
|
5
|
+
new.check(arguments)
|
6
|
+
end
|
7
|
+
|
8
|
+
def check(arguments)
|
9
|
+
arguments.reverse.each_with_index do |arg, i|
|
10
|
+
@arg, @i = arg, i
|
11
|
+
type_check
|
12
|
+
block_check
|
13
|
+
splat_check
|
14
|
+
required_after_optional_check
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
attr_reader :arg, :i
|
21
|
+
|
22
|
+
TYPES = [Symbol, String, Hash]
|
23
|
+
|
24
|
+
def type_check
|
25
|
+
return if TYPES.include?(arg.class)
|
26
|
+
fail ArgumentError, 'Must be Symbol, String or Hash.'
|
27
|
+
end
|
28
|
+
|
29
|
+
def block_check
|
30
|
+
return unless block?
|
31
|
+
fail ArgumentError, 'Block arguments must be last' unless i == 0
|
32
|
+
@has_block = true
|
33
|
+
end
|
34
|
+
|
35
|
+
def splat_check
|
36
|
+
return unless splat?
|
37
|
+
return if i == (@has_block ? 1 : 0)
|
38
|
+
fail ArgumentError, \
|
39
|
+
'Splat arguments must come after required and optional arguments'
|
40
|
+
end
|
41
|
+
|
42
|
+
def required_after_optional_check
|
43
|
+
return if block? || splat? || hash?
|
44
|
+
return @has_requireds = true unless optional?
|
45
|
+
return unless @has_requireds
|
46
|
+
fail ArgumentError, 'Required arguments must come before optional'
|
47
|
+
end
|
48
|
+
|
49
|
+
def block?
|
50
|
+
arg.to_s.start_with?('&')
|
51
|
+
end
|
52
|
+
|
53
|
+
def splat?
|
54
|
+
arg.to_s.start_with?('*')
|
55
|
+
end
|
56
|
+
|
57
|
+
def hash?
|
58
|
+
arg.is_a?(Hash)
|
59
|
+
end
|
60
|
+
|
61
|
+
def optional?
|
62
|
+
arg.to_s.include?('=')
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require_relative 'values_matcher'
|
2
|
+
|
3
|
+
module Attire
|
4
|
+
module AttrInit
|
5
|
+
class Initializer
|
6
|
+
def initialize(arguments, after_initialize, opts = {})
|
7
|
+
@values_matcher = opts[:values_matcher] || ValuesMatcher.new(arguments)
|
8
|
+
@arity_range = arguments.arity_range
|
9
|
+
@after_initialize = after_initialize
|
10
|
+
end
|
11
|
+
|
12
|
+
def instance_initialize(instance, values, value_block)
|
13
|
+
arity_check(values)
|
14
|
+
values_matcher.match(values, value_block).each do |k, v|
|
15
|
+
instance.instance_variable_set("@#{k}", v)
|
16
|
+
end
|
17
|
+
instance.instance_exec(&after_initialize) if after_initialize
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :values_matcher, :arity_range, :after_initialize
|
23
|
+
|
24
|
+
def arity_check(values)
|
25
|
+
return if arity_range.include?(values.length)
|
26
|
+
fail ArgumentError, "wrong number of arguments (#{values.length} for #{arity_range})"
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Attire
|
4
|
+
module AttrInit
|
5
|
+
class ValuesMatcher
|
6
|
+
extend Forwardable
|
7
|
+
|
8
|
+
def initialize(arguments)
|
9
|
+
@arguments = arguments
|
10
|
+
end
|
11
|
+
|
12
|
+
def match(values, value_block)
|
13
|
+
@matched = {}
|
14
|
+
names.zip(values) { |n, v| n.is_a?(Array) ? set_from_hash(v) : set(n, v) }
|
15
|
+
set_splat(values)
|
16
|
+
set_block(value_block)
|
17
|
+
matched
|
18
|
+
end
|
19
|
+
|
20
|
+
private
|
21
|
+
|
22
|
+
attr_reader :arguments, :matched
|
23
|
+
def_delegators :arguments, :names, :splat, :block
|
24
|
+
|
25
|
+
def set(name, value)
|
26
|
+
matched[name] = value
|
27
|
+
end
|
28
|
+
|
29
|
+
def set_from_hash(values)
|
30
|
+
matched.merge!(values || {})
|
31
|
+
end
|
32
|
+
|
33
|
+
def set_splat(values)
|
34
|
+
matched[splat] = values[names.length..-1] || [] if splat
|
35
|
+
end
|
36
|
+
|
37
|
+
def set_block(value_block)
|
38
|
+
matched[block] = value_block if block
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/lib/attire/attr_init.rb
CHANGED
@@ -1,94 +1,38 @@
|
|
1
|
-
require 'attire/
|
1
|
+
require 'attire/attr_init/arguments'
|
2
|
+
require 'attire/attr_init/initializer'
|
2
3
|
|
3
4
|
module Attire
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
end
|
12
|
-
|
13
|
-
def apply
|
14
|
-
type_check
|
15
|
-
extract_splat_and_block_names
|
16
|
-
optional_arguments_check
|
17
|
-
instance_initialize = initializer.method(:instance_initialize)
|
18
|
-
|
19
|
-
klass.send(:define_method, :initialize) do |*values, &value_block|
|
20
|
-
instance_initialize.call(self, values, value_block)
|
5
|
+
module AttrInit
|
6
|
+
class << self
|
7
|
+
def apply(klass, args, after_initialize)
|
8
|
+
arguments = Arguments.new(args)
|
9
|
+
initializer = Initializer.new(arguments, after_initialize)
|
10
|
+
define_initializer(klass, initializer)
|
11
|
+
define_getters(klass, arguments)
|
21
12
|
end
|
22
13
|
|
23
|
-
|
24
|
-
end
|
25
|
-
|
26
|
-
private
|
27
|
-
|
28
|
-
attr_reader :klass, :names, :splat_name, :block_name, :after_initialize
|
14
|
+
private
|
29
15
|
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
def extract_splat_and_block_names
|
36
|
-
@block_name = last_name_with_prefix('&')
|
37
|
-
@splat_name = last_name_with_prefix('*')
|
38
|
-
excess_splat_and_block_names_check
|
39
|
-
end
|
40
|
-
|
41
|
-
def initializer
|
42
|
-
Initializer.new(names, splat_name, block_name, after_initialize)
|
43
|
-
end
|
44
|
-
|
45
|
-
def define_getters
|
46
|
-
getter_names.each do |name|
|
47
|
-
klass.send(:define_method, name) { instance_variable_get("@#{name}") }
|
16
|
+
def define_initializer(klass, initializer)
|
17
|
+
klass.send(:define_method, :initialize) do |*values, &value_block|
|
18
|
+
initializer.instance_initialize(self, values, value_block)
|
19
|
+
end
|
48
20
|
end
|
49
|
-
klass.send(:private, *getter_names)
|
50
|
-
end
|
51
21
|
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
arg
|
22
|
+
def define_getters(klass, arguments)
|
23
|
+
names = arguments.getter_names
|
24
|
+
names.each { |n| define_getter(klass, n, arguments.defaults[n]) }
|
25
|
+
klass.send(:private, *names)
|
57
26
|
end
|
58
|
-
getter_names += [splat_name, block_name]
|
59
|
-
getter_names.flatten.compact
|
60
|
-
end
|
61
|
-
|
62
|
-
def last_name_with_prefix(prefix)
|
63
|
-
without_prefix(names.pop) if last_name_prefix?(prefix)
|
64
|
-
end
|
65
|
-
|
66
|
-
def without_prefix(symbol)
|
67
|
-
symbol.to_s[1..-1].to_sym
|
68
|
-
end
|
69
|
-
|
70
|
-
def last_name_prefix?(prefix)
|
71
|
-
names.last.to_s.start_with?(prefix)
|
72
|
-
end
|
73
27
|
|
74
|
-
|
75
|
-
|
76
|
-
|
77
|
-
|
78
|
-
|
79
|
-
|
80
|
-
|
81
|
-
|
82
|
-
return if names[start..-1].all? { |n| n.is_a?(Hash) || optional?(n) }
|
83
|
-
fail ArgumentError, 'Required arguments must come before optional'
|
84
|
-
end
|
85
|
-
|
86
|
-
def optional?(name)
|
87
|
-
name.to_s.include?('=')
|
88
|
-
end
|
89
|
-
|
90
|
-
def optional_name(name)
|
91
|
-
name.to_s.split('=')[0].strip
|
28
|
+
def define_getter(klass, name, default)
|
29
|
+
klass.send(:define_method, name) do
|
30
|
+
value = instance_variable_get("@#{name}")
|
31
|
+
return value unless value.nil? && !default.nil?
|
32
|
+
default = default.duplicable? ? default.dup : default
|
33
|
+
instance_variable_set("@#{name}", default)
|
34
|
+
end
|
35
|
+
end
|
92
36
|
end
|
93
37
|
end
|
94
38
|
end
|
data/lib/attire.rb
CHANGED
@@ -1,24 +1,24 @@
|
|
1
|
-
require 'attire/attr_init'
|
2
|
-
|
3
|
-
module Attire
|
4
|
-
def attr_query(*names)
|
5
|
-
names.each do |name|
|
6
|
-
name = name.to_s
|
7
|
-
fail ArgumentError, "`#{name}?`, not `#{name}`." unless name.end_with?('?')
|
8
|
-
define_method(name) { !!send(name.chop) }
|
9
|
-
end
|
10
|
-
end
|
11
|
-
|
12
|
-
def attr_init(*
|
13
|
-
AttrInit.apply(self,
|
14
|
-
end
|
15
|
-
|
16
|
-
def attr_method(verb, *
|
17
|
-
define_singleton_method(verb) { |*a, &b| new(*a, &b).send(verb) }
|
18
|
-
attr_init(*
|
19
|
-
end
|
20
|
-
end
|
21
|
-
|
22
|
-
class Module
|
23
|
-
include Attire
|
24
|
-
end
|
1
|
+
require 'attire/attr_init'
|
2
|
+
|
3
|
+
module Attire
|
4
|
+
def attr_query(*names)
|
5
|
+
names.each do |name|
|
6
|
+
name = name.to_s
|
7
|
+
fail ArgumentError, "`#{name}?`, not `#{name}`." unless name.end_with?('?')
|
8
|
+
define_method(name) { !!send(name.chop) }
|
9
|
+
end
|
10
|
+
end
|
11
|
+
|
12
|
+
def attr_init(*args, &block)
|
13
|
+
AttrInit.apply(self, args, block)
|
14
|
+
end
|
15
|
+
|
16
|
+
def attr_method(verb, *args, &block)
|
17
|
+
define_singleton_method(verb) { |*a, &b| new(*a, &b).send(verb) }
|
18
|
+
attr_init(*args, &block)
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
class Module
|
23
|
+
include Attire
|
24
|
+
end
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attire
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 1.0.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Max White
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2015-02
|
11
|
+
date: 2015-03-02 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -40,9 +40,12 @@ files:
|
|
40
40
|
- README.md
|
41
41
|
- lib/attire.rb
|
42
42
|
- lib/attire/attr_init.rb
|
43
|
+
- lib/attire/attr_init/arguments.rb
|
44
|
+
- lib/attire/attr_init/arguments_checker.rb
|
45
|
+
- lib/attire/attr_init/initializer.rb
|
46
|
+
- lib/attire/attr_init/values_matcher.rb
|
43
47
|
- lib/attire/core_ext/duplicable.rb
|
44
|
-
|
45
|
-
homepage:
|
48
|
+
homepage: https://github.com/mushishi78/attire
|
46
49
|
licenses:
|
47
50
|
- MIT
|
48
51
|
metadata: {}
|
data/lib/attire/initializer.rb
DELETED
@@ -1,92 +0,0 @@
|
|
1
|
-
require 'attire/core_ext/duplicable'
|
2
|
-
|
3
|
-
module Attire
|
4
|
-
class Initializer
|
5
|
-
def initialize(names, splat_name, block_name, after_initialize)
|
6
|
-
@names = names
|
7
|
-
@splat_name = splat_name
|
8
|
-
@block_name = block_name
|
9
|
-
@after_initialize = after_initialize
|
10
|
-
end
|
11
|
-
|
12
|
-
def instance_initialize(instance, values, value_block)
|
13
|
-
@instance, @values, @value_block = instance, values, value_block
|
14
|
-
arity_check
|
15
|
-
set_ivars
|
16
|
-
instance.instance_eval(&after_initialize) if after_initialize
|
17
|
-
end
|
18
|
-
|
19
|
-
private
|
20
|
-
|
21
|
-
attr_reader :names, :splat_name, :block_name, :after_initialize,
|
22
|
-
:instance, :values, :value_block
|
23
|
-
|
24
|
-
def set_ivars
|
25
|
-
names.zip(values).each do |name, value|
|
26
|
-
next set_hash(name, value) if name.is_a?(Hash)
|
27
|
-
next set_optional(name, value) if optional?(name)
|
28
|
-
set_ivar(name, value)
|
29
|
-
end
|
30
|
-
set_splat
|
31
|
-
set_block
|
32
|
-
end
|
33
|
-
|
34
|
-
def set_hash(defaults, values)
|
35
|
-
values ||= {}
|
36
|
-
hash_check(values)
|
37
|
-
defaults.each do |name, default|
|
38
|
-
next set_ivar(name, values[name]) unless values[name].nil?
|
39
|
-
set_ivar(name, default.duplicable? ? default.dup : default)
|
40
|
-
end
|
41
|
-
end
|
42
|
-
|
43
|
-
def set_optional(name, value)
|
44
|
-
name, default = name.to_s.split('=').map(&:strip)
|
45
|
-
value = instance.instance_eval(default) if value.nil?
|
46
|
-
set_ivar(name, value)
|
47
|
-
end
|
48
|
-
|
49
|
-
def set_splat
|
50
|
-
return unless splat_name
|
51
|
-
value_splat = values[names.length..values.length] || []
|
52
|
-
set_ivar(splat_name, value_splat)
|
53
|
-
end
|
54
|
-
|
55
|
-
def set_block
|
56
|
-
set_ivar(block_name, value_block) if block_name
|
57
|
-
end
|
58
|
-
|
59
|
-
def set_ivar(name, value)
|
60
|
-
instance.instance_variable_set("@#{name}", value)
|
61
|
-
end
|
62
|
-
|
63
|
-
def arity_check
|
64
|
-
return if arity_range.include?(values.length)
|
65
|
-
fail ArgumentError, "wrong number of arguments (#{values.length} for #{arity_range})"
|
66
|
-
end
|
67
|
-
|
68
|
-
def hash_check(value)
|
69
|
-
return if value.is_a?(Hash)
|
70
|
-
fail ArgumentError, "#{value} should be Hash."
|
71
|
-
end
|
72
|
-
|
73
|
-
def min_arity
|
74
|
-
last_required = names.reverse_each.find_index do |n|
|
75
|
-
!(optional?(n) || n.is_a?(Hash))
|
76
|
-
end
|
77
|
-
last_required ? names.length - last_required : 0
|
78
|
-
end
|
79
|
-
|
80
|
-
def max_arity
|
81
|
-
splat_name ? Float::INFINITY : names.length
|
82
|
-
end
|
83
|
-
|
84
|
-
def arity_range
|
85
|
-
@arity_range ||= (min_arity..max_arity)
|
86
|
-
end
|
87
|
-
|
88
|
-
def optional?(name)
|
89
|
-
name.to_s.include?('=')
|
90
|
-
end
|
91
|
-
end
|
92
|
-
end
|