constructable 0.2.5 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.2.5
1
+ 0.3.0
@@ -5,11 +5,11 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = %q{constructable}
8
- s.version = "0.2.5"
8
+ s.version = "0.3.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Manuel Korfmann"]
12
- s.date = %q{2011-06-12}
12
+ s.date = %q{2011-06-15}
13
13
  s.description = %q{
14
14
  Adds the class macro Class#constructable to easily define what attributes a Class accepts provided as a hash to Class#new.
15
15
  Attributes can be configured in their behaviour in case they are not provided or are in the wrong format.
@@ -4,12 +4,6 @@ module Constructable
4
4
  attr_accessor *ATTRIBUTES, :name
5
5
  attr_reader :value
6
6
 
7
- REQUIRED_REQUIREMENT = {
8
- name: :required,
9
- message: proc {":#{self.name} is a required attribute"},
10
- check: ->(hash) { hash[self.name] }
11
- }
12
-
13
7
  REQUIREMENTS = [
14
8
  {
15
9
  name: :validate,
@@ -55,10 +49,11 @@ module Constructable
55
49
  REQUIREMENTS.each do |requirement|
56
50
  check_for_requirement(requirement, constructor_hash)
57
51
  end
52
+
58
53
  value = constructor_hash[self.name]
59
54
  self.converter ? converter.(value) : value
60
55
  else
61
- check_for_requirement(REQUIRED_REQUIREMENT, constructor_hash)
56
+ raise AttributeError, ":#{self.name} is a required attribute" if self.required
62
57
  self.default
63
58
  end
64
59
  end
@@ -2,11 +2,12 @@ module Constructable
2
2
  class Constructor
3
3
  attr_accessor :attributes
4
4
 
5
- def initialize(klass)
5
+ def initialize(base)
6
6
  @attributes = []
7
- @klass = klass
8
- self.redefine_new(klass)
9
- self.define_attributes_method
7
+ @module = Module.new
8
+ @base = base
9
+ @base.send :include, @module
10
+ self.define_concstructable_attributes_method
10
11
  end
11
12
 
12
13
  def redefine_new(klass)
@@ -20,14 +21,13 @@ module Constructable
20
21
  end
21
22
  end
22
23
 
23
-
24
24
  def define_attributes(attributes)
25
25
  attributes = generate_attributes(attributes)
26
26
  @attributes.concat attributes
27
27
 
28
28
  attributes = @attributes
29
29
  attributes.each do |attribute|
30
- @klass.class_eval do
30
+ @module.module_eval do
31
31
  attr_reader attribute.name if attribute.readable
32
32
 
33
33
  define_method(:"#{attribute.name}=") do |value|
@@ -50,10 +50,10 @@ module Constructable
50
50
  end
51
51
  end
52
52
 
53
- def define_attributes_method
53
+ def define_concstructable_attributes_method
54
54
  constructor = self
55
- @klass.class_eval do
56
- define_method :attributes do
55
+ @base.module_eval do
56
+ define_method :constructable_attributes do
57
57
  Hash[
58
58
  constructor.attributes
59
59
  .map { |a| [a.name,instance_variable_get(a.ivar_symbol)] }
@@ -34,16 +34,17 @@ module Constructable
34
34
  #
35
35
  # @param [Array<[Array<Symbol, Hash>]>] args an array of symbols or arrays: the name of the attribute and it's configuration
36
36
  def constructable(*args)
37
+ @constructor ||= Constructor.new(self)
38
+ @constructor.define_attributes(args)
37
39
  case self
38
40
  when Class
39
- @constructor ||= Constructor.new(self)
40
- @constructor.define_attributes(args)
41
- return nil
41
+ @constructor.redefine_new(self)
42
42
  when Module
43
- define_singleton_method :included do |klass|
44
- klass.constructable *args
43
+ define_singleton_method :included do |base|
44
+ @constructor.redefine_new(base) if Class === base
45
45
  end
46
46
  end
47
+ return nil
47
48
  end
48
49
  end
49
50
  end
@@ -2,13 +2,6 @@ require 'helper'
2
2
  describe 'integration' do
3
3
  describe 'Class' do
4
4
  describe 'constructable' do
5
- it 'should define attr_accessors' do
6
- klass = Class.new
7
- klass.constructable([:foo, accessible: true])
8
- assert_respond_to klass.new, :foo
9
- assert_respond_to klass.new, :foo=
10
- end
11
-
12
5
  it 'should assign values found in the constructer hash' do
13
6
  klass = Class.new
14
7
  klass.constructable([:foo, readable: true])
@@ -45,17 +38,19 @@ describe 'integration' do
45
38
  assert_equal 20, instance.bar
46
39
  end
47
40
 
48
- it 'works for methods with only arguments provided' do
41
+ it 'works for initialize methods with arguments' do
49
42
  klass = Class.new
50
43
  klass.constructable [:bar, accessible: true]
44
+ klass.send :attr_accessor, :baz
51
45
  klass.class_eval do
52
- def initialize(bar)
53
- self.bar = bar
46
+ def initialize(baz, options = {})
47
+ self.baz = baz
54
48
  end
55
49
  end
56
50
 
57
- instance = klass.new(1)
58
- assert_equal 1, instance.bar
51
+ instance = klass.new(1, bar: 5)
52
+ assert_equal 1, instance.baz
53
+ assert_equal 5, instance.bar
59
54
  end
60
55
  end
61
56
 
@@ -2,9 +2,17 @@ require 'helper'
2
2
  describe 'Constructor' do
3
3
  before do
4
4
  @klass = Class.new
5
+ @module = Module.new
5
6
  end
6
7
 
7
8
  describe 'define_attributes' do
9
+ it 'should define attr_accessors' do
10
+ klass = Class.new
11
+ klass.constructable([:foo, accessible: true])
12
+ assert_respond_to klass.new, :foo
13
+ assert_respond_to klass.new, :foo=
14
+ end
15
+
8
16
  it 'defines public setters validating like in the constructor' do
9
17
  @klass.constructable [:integer, validate_type: Integer, writable: true]
10
18
  instance = @klass.new
@@ -12,13 +20,82 @@ describe 'Constructor' do
12
20
  instance.integer = 6.6
13
21
  end
14
22
  end
23
+
24
+ describe 'redefining' do
25
+
26
+ describe 'class' do
27
+ it 'getters ' do
28
+ @klass.constructable [:integer, validate_type: Integer, accessible: true]
29
+ @klass.class_eval { define_method(:integer){ 1 } }
30
+ instance = @klass.new(integer: 2)
31
+ assert_equal 1, instance.integer
32
+ end
33
+
34
+ it 'setters ' do
35
+ @klass.constructable [:integer, validate_type: Integer, accessible: true]
36
+ @klass.class_eval { def integer=(foo);@integer = 1;end }
37
+ instance = @klass.new(integer: 4)
38
+ instance.integer = 5
39
+ assert_equal 1, instance.integer
40
+ end
41
+ end
42
+
43
+ describe 'module' do
44
+ before do
45
+ @module.constructable [:integer, validate_type: Integer, accessible: true]
46
+ end
47
+
48
+ it 'getters ' do
49
+ @module.module_eval { def integer;1;end }
50
+ @klass.send :include,@module
51
+ instance = @klass.new(integer: 2)
52
+ assert_equal 1, instance.integer
53
+ end
54
+
55
+ it 'setters ' do
56
+ @module.module_eval { def integer=(foo);@integer = 1;end }
57
+ @klass.send :include,@module
58
+ instance = @klass.new(integer: 4)
59
+ instance.integer = 5
60
+ assert_equal 1, instance.integer
61
+ end
62
+
63
+ it 'also works for multiple inclusion' do
64
+ @module.module_eval { def integer=(foo);@integer = 1;end }
65
+ other_module = Module.new
66
+ other_module.send :include, @module
67
+ @klass.send :include, other_module
68
+ instance = @klass.new(integer: 4)
69
+ instance.integer = 5
70
+ assert_equal 1, instance.integer
71
+ end
72
+ end
73
+
74
+ describe 'allows to super to the generated method' do
75
+ it 'gets' do
76
+ @klass.constructable [:integer, validate_type: Integer, accessible: true]
77
+ @klass.class_eval { def integer; super ;end }
78
+ instance = @klass.new(integer: 2)
79
+ assert_equal 2, instance.integer
80
+ end
81
+
82
+ it 'sets' do
83
+ @klass.constructable [:integer, validate_type: Integer, accessible: true]
84
+ @klass.class_eval { def integer=(value); super ;end }
85
+ instance = @klass.new(integer: 2)
86
+ assert_raises Constructable::AttributeError do
87
+ instance.integer = :not_an_integer
88
+ end
89
+ end
90
+ end
91
+ end
15
92
  end
16
93
 
17
- describe 'Class#attributes' do
94
+ describe 'Class#constructable_attributes' do
18
95
  it 'returns the attribute matching the symbol' do
19
96
  @klass.constructable :foo, :bar
20
97
  instance = @klass.new(foo: 6)
21
- assert_equal({ foo: 6 }, instance.attributes)
98
+ assert_equal({ foo: 6 }, instance.constructable_attributes)
22
99
  end
23
100
  end
24
101
 
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: constructable
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.2.5
5
+ version: 0.3.0
6
6
  platform: ruby
7
7
  authors:
8
8
  - Manuel Korfmann
@@ -10,7 +10,7 @@ autorequire:
10
10
  bindir: bin
11
11
  cert_chain: []
12
12
 
13
- date: 2011-06-12 00:00:00 +02:00
13
+ date: 2011-06-15 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -103,7 +103,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
103
  requirements:
104
104
  - - ">="
105
105
  - !ruby/object:Gem::Version
106
- hash: 419636223836929306
106
+ hash: 830416941491402705
107
107
  segments:
108
108
  - 0
109
109
  version: "0"