constructable 0.2.5 → 0.3.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.
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"