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 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