attire 0.0.3 → 0.1.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 +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
|
[](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
|