constructable 0.1.0 → 0.2.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/README.markdown CHANGED
@@ -10,20 +10,20 @@ Provides a powerful class macro for defining and configuring constructable attri
10
10
  * Provides a granular control on how accessible your attributes are(no need to define attr_* yourself)
11
11
 
12
12
  ## Usage
13
- <pre><code>
13
+ ```ruby
14
14
  class Foo
15
15
  constructable [:bar, :readable => true], [:baz, :required => true, :readable => true]
16
16
  end
17
17
 
18
18
  foo = Foo.new(bar: 5)
19
- \# raises AttributeError, ':baz is a required attribute'
19
+ # raises AttributeError, ':baz is a required attribute'
20
20
 
21
21
  foo = Foo.new(baz: 7, bar: 5)
22
22
 
23
23
  foo.bar
24
- \# => 5
24
+ # => 5
25
25
  foo.baz
26
- \# => 7
26
+ # => 7
27
27
 
28
28
  class ProgrammingLanguage
29
29
  constructable [:paradigms,
@@ -33,12 +33,12 @@ class ProgrammingLanguage
33
33
  end
34
34
 
35
35
  c = ProgrammingLanguage.new(paradigms: :functional)
36
- \# raises AttributeError, ':paradigms needs to be of type Array'
36
+ # raises AttributeError, ':paradigms needs to be of type Array'
37
37
 
38
38
  ruby = ProgrammingLanguage.new(paradigms: [:object_oriented, :functional])
39
39
  ruby.paradigms
40
- \# => [:object_oriented, :functional]
41
- </pre></code>
40
+ # => [:object_oriented, :functional]
41
+ ```
42
42
 
43
43
 
44
44
  ## Contributing to constructable
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
@@ -0,0 +1,72 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = %q{constructable}
8
+ s.version = "0.2.0"
9
+
10
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
+ s.authors = ["Manuel Korfmann"]
12
+ s.date = %q{2011-06-09}
13
+ s.description = %q{
14
+ Adds the class macro Class#constructable to easily define what attributes a Class accepts provided as a hash to Class#new.
15
+ Attributes can be configured in their behaviour in case they are not provided or are in the wrong format.
16
+ Their default value can also be defined and you have granular control on how accessible your attribute is.
17
+ See the documentation for Constructable::Constructable#constructable or the README for more information.
18
+ }
19
+ s.email = %q{manu@korfmann.info}
20
+ s.extra_rdoc_files = [
21
+ "LICENSE.txt",
22
+ "README.markdown"
23
+ ]
24
+ s.files = [
25
+ ".document",
26
+ ".rvmrc",
27
+ ".travis.yml",
28
+ "Gemfile",
29
+ "LICENSE.txt",
30
+ "README.markdown",
31
+ "Rakefile",
32
+ "VERSION",
33
+ "constructable.gemspec",
34
+ "lib/constructable.rb",
35
+ "lib/constructable/attribute.rb",
36
+ "lib/constructable/constructable.rb",
37
+ "lib/constructable/constructor.rb",
38
+ "lib/constructable/core_ext.rb",
39
+ "lib/constructable/exceptions.rb",
40
+ "test/constructable/test_attribute.rb",
41
+ "test/constructable/test_constructable.rb",
42
+ "test/constructable/test_constructor.rb",
43
+ "test/helper.rb"
44
+ ]
45
+ s.homepage = %q{http://github.com/mkorfmann/constructable}
46
+ s.licenses = ["MIT"]
47
+ s.require_paths = ["lib"]
48
+ s.rubygems_version = %q{1.6.2}
49
+ s.summary = %q{Makes constructing objects through an attributes hash easier}
50
+
51
+ if s.respond_to? :specification_version then
52
+ s.specification_version = 3
53
+
54
+ if Gem::Version.new(Gem::VERSION) >= Gem::Version.new('1.2.0') then
55
+ s.add_development_dependency(%q<bundler>, ["~> 1.0.0"])
56
+ s.add_development_dependency(%q<jeweler>, ["~> 1.6.0"])
57
+ s.add_development_dependency(%q<simplecov>, [">= 0"])
58
+ s.add_development_dependency(%q<yard>, [">= 0"])
59
+ else
60
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
61
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
62
+ s.add_dependency(%q<simplecov>, [">= 0"])
63
+ s.add_dependency(%q<yard>, [">= 0"])
64
+ end
65
+ else
66
+ s.add_dependency(%q<bundler>, ["~> 1.0.0"])
67
+ s.add_dependency(%q<jeweler>, ["~> 1.6.0"])
68
+ s.add_dependency(%q<simplecov>, [">= 0"])
69
+ s.add_dependency(%q<yard>, [">= 0"])
70
+ end
71
+ end
72
+
@@ -1,7 +1,8 @@
1
1
  module Constructable
2
2
  class Attribute
3
- ATTRIBUTES = [:writable, :readable, :accessible, :required, :validate, :default, :validate_type, :converter]
3
+ ATTRIBUTES = [:group, :writable, :readable, :accessible, :required, :validate, :default, :validate_type, :converter]
4
4
  attr_accessor *ATTRIBUTES, :name
5
+ attr_reader :value
5
6
 
6
7
  REQUIRED_REQUIREMENT = {
7
8
  name: :required,
@@ -24,8 +25,8 @@ module Constructable
24
25
 
25
26
  def initialize(name, options = {})
26
27
  @name = name
27
- options.each do |option, value|
28
- self.send(:"#{option}=", value )
28
+ ATTRIBUTES.each do |attribute|
29
+ self.send(:"#{attribute}=", options[attribute])
29
30
  end
30
31
  end
31
32
 
@@ -59,7 +60,7 @@ module Constructable
59
60
  else
60
61
  check_for_requirement(REQUIRED_REQUIREMENT, constructor_hash)
61
62
  self.default
62
- end
63
+ end.tap { |value| @value = value }
63
64
  end
64
65
  end
65
66
  end
@@ -15,14 +15,25 @@ module Constructable
15
15
 
16
16
 
17
17
  def define_attributes(attributes)
18
- @attributes.concat attributes.map! { |c| Attribute.new(*c) }
18
+ attributes = generate_attributes(attributes)
19
+ @attributes.concat attributes
20
+
21
+ attributes = @attributes
19
22
  attributes.each do |attribute|
20
23
  @klass.class_eval do
21
- setter = :"#{attribute.name}="
22
- define_method(attribute.name) { instance_variable_get attribute.ivar_symbol }
23
- private attribute.name unless attribute.readable
24
- define_method(setter) { |value| instance_variable_set attribute.ivar_symbol, attribute.process({ attribute.name => value}) }
25
- private setter unless attribute.writable
24
+
25
+ attr_reader attribute.name if attribute.readable
26
+
27
+ define_method(:"#{attribute.name}=") do |value|
28
+ instance_variable_set attribute.ivar_symbol, attribute.process({ attribute.name => value})
29
+ end if attribute.writable
30
+
31
+ define_method(attribute.group) do
32
+ attributes.group_by(&:group)[attribute.group].inject({}) do |hash, attribute|
33
+ hash[attribute.name] = attribute.value
34
+ hash
35
+ end
36
+ end if attribute.group && !method_defined?(attribute.group)
26
37
  end
27
38
  end
28
39
  end
@@ -33,5 +44,19 @@ module Constructable
33
44
  obj.instance_variable_set(attributes.ivar_symbol, attributes.process(constructor_hash))
34
45
  end
35
46
  end
47
+
48
+ def generate_attributes(attributes)
49
+ attributes.map do |dynamic_args|
50
+ if Hash === dynamic_args
51
+ dynamic_args.map do |name, attributes|
52
+ attributes.map do |attribute|
53
+ Attribute.new(*attribute).tap { |a| a.group = dynamic_args.keys.first }
54
+ end
55
+ end
56
+ else
57
+ Attribute.new(*dynamic_args)
58
+ end
59
+ end.flatten
60
+ end
36
61
  end
37
62
  end
@@ -1,6 +1,17 @@
1
1
  require 'helper'
2
2
  include Constructable
3
3
  describe 'Attribute' do
4
+
5
+ describe 'value' do
6
+ it 'returns the last processed value' do
7
+ attribute = Attribute.new(:foo)
8
+ attribute.process({foo: :bar})
9
+ assert_equal :bar, attribute.value
10
+ attribute.process({foo: 1})
11
+ assert_equal 1, attribute.value
12
+ end
13
+ end
14
+
4
15
  describe 'name' do
5
16
  it 'returns the name' do
6
17
  attribute = Attribute.new(:attribute)
@@ -14,6 +14,26 @@ describe 'Constructor' do
14
14
  end
15
15
  end
16
16
 
17
+ describe 'Attribute#group' do
18
+ it 'returns attributes included in the group along with their values' do
19
+ @klass.constructable [:foo, group: :foobar], [:bar, group: :foobar]
20
+ instance = @klass.new(foo: 1, bar: 2)
21
+ assert_equal({foo: 1, bar: 2}, instance.foobar)
22
+ end
23
+
24
+ it 'ONLY returns attributes included in that group' do
25
+ @klass.constructable [:foo, group: :foobar], [:bar]
26
+ instance = @klass.new(foo: 1, bar: 2)
27
+ assert_equal({foo: 1}, instance.foobar)
28
+ end
29
+
30
+ it 'has a nice syntax' do
31
+ @klass.constructable foobar: [:foo, :bar]
32
+ instance = @klass.new(foo: 1, bar: 2)
33
+ assert_equal({foo: 1, bar: 2}, instance.foobar)
34
+ end
35
+ end
36
+
17
37
  describe 'permission' do
18
38
  it 'should allow writable attributes' do
19
39
  @klass.constructable [:writable_attribute, writable: true]
metadata CHANGED
@@ -2,7 +2,7 @@
2
2
  name: constructable
3
3
  version: !ruby/object:Gem::Version
4
4
  prerelease:
5
- version: 0.1.0
5
+ version: 0.2.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-08 00:00:00 +02:00
13
+ date: 2011-06-09 00:00:00 +02:00
14
14
  default_executable:
15
15
  dependencies:
16
16
  - !ruby/object:Gem::Dependency
@@ -79,6 +79,7 @@ files:
79
79
  - README.markdown
80
80
  - Rakefile
81
81
  - VERSION
82
+ - constructable.gemspec
82
83
  - lib/constructable.rb
83
84
  - lib/constructable/attribute.rb
84
85
  - lib/constructable/constructable.rb
@@ -103,7 +104,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
103
104
  requirements:
104
105
  - - ">="
105
106
  - !ruby/object:Gem::Version
106
- hash: 2461341662544041366
107
+ hash: -4108706002012057813
107
108
  segments:
108
109
  - 0
109
110
  version: "0"