attire 0.0.3 → 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +32 -31
- data/lib/attire/attr_init.rb +39 -41
- data/lib/attire/initializer.rb +72 -0
- data/lib/attire.rb +5 -17
- metadata +3 -2
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: f2bfbf4841ab811cd44ca5b6cdc0e1f2b7684edd
|
4
|
+
data.tar.gz: 3b5c032e8ace9ffebb12a3d4b05cf34c6c5165b2
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c3e7f83d80850d61a9e209840546656c90830d1c18928cc647520e434d9992337d83de6b455636f34249b4a763d0b3b8c7264d807e3fae07b4224211aa4cb38b
|
7
|
+
data.tar.gz: 2b3e84746a21c8668b55cb96a069f4da96f4d33052caca4d1340e32ad6c079d2dc36fccb8b5f7115e44094f0f6957999b90a99efd92df5f136a0abfcd6bc73f9
|
data/README.md
CHANGED
@@ -2,34 +2,50 @@
|
|
2
2
|
|
3
3
|
[![Gem Version](https://badge.fury.io/rb/attire.svg)](http://badge.fury.io/rb/attire)
|
4
4
|
|
5
|
-
Convenience methods to remove some boiler plate in defining classes.
|
5
|
+
Convenience methods to remove some boiler plate in defining classes. Inspired by [attr_extras](https://github.com/barsoom/attr_extras).
|
6
6
|
|
7
7
|
## Usage
|
8
8
|
|
9
9
|
### `attr_init :foo, :bar, fizz: 15, pop: nil`
|
10
10
|
|
11
|
-
Defines the following
|
11
|
+
Defines the following:
|
12
12
|
|
13
13
|
``` ruby
|
14
|
-
def
|
14
|
+
def initialize(foo, bar, opts = {})
|
15
15
|
@foo = foo
|
16
16
|
@bar = bar
|
17
17
|
@fizz = opts[:fizz] || 15
|
18
18
|
@pop = opts[:pop]
|
19
19
|
end
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
attr_reader :foo, :bar, :fizz, :pop
|
24
|
+
```
|
25
|
+
|
26
|
+
Splat arguments and blocks can also be defined:
|
27
|
+
|
28
|
+
``` ruby
|
29
|
+
attr_init :'*args', :'&block'
|
20
30
|
```
|
21
31
|
|
22
|
-
|
32
|
+
If a block is provided, it will be evaluated after initialization:
|
33
|
+
|
34
|
+
``` ruby
|
35
|
+
attr_init :foo do
|
36
|
+
@foo = foo ** 2
|
37
|
+
end
|
38
|
+
```
|
23
39
|
|
24
40
|
### `attr_method :select, :bar`
|
25
41
|
|
26
|
-
|
42
|
+
Defines the following:
|
27
43
|
|
28
44
|
``` ruby
|
29
45
|
attr_init :bar
|
30
46
|
|
31
|
-
def self.select(
|
32
|
-
new(
|
47
|
+
def self.select(*args, &block)
|
48
|
+
new(*args, &block).select
|
33
49
|
end
|
34
50
|
```
|
35
51
|
|
@@ -40,46 +56,31 @@ class CheeseSpreader
|
|
40
56
|
attr_method :spread, :cheese, crackers: Jacobs.new
|
41
57
|
|
42
58
|
def spread
|
43
|
-
|
44
|
-
|
59
|
+
raise CheeseError unless cheese.is_a?(Cheddar)
|
60
|
+
cheese.spread_on(crackers)
|
45
61
|
end
|
46
62
|
end
|
47
63
|
|
48
|
-
|
49
|
-
|
50
|
-
my_cheese = Roquefort.new
|
51
|
-
CheeseSpreader.spread(my_cheese) # CheeseError
|
64
|
+
CheeseSpreader.spread(Roquefort.new) # CheeseError
|
52
65
|
```
|
53
66
|
|
54
67
|
### `attr_query :foo?`
|
55
68
|
|
56
|
-
Defines query
|
57
|
-
|
58
|
-
### `fattr_init :foo`
|
59
|
-
|
60
|
-
Calls `self.freeze` after initialization to make object immutable.
|
61
|
-
|
62
|
-
### `fattr_method :foo`
|
63
|
-
|
64
|
-
Same as `fattr_init`, only for `attr_method`.
|
65
|
-
|
69
|
+
Defines query `foo?`, which is true if `foo` is truthy.
|
66
70
|
|
67
71
|
## Installation
|
68
72
|
|
69
|
-
Add
|
73
|
+
Add to Gemfile:
|
70
74
|
|
71
75
|
```ruby
|
72
76
|
gem 'attire'
|
73
77
|
```
|
74
78
|
|
75
|
-
|
76
|
-
|
77
|
-
$ bundle
|
78
|
-
|
79
|
-
Or install it yourself as:
|
80
|
-
|
81
|
-
$ gem install attire
|
79
|
+
Require library:
|
82
80
|
|
81
|
+
``` ruby
|
82
|
+
require 'attire'
|
83
|
+
```
|
83
84
|
|
84
85
|
## Contributing
|
85
86
|
|
data/lib/attire/attr_init.rb
CHANGED
@@ -1,76 +1,74 @@
|
|
1
|
+
require 'attire/initializer'
|
2
|
+
|
1
3
|
module Attire
|
2
4
|
class AttrInit
|
3
5
|
def self.apply(*args)
|
4
6
|
new(*args).apply
|
5
7
|
end
|
6
8
|
|
7
|
-
def initialize(klass,
|
8
|
-
@klass, @
|
9
|
+
def initialize(klass, names, after_initialize)
|
10
|
+
@klass, @names, @after_initialize = klass, names, after_initialize
|
9
11
|
end
|
10
12
|
|
11
13
|
def apply
|
12
14
|
type_check
|
13
|
-
|
14
|
-
|
15
|
+
extract_splat_and_block_names
|
16
|
+
instance_initialize = initializer.method(:instance_initialize)
|
17
|
+
|
18
|
+
klass.send(:define_method, :initialize) do |*values, &value_block|
|
19
|
+
instance_initialize.call(self, values, value_block)
|
20
|
+
end
|
21
|
+
|
15
22
|
define_getters
|
16
23
|
end
|
17
24
|
|
18
25
|
private
|
19
26
|
|
20
|
-
attr_reader :klass, :
|
27
|
+
attr_reader :klass, :names, :splat_name, :block_name, :after_initialize
|
21
28
|
|
22
|
-
def
|
23
|
-
|
24
|
-
|
25
|
-
set_variables
|
26
|
-
instance.instance_eval(&block) if block
|
29
|
+
def type_check
|
30
|
+
return if names.all? { |n| [Symbol, Hash].include?(n.class) }
|
31
|
+
fail ArgumentError, 'Must be Symbol or Hash.'
|
27
32
|
end
|
28
33
|
|
29
|
-
def
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
hash_check(value)
|
34
|
-
arg.each { |k, v| set_variable(k, value[k] || v) }
|
35
|
-
end
|
34
|
+
def extract_splat_and_block_names
|
35
|
+
@block_name = last_name_with_prefix('&')
|
36
|
+
@splat_name = last_name_with_prefix('*')
|
37
|
+
excess_splat_and_block_names_check
|
36
38
|
end
|
37
39
|
|
38
|
-
def
|
39
|
-
|
40
|
-
klass.send(:define_method, arg) { instance_variable_get("@#{arg}") }
|
41
|
-
klass.send(:private, arg)
|
42
|
-
end
|
40
|
+
def initializer
|
41
|
+
Initializer.new(names, splat_name, block_name, after_initialize)
|
43
42
|
end
|
44
43
|
|
45
|
-
def
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
def arity_check
|
51
|
-
return if arity_range.include?(values.length)
|
52
|
-
fail ArgumentError, "wrong number of arguments (#{values.length} for #{arity_range})"
|
44
|
+
def define_getters
|
45
|
+
getter_names.each do |name|
|
46
|
+
klass.send(:define_method, name) { instance_variable_get("@#{name}") }
|
47
|
+
end
|
48
|
+
klass.send(:private, *getter_names)
|
53
49
|
end
|
54
50
|
|
55
|
-
def
|
56
|
-
|
57
|
-
|
51
|
+
def getter_names
|
52
|
+
getter_names = names.map { |arg| arg.respond_to?(:keys) ? arg.keys : arg }
|
53
|
+
getter_names += [splat_name, block_name]
|
54
|
+
getter_names.flatten.compact
|
58
55
|
end
|
59
56
|
|
60
|
-
def
|
61
|
-
|
57
|
+
def last_name_with_prefix(prefix)
|
58
|
+
without_prefix(names.pop) if last_name_prefix?(prefix)
|
62
59
|
end
|
63
60
|
|
64
|
-
def
|
65
|
-
|
61
|
+
def without_prefix(symbol)
|
62
|
+
symbol.to_s[1..-1].to_sym
|
66
63
|
end
|
67
64
|
|
68
|
-
def
|
69
|
-
|
65
|
+
def last_name_prefix?(prefix)
|
66
|
+
names.last.to_s.start_with?(prefix)
|
70
67
|
end
|
71
68
|
|
72
|
-
def
|
73
|
-
|
69
|
+
def excess_splat_and_block_names_check
|
70
|
+
return if names.none? { |n| n.to_s.start_with?('&', '*') }
|
71
|
+
fail ArgumentError, "Splat and Block arguments must be last"
|
74
72
|
end
|
75
73
|
end
|
76
74
|
end
|
@@ -0,0 +1,72 @@
|
|
1
|
+
module Attire
|
2
|
+
class Initializer
|
3
|
+
def initialize(names, splat_name, block_name, after_initialize)
|
4
|
+
@names = names
|
5
|
+
@splat_name = splat_name
|
6
|
+
@block_name = block_name
|
7
|
+
@after_initialize = after_initialize
|
8
|
+
end
|
9
|
+
|
10
|
+
def instance_initialize(instance, values, value_block)
|
11
|
+
@instance, @values, @value_block = instance, values, value_block
|
12
|
+
arity_check
|
13
|
+
set_ivars
|
14
|
+
instance.instance_eval(&after_initialize) if after_initialize
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :names, :splat_name, :block_name, :after_initialize,
|
20
|
+
:instance, :values, :value_block
|
21
|
+
|
22
|
+
def set_ivars
|
23
|
+
names.zip(values).each do |name, value|
|
24
|
+
name.is_a?(Symbol) ? set_ivar(name, value) : set_hash(name, value)
|
25
|
+
end
|
26
|
+
set_splat
|
27
|
+
set_block
|
28
|
+
end
|
29
|
+
|
30
|
+
def set_hash(defaults, values)
|
31
|
+
values ||= {}
|
32
|
+
hash_check(values)
|
33
|
+
defaults.each { |name, default| set_ivar(name, values[name] || default) }
|
34
|
+
end
|
35
|
+
|
36
|
+
def set_splat
|
37
|
+
return unless splat_name
|
38
|
+
value_splat = values[names.length..values.length] || []
|
39
|
+
set_ivar(splat_name, value_splat)
|
40
|
+
end
|
41
|
+
|
42
|
+
def set_block
|
43
|
+
set_ivar(block_name, value_block) if block_name
|
44
|
+
end
|
45
|
+
|
46
|
+
def set_ivar(name, value)
|
47
|
+
instance.instance_variable_set("@#{name}", value)
|
48
|
+
end
|
49
|
+
|
50
|
+
def arity_check
|
51
|
+
return if arity_range.include?(values.length)
|
52
|
+
fail ArgumentError, "wrong number of arguments (#{values.length} for #{arity_range})"
|
53
|
+
end
|
54
|
+
|
55
|
+
def hash_check(value)
|
56
|
+
return if value.is_a?(Hash)
|
57
|
+
fail ArgumentError, "#{value} should be Hash."
|
58
|
+
end
|
59
|
+
|
60
|
+
def min_arity
|
61
|
+
names.last.is_a?(Hash) ? names.length - 1 : names.length
|
62
|
+
end
|
63
|
+
|
64
|
+
def max_arity
|
65
|
+
splat_name ? Float::INFINITY : names.length
|
66
|
+
end
|
67
|
+
|
68
|
+
def arity_range
|
69
|
+
@arity_range ||= (min_arity..max_arity)
|
70
|
+
end
|
71
|
+
end
|
72
|
+
end
|
data/lib/attire.rb
CHANGED
@@ -9,25 +9,13 @@ module Attire
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
-
def attr_init(*
|
13
|
-
AttrInit.apply(self,
|
12
|
+
def attr_init(*names, &b)
|
13
|
+
AttrInit.apply(self, names, b)
|
14
14
|
end
|
15
15
|
|
16
|
-
def attr_method(verb, *
|
17
|
-
define_singleton_method(verb) { |*a| new(*a).send(verb) }
|
18
|
-
attr_init(*
|
19
|
-
end
|
20
|
-
|
21
|
-
def fattr_init(*args, &b)
|
22
|
-
attr_init(*args) do
|
23
|
-
instance_eval(&b) if b
|
24
|
-
freeze
|
25
|
-
end
|
26
|
-
end
|
27
|
-
|
28
|
-
def fattr_method(verb, *args, &b)
|
29
|
-
define_singleton_method(verb) { |*a| new(*a).send(verb) }
|
30
|
-
fattr_init(*args, &b)
|
16
|
+
def attr_method(verb, *names, &b)
|
17
|
+
define_singleton_method(verb) { |*a, &b| new(*a, &b).send(verb) }
|
18
|
+
attr_init(*names, &b)
|
31
19
|
end
|
32
20
|
end
|
33
21
|
|
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.0
|
4
|
+
version: 0.1.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-01-
|
11
|
+
date: 2015-01-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -40,6 +40,7 @@ files:
|
|
40
40
|
- README.md
|
41
41
|
- lib/attire.rb
|
42
42
|
- lib/attire/attr_init.rb
|
43
|
+
- lib/attire/initializer.rb
|
43
44
|
homepage:
|
44
45
|
licenses:
|
45
46
|
- MIT
|