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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 64462f8404d14584ebdfed3fead9ce4a7d0e250e
4
- data.tar.gz: 480ae9e4232ff1226c98af84fec1ad78e538b5b6
3
+ metadata.gz: f2bfbf4841ab811cd44ca5b6cdc0e1f2b7684edd
4
+ data.tar.gz: 3b5c032e8ace9ffebb12a3d4b05cf34c6c5165b2
5
5
  SHA512:
6
- metadata.gz: 38df5f2ded5aec66f5a6275d2922da706153223620815afb0c06ca8b2f3abe4c11c78b8626cf5fe2f231841b14eadd13874b4a208285b600c9ee888835cd3074
7
- data.tar.gz: 7f1f0b736e8b6f7e3390a9d50ad374b304e82f7c2d44dd7803a05532e65ab116f85164c226945023af42db03b59f567c2f33667f9378dc60da0563eac79571ea
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. Heavily inspired by [attr_extras](https://github.com/barsoom/attr_extras).
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 initializer:
11
+ Defines the following:
12
12
 
13
13
  ``` ruby
14
- def initializer(foo, bar, opts = {})
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
- `attr_init` can also accept a block which will be invoked after initialization.
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
- Shortcut for:
42
+ Defines the following:
27
43
 
28
44
  ``` ruby
29
45
  attr_init :bar
30
46
 
31
- def self.select(bar)
32
- new(bar).select
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
- raise CheeseError unless cheese.is_a?(Cheddar)
44
- cheese.spread_on(crackers)
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 methods like `foo?`, which is true if `foo` is truthy.
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 this line to your application's Gemfile:
73
+ Add to Gemfile:
70
74
 
71
75
  ```ruby
72
76
  gem 'attire'
73
77
  ```
74
78
 
75
- And then execute:
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
 
@@ -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, args, block)
8
- @klass, @args, @block = klass, args, block
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
- init = method(:init)
14
- klass.send(:define_method, :initialize) { |*values| init.call(self, values) }
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, :args, :block, :instance, :values
27
+ attr_reader :klass, :names, :splat_name, :block_name, :after_initialize
21
28
 
22
- def init(instance, values)
23
- @instance, @values = instance, values
24
- arity_check
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 set_variables
30
- args.zip(values).each do |arg, value|
31
- next set_variable(arg, value) if arg.is_a?(Symbol)
32
- value = {} if value.nil?
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 define_getters
39
- getter_names.each do |arg|
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 type_check
46
- return if args.all? { |a| [Symbol, Hash].include?(a.class) }
47
- fail ArgumentError, 'Must be Symbol or Hash.'
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})"
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 hash_check(value)
56
- return if value.is_a?(Hash)
57
- fail ArgumentError, "#{value} should be Hash."
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 min_arity
61
- args.last.is_a?(Hash) ? args.length - 1 : args.length
57
+ def last_name_with_prefix(prefix)
58
+ without_prefix(names.pop) if last_name_prefix?(prefix)
62
59
  end
63
60
 
64
- def arity_range
65
- @arity_range ||= (min_arity..args.length)
61
+ def without_prefix(symbol)
62
+ symbol.to_s[1..-1].to_sym
66
63
  end
67
64
 
68
- def set_variable(name, value)
69
- instance.instance_variable_set("@#{name}", value)
65
+ def last_name_prefix?(prefix)
66
+ names.last.to_s.start_with?(prefix)
70
67
  end
71
68
 
72
- def getter_names
73
- args.map { |arg| arg.respond_to?(:keys) ? arg.keys : arg }.flatten
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(*args, &b)
13
- AttrInit.apply(self, args, b)
12
+ def attr_init(*names, &b)
13
+ AttrInit.apply(self, names, b)
14
14
  end
15
15
 
16
- def attr_method(verb, *args, &b)
17
- define_singleton_method(verb) { |*a| new(*a).send(verb) }
18
- attr_init(*args, &b)
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.3
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-08 00:00:00.000000000 Z
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