attr_plus 0.3.0 → 0.4.1
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.md +148 -90
- data/lib/attr_plus.rb +4 -1
- data/lib/attr_plus/class.rb +10 -5
- data/lib/attr_plus/hash.rb +68 -0
- data/lib/attr_plus/version.rb +3 -0
- data/spec/attr_plus/class_inheirtable_spec.rb +108 -0
- data/spec/attr_plus/class_spec.rb +34 -93
- data/spec/attr_plus/hash_spec.rb +167 -0
- data/spec/attr_plus/instance_spec.rb +1 -1
- data/spec/attr_plus/module_spec.rb +4 -13
- data/spec/{class_attr_spec.rb → attr_plus_spec.rb} +0 -0
- data/spec/spec_helper.rb +6 -4
- data/spec/usage_spec.rb +121 -0
- metadata +12 -4
data/README.md
CHANGED
@@ -2,75 +2,79 @@
|
|
2
2
|
|
3
3
|
## ClassAttr
|
4
4
|
|
5
|
-
Adds
|
5
|
+
Adds `class_attr_accessor` (and reader/writer) and `inheritable_class_attr_accessor` (and
|
6
6
|
reader/writer of course) to Class.
|
7
7
|
|
8
|
-
|
8
|
+
``` ruby
|
9
|
+
require 'attr_plus'
|
9
10
|
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
|
16
|
-
|
17
|
-
|
18
|
-
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
|
24
|
-
|
25
|
-
|
26
|
-
|
27
|
-
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
11
|
+
class Polygon
|
12
|
+
class_attr_accessor :sides
|
13
|
+
end
|
14
|
+
|
15
|
+
Polygon.sides = 5
|
16
|
+
Polygon.sides #=> 5
|
17
|
+
|
18
|
+
class Square < Polygon
|
19
|
+
end
|
20
|
+
|
21
|
+
Square.sides #=> nil
|
22
|
+
|
23
|
+
|
24
|
+
class InheritablePolygon
|
25
|
+
inheritable_class_attr_accessor :sides
|
26
|
+
end
|
27
|
+
|
28
|
+
Polygon.sides = 4
|
29
|
+
|
30
|
+
class NewSquare < Polygon
|
31
|
+
end
|
32
|
+
|
33
|
+
Square.sides #=> 4
|
34
|
+
```
|
33
35
|
|
34
36
|
You can provide default values using a hash with :default set for the last value, or if just
|
35
37
|
creating one accessor/reader/writer add `=> defaultvalue` to the end, this example should
|
36
38
|
make it more clear:
|
37
39
|
|
38
|
-
|
39
|
-
|
40
|
-
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
40
|
+
``` ruby
|
41
|
+
require 'attr_plus/class'
|
42
|
+
|
43
|
+
class Person
|
44
|
+
class_attr_accessor :name => 'John Doe'
|
45
|
+
inheritable_class_attr_accessor :arms, :legs, :default => 2
|
46
|
+
inheritable_class_attr_accessor :fingers, :toes, :default => 5
|
47
|
+
end
|
48
|
+
|
49
|
+
class Agent < Person
|
50
|
+
@name = "James Bond"
|
51
|
+
end
|
52
|
+
|
53
|
+
Person.name #=> "John Doe"
|
54
|
+
Person.arms #=> 2
|
55
|
+
Person.toes #=> 5
|
56
|
+
Agent.name #=> "James Bond"
|
57
|
+
Agent.legs #=> 2
|
58
|
+
```
|
55
59
|
|
56
60
|
|
57
61
|
## ModuleAttr
|
58
62
|
|
59
|
-
Almost exactly the same as `class_*` but for modules.
|
60
|
-
so `inheritable_module_*` will not work, I am thinking of adding `includable_module_*` later
|
61
|
-
but they aren't in yet so can't be used!
|
63
|
+
Almost exactly the same as `class_*` but for modules.
|
62
64
|
|
63
|
-
|
65
|
+
``` ruby
|
66
|
+
require 'attr_plus/module'
|
64
67
|
|
65
|
-
|
66
|
-
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
68
|
+
module MyHouse
|
69
|
+
module_attr_accessor :width, :height, :default => 200
|
70
|
+
module_attr_accessor :rooms => []
|
71
|
+
module_attr_accessor :number, :street, :city, :country
|
72
|
+
end
|
73
|
+
|
74
|
+
House.width = 500
|
75
|
+
House.rooms = [:living_room, :kitchen]
|
76
|
+
House.rooms.first #=> :living_room
|
77
|
+
```
|
74
78
|
|
75
79
|
|
76
80
|
## Instance Extensions
|
@@ -78,52 +82,106 @@ but they aren't in yet so can't be used!
|
|
78
82
|
I've also added extensions to the methods for creating accessors on instances. These create
|
79
83
|
private versions, working exactly the same in every other way.
|
80
84
|
|
81
|
-
|
82
|
-
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
-
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
108
|
-
|
85
|
+
``` ruby
|
86
|
+
require 'attr_plus/instance'
|
87
|
+
|
88
|
+
class SecretBox
|
89
|
+
attr_writer :stuff
|
90
|
+
private_attr_reader :stuff
|
91
|
+
|
92
|
+
def initialize
|
93
|
+
@stuff = []
|
94
|
+
end
|
95
|
+
|
96
|
+
def <<(val)
|
97
|
+
stuff << val
|
98
|
+
end
|
99
|
+
|
100
|
+
def shake
|
101
|
+
stuff[rand(stuff.size)]
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
box = SecretBox.new
|
106
|
+
box << "giraffe"
|
107
|
+
box << "elephant"
|
108
|
+
box << "camel"
|
109
|
+
box << "cat"
|
110
|
+
p box.shake #=> "giraffe"
|
111
|
+
p box.stuff # NoMethodError: private method 'stuff' called
|
112
|
+
box.stuff = %w(dog hamster fish)
|
113
|
+
p box.shake #=> "fish"
|
114
|
+
```
|
109
115
|
|
110
116
|
And then as usual there are `private_attr_accessor` and `private_attr_writer` which work
|
111
117
|
as expected.
|
112
118
|
|
113
119
|
|
120
|
+
## HashAttr
|
121
|
+
|
122
|
+
You can now access specific keys of a hash using `hash_attr_*` or `class_hash_attr_*`. The
|
123
|
+
normal version will get the variable in an instance but the class version works at the class
|
124
|
+
level, for example,
|
125
|
+
|
126
|
+
``` ruby
|
127
|
+
require_relative 'lib/attr_plus/hash'
|
128
|
+
|
129
|
+
class SomeApp
|
130
|
+
@config = {:name => 'SomeApp', :version => '3.1.7'}
|
131
|
+
class_hash_attr_accessor :@config, :name, :version
|
132
|
+
|
133
|
+
def self.config; @config; end
|
134
|
+
end
|
135
|
+
|
136
|
+
p SomeApp.config #=> {:name => 'SomeApp', :version => '3.1.7'}
|
137
|
+
SomeApp.name = 'CoolApp'
|
138
|
+
p SomeApp.name #=> 'CoolApp'
|
139
|
+
SomeApp.version = '4.0.0'
|
140
|
+
p SomeApp.config #=> {:name => 'CoolApp', :version => '4.0.0'}
|
141
|
+
```
|
142
|
+
|
143
|
+
Uses the class versions, but it could easily be written using the normal versions (probably
|
144
|
+
the most usual way):
|
145
|
+
|
146
|
+
``` ruby
|
147
|
+
class AnApp
|
148
|
+
def initialize
|
149
|
+
@config = {}
|
150
|
+
end
|
151
|
+
|
152
|
+
hash_attr_accessor :@config, :name, :version
|
153
|
+
attr_accessor :config
|
154
|
+
end
|
155
|
+
|
156
|
+
some_app = AnApp.new
|
157
|
+
some_app.name = 'AnotherApp'
|
158
|
+
some_app.version = '1.5.0'
|
159
|
+
p some_app.config #=> {:name => 'AnotherApp', :version => '1.5.0'}
|
160
|
+
```
|
161
|
+
|
162
|
+
In both of these I've passed the instance variable as a symbol as the argument to get the hash
|
163
|
+
but I could have used just `:config` as I have create the methods in each. If the hash uses
|
164
|
+
string keys just pass the arguments to `.hash_attr_` as strings instead of symbols.
|
165
|
+
|
166
|
+
|
114
167
|
## Install
|
115
168
|
|
116
|
-
|
169
|
+
``` bash
|
170
|
+
$ (sudo) gem install attr_plus
|
171
|
+
```
|
117
172
|
|
118
173
|
|
119
174
|
## Use
|
120
175
|
|
121
|
-
|
122
|
-
|
123
|
-
|
124
|
-
|
125
|
-
|
126
|
-
|
176
|
+
``` ruby
|
177
|
+
require 'attr_plus'
|
178
|
+
|
179
|
+
# OR for specific methods
|
180
|
+
require 'attr_plus/class' # for only class_*
|
181
|
+
require 'attr_plus/module' # for only module_*
|
182
|
+
require 'attr_plus/hash' # for only hash_*
|
183
|
+
require 'attr_plus/instance' # for only private_attr_*
|
184
|
+
```
|
127
185
|
|
128
186
|
|
129
187
|
### Important!
|
data/lib/attr_plus.rb
CHANGED
data/lib/attr_plus/class.rb
CHANGED
@@ -3,15 +3,15 @@ require 'attr_plus/ext'
|
|
3
3
|
# Should add cattr_accessor, which provides accessors for @@ class
|
4
4
|
# variables!
|
5
5
|
|
6
|
-
|
7
6
|
class Class
|
8
7
|
|
9
8
|
# Defines a method that allows you to read an instance variable set at the
|
10
9
|
# class level. Also defines an _instance_ method that reads the same thing.
|
11
10
|
# Comparable to #attr_reader for the class level.
|
12
11
|
#
|
13
|
-
# So in summary defines:
|
14
|
-
#
|
12
|
+
# So in summary defines:
|
13
|
+
# - .var (which gets @var) and
|
14
|
+
# - #var (which gets self.class.var)
|
15
15
|
#
|
16
16
|
# @example
|
17
17
|
#
|
@@ -41,7 +41,7 @@ class Class
|
|
41
41
|
end
|
42
42
|
|
43
43
|
def #{name}
|
44
|
-
self.class.send(:#{name})
|
44
|
+
@#{name} ||= self.class.send(:#{name}).dup
|
45
45
|
end
|
46
46
|
EOS
|
47
47
|
self.instance_variable_set("@#{name}", (default.dup rescue default))
|
@@ -75,6 +75,10 @@ class Class
|
|
75
75
|
def self.#{name}=(obj)
|
76
76
|
@#{name} = obj
|
77
77
|
end
|
78
|
+
|
79
|
+
def #{name}=(obj)
|
80
|
+
@#{name} = obj
|
81
|
+
end
|
78
82
|
EOS
|
79
83
|
end
|
80
84
|
end
|
@@ -101,6 +105,7 @@ class Class
|
|
101
105
|
class_attr_writer(*names)
|
102
106
|
end
|
103
107
|
|
108
|
+
|
104
109
|
# Creates a class and instance method to read the class level variable(s)
|
105
110
|
# with the name(s) provided. If no value has been set it attempts to use
|
106
111
|
# the value of the superclass.
|
@@ -120,7 +125,7 @@ class Class
|
|
120
125
|
end
|
121
126
|
|
122
127
|
def #{name}
|
123
|
-
self.class.send(:#{name})
|
128
|
+
@#{name} ||= self.class.send(:#{name})
|
124
129
|
end
|
125
130
|
EOS
|
126
131
|
self.instance_variable_set("@#{name}", (default.dup rescue default))
|
@@ -0,0 +1,68 @@
|
|
1
|
+
class Module
|
2
|
+
|
3
|
+
# @param var [Symbol]
|
4
|
+
# Instance variable as a symbol, or method symbol to call which returns
|
5
|
+
# a hash.
|
6
|
+
#
|
7
|
+
# @param args [Symbol]
|
8
|
+
# Keys for +var+, these will have methods set up for retrieving them.
|
9
|
+
#
|
10
|
+
def hash_attr_reader(var, *args)
|
11
|
+
args.each do |arg|
|
12
|
+
self.class_eval <<-EOS
|
13
|
+
def #{arg}
|
14
|
+
#{var}[#{arg.inspect}]
|
15
|
+
end
|
16
|
+
EOS
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
# @param var [Symbol]
|
21
|
+
# Instance variable as a symbol, or method symbol to call which returns
|
22
|
+
# a hash.
|
23
|
+
#
|
24
|
+
# @param args [Symbol]
|
25
|
+
# Keys for +var+, these will have methods set up for writing to.
|
26
|
+
#
|
27
|
+
def hash_attr_writer(var, *args)
|
28
|
+
args.each do |arg|
|
29
|
+
self.class_eval <<-EOS
|
30
|
+
def #{arg}=(val)
|
31
|
+
#{var}[#{arg.inspect}] = val
|
32
|
+
end
|
33
|
+
EOS
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def hash_attr_accessor(*args)
|
38
|
+
hash_attr_reader(*args)
|
39
|
+
hash_attr_writer(*args)
|
40
|
+
end
|
41
|
+
|
42
|
+
# Like #hash_attr_accessor but creates class methods
|
43
|
+
def class_hash_attr_accessor(*args)
|
44
|
+
class_hash_attr_reader(*args)
|
45
|
+
class_hash_attr_writer(*args)
|
46
|
+
end
|
47
|
+
|
48
|
+
def class_hash_attr_reader(var, *args)
|
49
|
+
args.each do |arg|
|
50
|
+
self.instance_eval <<-EOS
|
51
|
+
def #{arg}
|
52
|
+
#{var}[#{arg.inspect}]
|
53
|
+
end
|
54
|
+
EOS
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
def class_hash_attr_writer(var, *args)
|
59
|
+
args.each do |arg|
|
60
|
+
self.instance_eval <<-EOS
|
61
|
+
def #{arg}=(val)
|
62
|
+
#{var}[#{arg.inspect}] = val
|
63
|
+
end
|
64
|
+
EOS
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
end
|
@@ -0,0 +1,108 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
|
4
|
+
describe "Class" do
|
5
|
+
|
6
|
+
|
7
|
+
describe ".inheritable_class_attr_reader" do
|
8
|
+
subject { Class.new { inheritable_class_attr_reader :test } }
|
9
|
+
|
10
|
+
it "defines a read method for the class" do
|
11
|
+
subject.should respond_to :test
|
12
|
+
end
|
13
|
+
|
14
|
+
it "defines a read method for instances of the class" do
|
15
|
+
subject.new.should respond_to :test
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
describe ".inheritable_class_attr_writer" do
|
20
|
+
subject { Class.new { inheritable_class_attr_writer :test } }
|
21
|
+
|
22
|
+
it "defines a write method for the class" do
|
23
|
+
subject.should respond_to :test=
|
24
|
+
end
|
25
|
+
|
26
|
+
it "defines a write method for instances of the class" do
|
27
|
+
subject.new.should respond_to :test=
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
describe ".inheritable_class_attr_accessor" do
|
32
|
+
subject { Class.new { inheritable_class_attr_accessor :test } }
|
33
|
+
|
34
|
+
it "defines a read method for the class" do
|
35
|
+
subject.should respond_to :test
|
36
|
+
end
|
37
|
+
|
38
|
+
it "defines a write method for the class" do
|
39
|
+
subject.should respond_to :test=
|
40
|
+
end
|
41
|
+
|
42
|
+
it "defines a read method for instances of the class" do
|
43
|
+
subject.new.should respond_to :test
|
44
|
+
end
|
45
|
+
|
46
|
+
it "defines a write method for instances of the class" do
|
47
|
+
subject.new.should respond_to :test=
|
48
|
+
end
|
49
|
+
end
|
50
|
+
|
51
|
+
context "When there is a subclass of a class with inheritable_class_attrs" do
|
52
|
+
|
53
|
+
let(:sup) { Class.new { inheritable_class_attr_accessor :test } }
|
54
|
+
let(:sub) { Class.new(sup) }
|
55
|
+
|
56
|
+
it "has the methods of the superclass" do
|
57
|
+
sub.should respond_to :test
|
58
|
+
sub.should respond_to :test=
|
59
|
+
end
|
60
|
+
|
61
|
+
describe "calling the writer method on the subclass" do
|
62
|
+
it "should not alter the value on the superclass" do
|
63
|
+
sub.test = "changed"
|
64
|
+
sub.test.should == "changed"
|
65
|
+
sup.test.should_not == "changed"
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
describe "calling the writer method on the superclass" do
|
70
|
+
it "should alter the value on the subclass if not set" do
|
71
|
+
sup.test = "changed it"
|
72
|
+
sup.test.should == "changed it"
|
73
|
+
sub.test.should == "changed it"
|
74
|
+
end
|
75
|
+
|
76
|
+
it "should not alter the value on the subclass if set" do
|
77
|
+
sub.test = "already set"
|
78
|
+
sup.test = "change it"
|
79
|
+
sup.test.should == "change it"
|
80
|
+
sub.test.should == "already set"
|
81
|
+
end
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
context "When given a default value" do
|
86
|
+
|
87
|
+
subject { Class.new { class_attr_accessor :test => "hi" } }
|
88
|
+
|
89
|
+
it "returns the default value before it is changed" do
|
90
|
+
subject.test.should == "hi"
|
91
|
+
end
|
92
|
+
|
93
|
+
it "returns the new value if it is changed" do
|
94
|
+
subject.test = nil
|
95
|
+
subject.test.should be_nil
|
96
|
+
end
|
97
|
+
|
98
|
+
context "When this class is inherited" do
|
99
|
+
let(:sub) { Class.new(subject) }
|
100
|
+
|
101
|
+
it "returns the default value as well" do
|
102
|
+
sub.test.should == "hi"
|
103
|
+
end
|
104
|
+
end
|
105
|
+
|
106
|
+
end
|
107
|
+
|
108
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Class do
|
3
|
+
describe "Class" do
|
4
4
|
|
5
5
|
describe ".class_attr_reader" do
|
6
6
|
subject { Class.new { class_attr_reader :test } }
|
@@ -20,6 +20,10 @@ describe Class do
|
|
20
20
|
it "defines a write method for the class" do
|
21
21
|
subject.should respond_to :test=
|
22
22
|
end
|
23
|
+
|
24
|
+
it "defines a write method for instances of the class" do
|
25
|
+
subject.new.should respond_to :test=
|
26
|
+
end
|
23
27
|
end
|
24
28
|
|
25
29
|
describe ".class_attr_accessor" do
|
@@ -36,8 +40,15 @@ describe Class do
|
|
36
40
|
it "defines a read method for instances of the class" do
|
37
41
|
subject.new.should respond_to :test
|
38
42
|
end
|
43
|
+
|
44
|
+
it "defines a write method for instances of the class" do
|
45
|
+
subject.new.should respond_to :test=
|
46
|
+
end
|
39
47
|
end
|
40
48
|
|
49
|
+
|
50
|
+
# EDGE CASES, specifically where I've had issues in the past so need to check against
|
51
|
+
|
41
52
|
# The subclass thing was starting to annoy me...
|
42
53
|
context "When there is a subclass of a class with class_attrs" do
|
43
54
|
|
@@ -65,108 +76,38 @@ describe Class do
|
|
65
76
|
end
|
66
77
|
end
|
67
78
|
end
|
68
|
-
|
69
|
-
|
70
|
-
# Inheritable class attributes
|
71
|
-
|
72
|
-
describe ".inheritable_class_attr_reader" do
|
73
|
-
subject { Class.new { inheritable_class_attr_reader :test } }
|
74
|
-
|
75
|
-
it "defines a read method for the class" do
|
76
|
-
subject.should respond_to :test
|
77
|
-
end
|
78
|
-
|
79
|
-
it "defines a read method for instances of the class" do
|
80
|
-
subject.new.should respond_to :test
|
81
|
-
end
|
82
|
-
end
|
83
79
|
|
84
|
-
describe ".inheritable_class_attr_writer" do
|
85
|
-
subject { Class.new { inheritable_class_attr_writer :test } }
|
86
|
-
|
87
|
-
it "defines a write method for the class" do
|
88
|
-
subject.should respond_to :test=
|
89
|
-
end
|
90
|
-
end
|
91
|
-
|
92
|
-
describe ".inheritable_class_attr_accessor" do
|
93
|
-
subject { Class.new { inheritable_class_attr_accessor :test } }
|
94
80
|
|
95
|
-
|
96
|
-
subject.should respond_to :test
|
97
|
-
end
|
98
|
-
|
99
|
-
it "defines a write method for the class" do
|
100
|
-
subject.should respond_to :test=
|
101
|
-
end
|
102
|
-
|
103
|
-
it "defines a read method for instances of the class" do
|
104
|
-
subject.new.should respond_to :test
|
105
|
-
end
|
106
|
-
end
|
81
|
+
context "When there are multiple instances of a class with class_attrs" do
|
107
82
|
|
108
|
-
|
83
|
+
subject { Class.new { class_attr_accessor :attrs } }
|
84
|
+
let(:obj1) { subject.new }
|
85
|
+
let(:obj2) { subject.new }
|
109
86
|
|
110
|
-
|
111
|
-
|
112
|
-
|
113
|
-
|
114
|
-
|
115
|
-
|
116
|
-
end
|
117
|
-
|
118
|
-
describe "calling the writer method on the subclass" do
|
119
|
-
it "should not alter the value on the superclass" do
|
120
|
-
sub.test = "changed"
|
121
|
-
sub.test.should == "changed"
|
122
|
-
sup.test.should_not == "changed"
|
123
|
-
end
|
124
|
-
end
|
125
|
-
|
126
|
-
describe "calling the writer method on the superclass" do
|
127
|
-
it "should alter the value on the subclass if not set" do
|
128
|
-
sup.test = "changed it"
|
129
|
-
sup.test.should == "changed it"
|
130
|
-
sub.test.should == "changed it"
|
87
|
+
describe "the class" do
|
88
|
+
it "should not be affected by changes to the objects" do
|
89
|
+
subject.attrs = %w(coolness)
|
90
|
+
obj1.attrs = %w(height weight)
|
91
|
+
obj2.attrs = %w(volume density)
|
92
|
+
subject.attrs.should == %w(coolness)
|
131
93
|
end
|
132
94
|
|
133
|
-
it "should not
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
95
|
+
it "should not affect objects when they have been changed" do
|
96
|
+
obj1.attrs = %w(name)
|
97
|
+
obj2.attrs = %w(date)
|
98
|
+
subject.attrs = %w(mass)
|
99
|
+
obj1.attrs.should == %w(name)
|
100
|
+
obj2.attrs.should == %w(date)
|
138
101
|
end
|
139
|
-
end
|
140
|
-
end
|
141
|
-
|
142
|
-
context "When given a default value" do
|
143
|
-
|
144
|
-
subject { Class.new { class_attr_accessor :test => "hi" } }
|
145
|
-
|
146
|
-
it "returns the default value before it is changed" do
|
147
|
-
subject.test.should == "hi"
|
148
|
-
end
|
149
|
-
|
150
|
-
it "returns the new value if it is changed" do
|
151
|
-
subject.test = nil
|
152
|
-
subject.test.should be_nil
|
153
|
-
end
|
154
|
-
|
155
|
-
context "When this class is inherited" do
|
156
|
-
let(:sub) { Class.new(subject) }
|
157
102
|
|
158
|
-
it "
|
159
|
-
|
103
|
+
it "should affect objects when they have not been changed" do
|
104
|
+
obj1.attrs = %w(hp)
|
105
|
+
subject.attrs = %w(mp)
|
106
|
+
obj1.attrs.should == %w(hp)
|
107
|
+
obj2.attrs.should == %w(mp)
|
160
108
|
end
|
161
109
|
end
|
162
|
-
|
163
|
-
end
|
164
|
-
|
165
|
-
|
166
|
-
# Class Variables
|
167
|
-
|
168
|
-
describe ".cattr_accessor" do
|
169
110
|
|
170
111
|
end
|
171
|
-
|
112
|
+
|
172
113
|
end
|
@@ -0,0 +1,167 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Hash" do
|
4
|
+
|
5
|
+
describe '.hash_attr_reader' do
|
6
|
+
subject {
|
7
|
+
Class.new {
|
8
|
+
hash_attr_reader :@config, :name
|
9
|
+
def initialize
|
10
|
+
@config = {:name => "John Doe"}
|
11
|
+
end
|
12
|
+
}.new
|
13
|
+
}
|
14
|
+
|
15
|
+
it "creates the reader method" do
|
16
|
+
subject.should respond_to :name
|
17
|
+
end
|
18
|
+
|
19
|
+
it "gets the value from the correct hash" do
|
20
|
+
subject.name.should == "John Doe"
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
describe '.hash_attr_writer' do
|
25
|
+
subject {
|
26
|
+
Class.new {
|
27
|
+
attr_reader :config
|
28
|
+
hash_attr_writer :@config, :name
|
29
|
+
def initialize
|
30
|
+
@config = {}
|
31
|
+
end
|
32
|
+
}.new
|
33
|
+
}
|
34
|
+
|
35
|
+
it "creates the writer method" do
|
36
|
+
subject.should respond_to :name=
|
37
|
+
end
|
38
|
+
|
39
|
+
it "sets the value in the hash" do
|
40
|
+
subject.name = "John Doe"
|
41
|
+
subject.config[:name].should == "John Doe"
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
describe '.hash_attr_accessor' do
|
47
|
+
subject {
|
48
|
+
Class.new {
|
49
|
+
attr_reader :config
|
50
|
+
hash_attr_accessor :@config, :name, :age
|
51
|
+
def initialize
|
52
|
+
@config = {
|
53
|
+
:name => 'John Doe',
|
54
|
+
:age => 21
|
55
|
+
}
|
56
|
+
end
|
57
|
+
}.new
|
58
|
+
}
|
59
|
+
|
60
|
+
it "creates the methods" do
|
61
|
+
subject.should respond_to :name
|
62
|
+
subject.should respond_to :age
|
63
|
+
subject.should respond_to :name=
|
64
|
+
subject.should respond_to :age=
|
65
|
+
end
|
66
|
+
|
67
|
+
it "allows you to read values" do
|
68
|
+
subject.name.should == 'John Doe'
|
69
|
+
subject.age.should == 21
|
70
|
+
end
|
71
|
+
|
72
|
+
it "allows you to set values" do
|
73
|
+
subject.name = 'Dave Jones'
|
74
|
+
subject.age = 59
|
75
|
+
subject.config.should == {:name => 'Dave Jones', :age => 59}
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
|
80
|
+
describe '.class_hash_attr_reader' do
|
81
|
+
subject {
|
82
|
+
Class.new {
|
83
|
+
@config = {:name => 'John Doe'}
|
84
|
+
class_hash_attr_reader :@config, :name
|
85
|
+
}
|
86
|
+
}
|
87
|
+
|
88
|
+
it "creates the reader method" do
|
89
|
+
subject.should respond_to :name
|
90
|
+
end
|
91
|
+
|
92
|
+
it "gets the value from the correct hash" do
|
93
|
+
subject.name.should == "John Doe"
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
describe '.class_hash_attr_writer' do
|
98
|
+
subject {
|
99
|
+
Class.new {
|
100
|
+
@config = {}
|
101
|
+
class_hash_attr_writer :@config, :name
|
102
|
+
class << self; attr_accessor :config; end
|
103
|
+
}
|
104
|
+
}
|
105
|
+
|
106
|
+
it "creates the writer method" do
|
107
|
+
subject.should respond_to :name=
|
108
|
+
end
|
109
|
+
|
110
|
+
it "sets the value in the hash" do
|
111
|
+
subject.name = "John Doe"
|
112
|
+
subject.config[:name].should == "John Doe"
|
113
|
+
end
|
114
|
+
end
|
115
|
+
|
116
|
+
describe '.hash_attr_accessor' do
|
117
|
+
subject {
|
118
|
+
Class.new {
|
119
|
+
class << self; attr_reader :config; end
|
120
|
+
class_hash_attr_accessor :@config, :name, :age
|
121
|
+
@config = {
|
122
|
+
:name => 'John Doe',
|
123
|
+
:age => 21
|
124
|
+
}
|
125
|
+
}
|
126
|
+
}
|
127
|
+
|
128
|
+
it "creates the methods" do
|
129
|
+
subject.should respond_to :name
|
130
|
+
subject.should respond_to :age
|
131
|
+
subject.should respond_to :name=
|
132
|
+
subject.should respond_to :age=
|
133
|
+
end
|
134
|
+
|
135
|
+
it "allows you to read values" do
|
136
|
+
subject.name.should == 'John Doe'
|
137
|
+
subject.age.should == 21
|
138
|
+
end
|
139
|
+
|
140
|
+
it "allows you to set values" do
|
141
|
+
subject.name = 'Dave Jones'
|
142
|
+
subject.age = 59
|
143
|
+
subject.config.should == {:name => 'Dave Jones', :age => 59}
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
context 'When using string keys' do
|
148
|
+
subject {
|
149
|
+
Class.new {
|
150
|
+
hash_attr_accessor :@config, 'name'
|
151
|
+
def initialize
|
152
|
+
@config = {'name' => "John Doe"}
|
153
|
+
end
|
154
|
+
}.new
|
155
|
+
}
|
156
|
+
|
157
|
+
it "allows access to values" do
|
158
|
+
subject.name.should == 'John Doe'
|
159
|
+
end
|
160
|
+
|
161
|
+
it "allows values to be set" do
|
162
|
+
subject.name = 'Tom'
|
163
|
+
subject.name.should == 'Tom'
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
end
|
@@ -1,6 +1,6 @@
|
|
1
1
|
require 'spec_helper'
|
2
2
|
|
3
|
-
describe Module do
|
3
|
+
describe "Module" do
|
4
4
|
|
5
5
|
describe "#module_attr_reader" do
|
6
6
|
subject { Module.new { module_attr_reader :test } }
|
@@ -38,18 +38,9 @@ describe Module do
|
|
38
38
|
end
|
39
39
|
|
40
40
|
it "returns the new value if it is changed" do
|
41
|
-
subject.test =
|
42
|
-
subject.test.should
|
43
|
-
end
|
44
|
-
|
45
|
-
context "when this module is included" do
|
46
|
-
subject { Class.new { include Module.new { module_attr_accessor :test => "hi" } } }
|
47
|
-
|
48
|
-
it "returns the default value as well" do
|
49
|
-
subject.test.should == "hi"
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
41
|
+
subject.test = "bye"
|
42
|
+
subject.test.should == "bye"
|
43
|
+
end
|
53
44
|
end
|
54
45
|
|
55
46
|
end
|
File without changes
|
data/spec/spec_helper.rb
CHANGED
@@ -1,11 +1,13 @@
|
|
1
1
|
if RUBY_VERSION >= "1.9"
|
2
2
|
require 'duvet'
|
3
|
-
Duvet.start :filter => '
|
3
|
+
Duvet.start :filter => 'attr_plus/lib'
|
4
4
|
end
|
5
5
|
|
6
6
|
require 'rspec'
|
7
7
|
require 'attr_plus'
|
8
8
|
|
9
|
-
RSpec.configure do |
|
10
|
-
|
11
|
-
|
9
|
+
RSpec.configure do |c|
|
10
|
+
c.color_enabled = true
|
11
|
+
c.filter_run :focus => true
|
12
|
+
c.run_all_when_everything_filtered = true
|
13
|
+
end
|
data/spec/usage_spec.rb
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Using a class level instance hash to hold config" do
|
4
|
+
|
5
|
+
subject {
|
6
|
+
Class.new {
|
7
|
+
@config = {:name => 'SomeApp', :version => '3.1.7'}
|
8
|
+
def self.config; @config; end
|
9
|
+
class_hash_attr_accessor :config, :name, :version
|
10
|
+
}
|
11
|
+
}
|
12
|
+
|
13
|
+
it "should get the values" do
|
14
|
+
subject.config.should == {:name => 'SomeApp', :version => '3.1.7'}
|
15
|
+
subject.name.should == 'SomeApp'
|
16
|
+
subject.version.should == '3.1.7'
|
17
|
+
end
|
18
|
+
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "Using an instance level hash to hold config" do
|
22
|
+
|
23
|
+
subject {
|
24
|
+
Class.new {
|
25
|
+
def initialize; @config = {}; end
|
26
|
+
attr_accessor :config
|
27
|
+
hash_attr_accessor :config, :name, :version
|
28
|
+
}.new
|
29
|
+
}
|
30
|
+
|
31
|
+
it "should get the values" do
|
32
|
+
subject.name = 'SomeApp'
|
33
|
+
subject.version = '1.5.0'
|
34
|
+
subject.config.should == {:name => 'SomeApp', :version => '1.5.0'}
|
35
|
+
end
|
36
|
+
|
37
|
+
end
|
38
|
+
|
39
|
+
|
40
|
+
describe "Putting things in a box" do
|
41
|
+
|
42
|
+
subject {
|
43
|
+
Class.new {
|
44
|
+
attr_writer :stuff
|
45
|
+
private_attr_reader :stuff
|
46
|
+
|
47
|
+
def initialize
|
48
|
+
@stuff = []
|
49
|
+
end
|
50
|
+
|
51
|
+
def <<(val)
|
52
|
+
stuff << val
|
53
|
+
end
|
54
|
+
|
55
|
+
def shake
|
56
|
+
stuff[rand(stuff.size)]
|
57
|
+
end
|
58
|
+
}.new
|
59
|
+
}
|
60
|
+
|
61
|
+
it "should work" do
|
62
|
+
subject << "giraffe"
|
63
|
+
subject << "elephant"
|
64
|
+
subject << "camel"
|
65
|
+
subject << "cat"
|
66
|
+
%w(giraffe elephant camel cat).should include subject.shake
|
67
|
+
expect { subject.stuff }.to raise_error NoMethodError
|
68
|
+
subject.stuff = %w(dog hamster fish)
|
69
|
+
%w(dog hamster fish).should include subject.shake
|
70
|
+
end
|
71
|
+
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
describe "Storing lists of attributes for a class" do
|
76
|
+
|
77
|
+
before {
|
78
|
+
@file = Class.new {
|
79
|
+
inheritable_class_attr_accessor :keys => []
|
80
|
+
def self.attr(*attrs)
|
81
|
+
keys.concat attrs
|
82
|
+
end
|
83
|
+
attr :url, :permalink, :path, :content
|
84
|
+
}
|
85
|
+
|
86
|
+
@page = Class.new(@file) { attr :title }
|
87
|
+
@post = Class.new(@page) { attr :date, :tags }
|
88
|
+
}
|
89
|
+
|
90
|
+
it "should work" do
|
91
|
+
@file.keys.should == [:url, :permalink, :path, :content]
|
92
|
+
@page.keys.should == [:url, :permalink, :path, :content, :title]
|
93
|
+
@post.keys.should == [:url, :permalink, :path, :content, :title, :date, :tags]
|
94
|
+
end
|
95
|
+
end
|
96
|
+
|
97
|
+
|
98
|
+
describe "A set of polygons" do
|
99
|
+
|
100
|
+
before {
|
101
|
+
@polygon = Class.new {
|
102
|
+
class_attr_writer :sides
|
103
|
+
def self.triangle?; @sides == 3; end
|
104
|
+
def self.rectangle?; @sides == 4; end
|
105
|
+
def self.pentagon?; @sides == 5; end
|
106
|
+
def self.nothing?; @sides.nil?; end
|
107
|
+
}
|
108
|
+
|
109
|
+
@triangle = Class.new(@polygon) { @sides = 3 }
|
110
|
+
@rectangle = Class.new(@polygon) { @sides = 4 }
|
111
|
+
@pentagon = Class.new(@polygon) { @sides = 5 }
|
112
|
+
}
|
113
|
+
|
114
|
+
it "should work" do
|
115
|
+
@triangle.should be_a_triangle
|
116
|
+
@rectangle.should be_a_rectangle
|
117
|
+
@pentagon.should be_a_pentagon
|
118
|
+
@polygon.should be_nothing
|
119
|
+
end
|
120
|
+
|
121
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: attr_plus
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.4.1
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-
|
12
|
+
date: 2011-06-08 00:00:00.000000000 +01:00
|
13
13
|
default_executable:
|
14
14
|
dependencies: []
|
15
15
|
description: ! " Provides attr_accessor style methods for easily creating methods
|
@@ -24,15 +24,20 @@ files:
|
|
24
24
|
- LICENSE
|
25
25
|
- lib/attr_plus/class.rb
|
26
26
|
- lib/attr_plus/ext.rb
|
27
|
+
- lib/attr_plus/hash.rb
|
27
28
|
- lib/attr_plus/instance.rb
|
28
29
|
- lib/attr_plus/module.rb
|
30
|
+
- lib/attr_plus/version.rb
|
29
31
|
- lib/attr_plus.rb
|
30
32
|
- lib/class_attr.rb
|
33
|
+
- spec/attr_plus/class_inheirtable_spec.rb
|
31
34
|
- spec/attr_plus/class_spec.rb
|
35
|
+
- spec/attr_plus/hash_spec.rb
|
32
36
|
- spec/attr_plus/instance_spec.rb
|
33
37
|
- spec/attr_plus/module_spec.rb
|
34
|
-
- spec/
|
38
|
+
- spec/attr_plus_spec.rb
|
35
39
|
- spec/spec_helper.rb
|
40
|
+
- spec/usage_spec.rb
|
36
41
|
has_rdoc: false
|
37
42
|
homepage: http://github.com/hawx/attr_plus
|
38
43
|
licenses: []
|
@@ -59,8 +64,11 @@ signing_key:
|
|
59
64
|
specification_version: 3
|
60
65
|
summary: attr_accessor for class and module level instance variables.
|
61
66
|
test_files:
|
67
|
+
- spec/attr_plus/class_inheirtable_spec.rb
|
62
68
|
- spec/attr_plus/class_spec.rb
|
69
|
+
- spec/attr_plus/hash_spec.rb
|
63
70
|
- spec/attr_plus/instance_spec.rb
|
64
71
|
- spec/attr_plus/module_spec.rb
|
65
|
-
- spec/
|
72
|
+
- spec/attr_plus_spec.rb
|
66
73
|
- spec/spec_helper.rb
|
74
|
+
- spec/usage_spec.rb
|