attr_plus 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/LICENSE +17 -0
- data/README.md +81 -0
- data/lib/attr_plus.rb +3 -0
- data/lib/attr_plus/class.rb +222 -0
- data/lib/attr_plus/ext.rb +20 -0
- data/lib/attr_plus/instance.rb +0 -0
- data/lib/attr_plus/module.rb +33 -0
- data/lib/class_attr.rb +3 -0
- data/spec/attr_plus/class_spec.rb +165 -0
- data/spec/attr_plus/module_spec.rb +55 -0
- data/spec/class_attr_spec.rb +29 -0
- data/spec/spec_helper.rb +11 -0
- metadata +78 -0
data/LICENSE
ADDED
@@ -0,0 +1,17 @@
|
|
1
|
+
Copyright (c) 2011 Joshua Hawxwell
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, there are
|
9
|
+
no conditions to fulfill.
|
10
|
+
|
11
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
12
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
13
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
14
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
15
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
16
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
17
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,81 @@
|
|
1
|
+
# ClassAttr
|
2
|
+
|
3
|
+
Adds `#class_attr_accessor` (and reader/writer) and `#inheritable_class_attr_accessor` (and
|
4
|
+
reader/writer of course) to Class.
|
5
|
+
|
6
|
+
class Polygon
|
7
|
+
class_attr_accessor :sides
|
8
|
+
end
|
9
|
+
|
10
|
+
Polygon.sides = 5
|
11
|
+
Polygon.sides #=> 5
|
12
|
+
|
13
|
+
class Square < Polygon
|
14
|
+
end
|
15
|
+
|
16
|
+
Square.sides #=> nil
|
17
|
+
|
18
|
+
|
19
|
+
class InheritablePolygon
|
20
|
+
inheritable_class_attr_accessor :sides
|
21
|
+
end
|
22
|
+
|
23
|
+
Polygon.sides = 4
|
24
|
+
|
25
|
+
class NewSquare < Polygon
|
26
|
+
end
|
27
|
+
|
28
|
+
Square.sides #=> 4
|
29
|
+
|
30
|
+
You can provide default values using a hash with :default set for the last value, or if just
|
31
|
+
creating one accessor/reader/writer add `=> defaultvalue` to the end, this example should
|
32
|
+
make it more clear:
|
33
|
+
|
34
|
+
class Person
|
35
|
+
class_attr_accessor :name => 'John Doe'
|
36
|
+
inheritable_class_attr_accessor :arms, :legs, :default => 2
|
37
|
+
inheritable_class_attr_accessor :fingers, :toes, :default => 5
|
38
|
+
end
|
39
|
+
|
40
|
+
class Agent < Person
|
41
|
+
@name = "James Bond"
|
42
|
+
end
|
43
|
+
|
44
|
+
Person.name #=> "John Doe"
|
45
|
+
Person.arms #=> 2
|
46
|
+
Person.toes #=> 5
|
47
|
+
Agent.name #=> "James Bond"
|
48
|
+
Agent.legs #=> 2
|
49
|
+
|
50
|
+
|
51
|
+
## Install
|
52
|
+
|
53
|
+
(sudo) gem install class_attr
|
54
|
+
|
55
|
+
|
56
|
+
## Use
|
57
|
+
|
58
|
+
require 'class_attr'
|
59
|
+
|
60
|
+
Or, as in some cases this may be overkill, copy the parts you need over (you will need to modify it,
|
61
|
+
but that should be easy to work out.)
|
62
|
+
|
63
|
+
|
64
|
+
### Important!
|
65
|
+
|
66
|
+
If in a class you define the `self.inherited` method, make sure to call super at the end (or beginning)
|
67
|
+
otherwise default values will not be set for the subclass. But I'm guessing you already called super
|
68
|
+
anyway in a method like that.
|
69
|
+
|
70
|
+
|
71
|
+
## Thanks
|
72
|
+
|
73
|
+
- <http://railstips.org/blog/archives/2006/11/18/class-and-instance-variables-in-ruby/>
|
74
|
+
For originally demystifying the class instance variable thing.
|
75
|
+
- <http://www.raulparolari.com/Rails/class_inheritable> For ideas on how to implement
|
76
|
+
class level attribute accessors which inherit values.
|
77
|
+
|
78
|
+
|
79
|
+
## Copyright
|
80
|
+
|
81
|
+
Copyright (c) 2010 Joshua Hawxwell. See LICENSE for details.
|
data/lib/attr_plus.rb
ADDED
@@ -0,0 +1,222 @@
|
|
1
|
+
require 'attr_plus/ext'
|
2
|
+
|
3
|
+
class Class
|
4
|
+
|
5
|
+
# Defines a method that allows you to read an instance variable set at the
|
6
|
+
# class level. Also defines an _instance_ method that reads the same thing.
|
7
|
+
# Comparable to #attr_reader for the class level.
|
8
|
+
#
|
9
|
+
# So in summary defines: .var (which gets @var) and
|
10
|
+
# #var (which gets self.class.var)
|
11
|
+
#
|
12
|
+
# @example
|
13
|
+
#
|
14
|
+
# class Polygon
|
15
|
+
# class_attr_reader :sides
|
16
|
+
#
|
17
|
+
# def self.is_a=(shape)
|
18
|
+
# case shape
|
19
|
+
# when 'triangle' then @sides = 3
|
20
|
+
# when 'square' then @sides = 4
|
21
|
+
# end
|
22
|
+
# end
|
23
|
+
# end
|
24
|
+
#
|
25
|
+
# Polygon.sides #=> nil
|
26
|
+
# Polygon.is_a 'triangle'
|
27
|
+
# Polygon.sides #=> 3
|
28
|
+
# t = Polygon.new
|
29
|
+
# t.sides #=> 3
|
30
|
+
#
|
31
|
+
def class_attr_reader(*args)
|
32
|
+
names, default = separate_arguments_and_set_defaults(args)
|
33
|
+
names.each do |name|
|
34
|
+
class_eval <<-EOS
|
35
|
+
def self.#{name}
|
36
|
+
@#{name}
|
37
|
+
end
|
38
|
+
|
39
|
+
def #{name}
|
40
|
+
self.class.send(:#{name})
|
41
|
+
end
|
42
|
+
EOS
|
43
|
+
self.instance_variable_set("@#{name}", (default.dup rescue default))
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Defines a method for to write to an instance varaible set at the class
|
48
|
+
# level. Comparable to #attr_writer for the class level.
|
49
|
+
#
|
50
|
+
# So in summary defines: .var= (which sets @var)
|
51
|
+
#
|
52
|
+
# @example
|
53
|
+
#
|
54
|
+
# class Polygon
|
55
|
+
# class_attr_writer :sides
|
56
|
+
#
|
57
|
+
# def self.rectangle?; @sides == 4; end
|
58
|
+
# def self.triangle?; @sides == 3; end
|
59
|
+
# end
|
60
|
+
#
|
61
|
+
# Polygon.rectangle? #=> false
|
62
|
+
# Polygon.sides = 4
|
63
|
+
# Polygon.rectangle? #=> true
|
64
|
+
# Polygon.sides = 3
|
65
|
+
# Polygon.triangle? #=> true
|
66
|
+
#
|
67
|
+
def class_attr_writer(*args)
|
68
|
+
names, default = separate_arguments_and_set_defaults(args)
|
69
|
+
names.each do |name|
|
70
|
+
class_eval <<-EOS
|
71
|
+
def self.#{name}=(obj)
|
72
|
+
@#{name} = obj
|
73
|
+
end
|
74
|
+
EOS
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
# Executes #class_attr_reader and #class_attr_writer.
|
79
|
+
#
|
80
|
+
# @see #class_attr_reader
|
81
|
+
# @see #class_attr_writer
|
82
|
+
#
|
83
|
+
# @example
|
84
|
+
#
|
85
|
+
# class Polygon
|
86
|
+
# class_attr_accessor :sides
|
87
|
+
# end
|
88
|
+
#
|
89
|
+
# Polygon.sides #=> nil
|
90
|
+
# Polygon.sides = 5
|
91
|
+
# Polygon.sides #=> 5
|
92
|
+
# pentagon = Polygon.new
|
93
|
+
# pentagon.sides #=> 5
|
94
|
+
#
|
95
|
+
def class_attr_accessor(*names)
|
96
|
+
class_attr_reader(*names)
|
97
|
+
class_attr_writer(*names)
|
98
|
+
end
|
99
|
+
|
100
|
+
# Creates a class and instance method to read the class level variable(s)
|
101
|
+
# with the name(s) provided. If no value has been set it attempts to use
|
102
|
+
# the value of the superclass.
|
103
|
+
#
|
104
|
+
# @see #class_attr_reader
|
105
|
+
#
|
106
|
+
def inheritable_class_attr_reader(*args)
|
107
|
+
names, default = separate_arguments_and_set_defaults(args)
|
108
|
+
names.each do |name|
|
109
|
+
class_eval <<-EOS
|
110
|
+
def self.#{name}
|
111
|
+
if @#{name}
|
112
|
+
@#{name}
|
113
|
+
elsif superclass.respond_to? :#{name}
|
114
|
+
@#{name} ||= superclass.#{name}
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def #{name}
|
119
|
+
self.class.send(:#{name})
|
120
|
+
end
|
121
|
+
EOS
|
122
|
+
self.instance_variable_set("@#{name}", (default.dup rescue default))
|
123
|
+
end
|
124
|
+
end
|
125
|
+
|
126
|
+
# The same as #class_attr_writer.
|
127
|
+
def inheritable_class_attr_writer(*args)
|
128
|
+
class_attr_writer(*args)
|
129
|
+
end
|
130
|
+
|
131
|
+
# Executes #inheritable_class_attr_reader and #inheritable_class_attr_writer.
|
132
|
+
#
|
133
|
+
# @see #inheritable_class_attr_reader
|
134
|
+
# @see #inheritable_class_attr_writer
|
135
|
+
#
|
136
|
+
# @example
|
137
|
+
#
|
138
|
+
# class Polygon
|
139
|
+
# inheritable_class_attr_accessor :sides, :angles
|
140
|
+
# self.angles = [90]
|
141
|
+
# end
|
142
|
+
#
|
143
|
+
# class Triangle < Polygon
|
144
|
+
# self.sides = 3
|
145
|
+
# self.angles = [100, 35, 45]
|
146
|
+
# end
|
147
|
+
#
|
148
|
+
# class Rectangle < Polygon
|
149
|
+
# self.sides = 4
|
150
|
+
# self.angles << 60 << 100 << 110
|
151
|
+
# end
|
152
|
+
#
|
153
|
+
# class Square < Rectangle
|
154
|
+
# # should get 4 sides from rectange
|
155
|
+
# self.angles = [90] * 4
|
156
|
+
# end
|
157
|
+
#
|
158
|
+
# Polygon.sides #=> nil
|
159
|
+
# Triangle.sides #=> 3
|
160
|
+
# Rectangle.sides #=> 4
|
161
|
+
# Rectangle.angles #=> [90, 60, 100, 110]
|
162
|
+
# Square.sides #=> 4
|
163
|
+
# Square.angles #=> [90, 90, 90, 90]
|
164
|
+
#
|
165
|
+
def inheritable_class_attr_accessor(*names)
|
166
|
+
inheritable_class_attr_reader(*names)
|
167
|
+
inheritable_class_attr_writer(*names)
|
168
|
+
end
|
169
|
+
|
170
|
+
|
171
|
+
private
|
172
|
+
|
173
|
+
# Non-inheritable attrs won't get any starting value, even if it has been set
|
174
|
+
# on a superclass so we need to save the value and set them when the class is
|
175
|
+
# inherited.
|
176
|
+
#
|
177
|
+
# @param key [Symbol]
|
178
|
+
# @param value [Object]
|
179
|
+
#
|
180
|
+
def register_default(key, value)
|
181
|
+
registered_defaults[key] = value
|
182
|
+
end
|
183
|
+
|
184
|
+
def registered_defaults
|
185
|
+
@registered_defaults ||= {}
|
186
|
+
end
|
187
|
+
|
188
|
+
def inherited_with_attrs(klass)
|
189
|
+
inherited_without_attrs(klass) if respond_to?(:inherited_without_attrs)
|
190
|
+
if registered_defaults
|
191
|
+
new_attrs = registered_defaults.inject({}) do |a, (k, v)|
|
192
|
+
a.update(k => (v.dup rescue v))
|
193
|
+
end
|
194
|
+
else
|
195
|
+
new_attrs = {}
|
196
|
+
end
|
197
|
+
|
198
|
+
new_attrs.each do |k, v|
|
199
|
+
klass.instance_variable_set("@#{k}", v)
|
200
|
+
end
|
201
|
+
klass.instance_variable_set("@registered_defaults", new_attrs)
|
202
|
+
end
|
203
|
+
alias inherited_without_attrs inherited
|
204
|
+
alias inherited inherited_with_attrs
|
205
|
+
|
206
|
+
# Need to use this instead of AttrPlus.separate_arguments so that any defaults
|
207
|
+
# are properly set, but that is only with Class as this is to allow subclasses
|
208
|
+
# to inherit the default values, Modules can't be inherited.
|
209
|
+
#
|
210
|
+
# BUT they can be included so I will have to look into this!
|
211
|
+
def separate_arguments_and_set_defaults(args)
|
212
|
+
args, default = AttrPlus.separate_arguments(args)
|
213
|
+
if default
|
214
|
+
args.each do |arg|
|
215
|
+
register_default(arg, default)
|
216
|
+
end
|
217
|
+
end
|
218
|
+
|
219
|
+
[args, default]
|
220
|
+
end
|
221
|
+
|
222
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
# Place extra methods in here to avoid polluting Class and Module.
|
2
|
+
#
|
3
|
+
module AttrPlus
|
4
|
+
|
5
|
+
# @param args [Array]
|
6
|
+
# @return [Array[Array, Object]]
|
7
|
+
# An array where the first item is a list of arguments that were passed
|
8
|
+
# and the second (last) item is a default value that was given or nil.
|
9
|
+
#
|
10
|
+
def self.separate_arguments(args)
|
11
|
+
if args.size == 1 && args.first.is_a?(Hash)
|
12
|
+
[[args.first.keys[0]], args.first.values[0]]
|
13
|
+
elsif args.last.is_a?(Hash)
|
14
|
+
[args[0..-2], args.last[:default]]
|
15
|
+
else
|
16
|
+
[args, nil]
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
end
|
File without changes
|
@@ -0,0 +1,33 @@
|
|
1
|
+
require 'attr_plus/ext'
|
2
|
+
|
3
|
+
class Module
|
4
|
+
|
5
|
+
def module_attr_reader(*args)
|
6
|
+
names, default = AttrPlus.separate_arguments(args)
|
7
|
+
names.each do |name|
|
8
|
+
module_eval <<-EOS
|
9
|
+
def self.#{name}
|
10
|
+
@#{name}
|
11
|
+
end
|
12
|
+
EOS
|
13
|
+
self.instance_variable_set("@#{name}", (default.dup rescue default))
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def module_attr_writer(*args)
|
18
|
+
names, default = AttrPlus.separate_arguments(args)
|
19
|
+
names.each do |name|
|
20
|
+
module_eval <<-EOS
|
21
|
+
def self.#{name}=(obj)
|
22
|
+
@#{name} = obj
|
23
|
+
end
|
24
|
+
EOS
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
def module_attr_accessor(*args)
|
29
|
+
module_attr_reader(*args)
|
30
|
+
module_attr_writer(*args)
|
31
|
+
end
|
32
|
+
|
33
|
+
end
|
data/lib/class_attr.rb
ADDED
@@ -0,0 +1,165 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Class do
|
4
|
+
|
5
|
+
describe "#class_attr_reader" do
|
6
|
+
subject { Class.new { class_attr_reader :test } }
|
7
|
+
|
8
|
+
it "defines a read method for the class" do
|
9
|
+
subject.should respond_to :test
|
10
|
+
end
|
11
|
+
|
12
|
+
it "defines a read method for instances of the class" do
|
13
|
+
subject.new.should respond_to :test
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
describe "#class_attr_writer" do
|
18
|
+
subject { Class.new { class_attr_writer :test } }
|
19
|
+
|
20
|
+
it "defines a write method for the class" do
|
21
|
+
subject.should respond_to :test=
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "#class_attr_accessor" do
|
26
|
+
subject { Class.new { class_attr_accessor :test } }
|
27
|
+
|
28
|
+
it "defines a read method for the class" do
|
29
|
+
subject.should respond_to :test
|
30
|
+
end
|
31
|
+
|
32
|
+
it "defines a write method for the class" do
|
33
|
+
subject.should respond_to :test=
|
34
|
+
end
|
35
|
+
|
36
|
+
it "defines a read method for instances of the class" do
|
37
|
+
subject.new.should respond_to :test
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
# The subclass thing was starting to annoy me...
|
42
|
+
context "When there is a subclass of a class with class_attrs" do
|
43
|
+
|
44
|
+
let(:sup) { Class.new { class_attr_accessor :test } }
|
45
|
+
let(:sub) { Class.new(sup) }
|
46
|
+
|
47
|
+
it "has the methods of the superclass" do
|
48
|
+
sub.should respond_to :test
|
49
|
+
sub.should respond_to :test=
|
50
|
+
end
|
51
|
+
|
52
|
+
describe "calling the writer method on the subclass" do
|
53
|
+
it "should not alter the value on the superclass" do
|
54
|
+
sub.test = "changed"
|
55
|
+
sub.test.should == "changed"
|
56
|
+
sup.test.should_not == "changed"
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
describe "calling the writer method on the superclass" do
|
61
|
+
it "should not alter the value on the subclass" do
|
62
|
+
sup.test = "changed again"
|
63
|
+
sup.test.should == "changed again"
|
64
|
+
sub.test.should_not == "changed again"
|
65
|
+
end
|
66
|
+
end
|
67
|
+
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
|
+
|
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
|
+
|
95
|
+
it "defines a read method for the class" do
|
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
|
107
|
+
|
108
|
+
context "When there is a subclass of a class with inheritable_class_attrs" do
|
109
|
+
|
110
|
+
let(:sup) { Class.new { inheritable_class_attr_accessor :test } }
|
111
|
+
let(:sub) { Class.new(sup) }
|
112
|
+
|
113
|
+
it "has the methods of the superclass" do
|
114
|
+
sub.should respond_to :test
|
115
|
+
sub.should respond_to :test=
|
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"
|
131
|
+
end
|
132
|
+
|
133
|
+
it "should not alter the value on the subclass if set" do
|
134
|
+
sub.test = "already set"
|
135
|
+
sup.test = "change it"
|
136
|
+
sup.test.should == "change it"
|
137
|
+
sub.test.should == "already set"
|
138
|
+
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
|
+
|
158
|
+
it "returns the default value as well" do
|
159
|
+
sub.test.should == "hi"
|
160
|
+
end
|
161
|
+
end
|
162
|
+
|
163
|
+
end
|
164
|
+
|
165
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Module do
|
4
|
+
|
5
|
+
describe "#module_attr_reader" do
|
6
|
+
subject { Module.new { module_attr_reader :test } }
|
7
|
+
|
8
|
+
it "defines a read method for the module" do
|
9
|
+
subject.should respond_to :test
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
describe "#module_attr_writer" do
|
14
|
+
subject { Module.new { module_attr_writer :test } }
|
15
|
+
|
16
|
+
it "defines a write method for the module" do
|
17
|
+
subject.should respond_to :test=
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "#module_attr_accessor" do
|
22
|
+
subject { Module.new { module_attr_accessor :test } }
|
23
|
+
|
24
|
+
it "defines a read method for the module" do
|
25
|
+
subject.should respond_to :test
|
26
|
+
end
|
27
|
+
|
28
|
+
it "defines a write method for the module" do
|
29
|
+
subject.should respond_to :test=
|
30
|
+
end
|
31
|
+
end
|
32
|
+
|
33
|
+
context "When given a default value" do
|
34
|
+
subject { Module.new { module_attr_accessor :test => "hi" } }
|
35
|
+
|
36
|
+
it "returns the default value before being changed" do
|
37
|
+
subject.test.should == "hi"
|
38
|
+
end
|
39
|
+
|
40
|
+
it "returns the new value if it is changed" do
|
41
|
+
subject.test = nil
|
42
|
+
subject.test.should be_nil
|
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
|
+
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe AttrPlus do
|
4
|
+
|
5
|
+
describe "#separate_argument_list_and_default" do
|
6
|
+
def call_it(*args)
|
7
|
+
AttrPlus.separate_arguments(*args)
|
8
|
+
end
|
9
|
+
|
10
|
+
context "when given a list of arguments with a default" do
|
11
|
+
it "returns an array with the arguments and a default value" do
|
12
|
+
call_it([:one, :two, :three, {:default => 0}]).should == [[:one, :two, :three], 0]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
context "when given an argument and a default" do
|
17
|
+
it "returns an array with the arguments and a default value" do
|
18
|
+
call_it([{:one => 1}]).should == [[:one], 1]
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
context "when given just arguments" do
|
23
|
+
it "returns and array with the arguments and nil" do
|
24
|
+
call_it([:one, :two, :three]).should == [[:one, :two, :three], nil]
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
end
|
data/spec/spec_helper.rb
ADDED
metadata
ADDED
@@ -0,0 +1,78 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: attr_plus
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
prerelease: false
|
5
|
+
segments:
|
6
|
+
- 0
|
7
|
+
- 2
|
8
|
+
- 0
|
9
|
+
version: 0.2.0
|
10
|
+
platform: ruby
|
11
|
+
authors:
|
12
|
+
- Joshua Hawxwell
|
13
|
+
autorequire:
|
14
|
+
bindir: bin
|
15
|
+
cert_chain: []
|
16
|
+
|
17
|
+
date: 2011-02-12 00:00:00 +00:00
|
18
|
+
default_executable:
|
19
|
+
dependencies: []
|
20
|
+
|
21
|
+
description: " Provides attr_accessor style methods for easily creating methods for\n working with class level instance variables and module level instance\n variables. Variables can be inherited and have default values.\n"
|
22
|
+
email: m@hawx.me
|
23
|
+
executables: []
|
24
|
+
|
25
|
+
extensions: []
|
26
|
+
|
27
|
+
extra_rdoc_files: []
|
28
|
+
|
29
|
+
files:
|
30
|
+
- README.md
|
31
|
+
- LICENSE
|
32
|
+
- lib/attr_plus/class.rb
|
33
|
+
- lib/attr_plus/ext.rb
|
34
|
+
- lib/attr_plus/instance.rb
|
35
|
+
- lib/attr_plus/module.rb
|
36
|
+
- lib/attr_plus.rb
|
37
|
+
- lib/class_attr.rb
|
38
|
+
- spec/attr_plus/class_spec.rb
|
39
|
+
- spec/attr_plus/module_spec.rb
|
40
|
+
- spec/class_attr_spec.rb
|
41
|
+
- spec/spec_helper.rb
|
42
|
+
has_rdoc: false
|
43
|
+
homepage: http://github.com/hawx/attr_plus
|
44
|
+
licenses: []
|
45
|
+
|
46
|
+
post_install_message:
|
47
|
+
rdoc_options: []
|
48
|
+
|
49
|
+
require_paths:
|
50
|
+
- lib
|
51
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
52
|
+
none: false
|
53
|
+
requirements:
|
54
|
+
- - ">="
|
55
|
+
- !ruby/object:Gem::Version
|
56
|
+
segments:
|
57
|
+
- 0
|
58
|
+
version: "0"
|
59
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
60
|
+
none: false
|
61
|
+
requirements:
|
62
|
+
- - ">="
|
63
|
+
- !ruby/object:Gem::Version
|
64
|
+
segments:
|
65
|
+
- 0
|
66
|
+
version: "0"
|
67
|
+
requirements: []
|
68
|
+
|
69
|
+
rubyforge_project:
|
70
|
+
rubygems_version: 1.3.7
|
71
|
+
signing_key:
|
72
|
+
specification_version: 3
|
73
|
+
summary: attr_accessor for class and module level instance variables.
|
74
|
+
test_files:
|
75
|
+
- spec/attr_plus/class_spec.rb
|
76
|
+
- spec/attr_plus/module_spec.rb
|
77
|
+
- spec/class_attr_spec.rb
|
78
|
+
- spec/spec_helper.rb
|