cascading_classes 0.2.0 → 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/README.md +60 -17
- data/lib/cascading_classes/cascading_classes.rb +24 -13
- data/lib/cascading_classes/dsl.rb +22 -2
- data/lib/cascading_classes.rb +23 -5
- data/spec/alternative_syntax_spec.rb +80 -53
- data/spec/extended_spec.rb +148 -0
- data/spec/included_spec.rb +7 -1
- metadata +7 -6
- data/spec/note.txt +0 -2
data/README.md
CHANGED
@@ -12,27 +12,22 @@ This library allows you to easily create properties that cascade down a class tr
|
|
12
12
|
|
13
13
|
class GrandChild < Child; end
|
14
14
|
|
15
|
-
now create
|
15
|
+
now create properties that will cascade down all descendents
|
16
16
|
|
17
17
|
Parent.cascade :eye_color, :hair_color
|
18
18
|
|
19
|
-
set
|
19
|
+
set a property on a parent class
|
20
20
|
|
21
21
|
Parent.eye_color = "brown"
|
22
|
-
Parent.hair_color = "black"
|
23
22
|
|
24
23
|
all child classes are affected
|
25
24
|
|
26
25
|
p Child.eye_color # => "brown"
|
27
26
|
p GrandChild.eye_color # => "brown"
|
28
27
|
|
29
|
-
|
30
|
-
p GrandChild.hair_color # => "black"
|
31
|
-
|
32
|
-
now change the ```eye_color``` and ```hair_color``` properties on ```Child```
|
28
|
+
now change the property on a descendent class
|
33
29
|
|
34
30
|
Child.eye_color = "blue"
|
35
|
-
Child.hair_color = "blond"
|
36
31
|
|
37
32
|
only descendents of ```Child``` are affected
|
38
33
|
|
@@ -56,7 +51,7 @@ Assume the class structure from above:
|
|
56
51
|
|
57
52
|
## Setting default values
|
58
53
|
|
59
|
-
Setting default values for cascaded properties
|
54
|
+
Setting default values for cascaded properties is easy. The first method is to bracket them in Array pairs. For example:
|
60
55
|
|
61
56
|
Parent.cascade [:eye_color, "hazel"], [:hair_color, "brown"], :has_education
|
62
57
|
|
@@ -69,8 +64,8 @@ You also create cascaded properties via ```Parent.all!```
|
|
69
64
|
|
70
65
|
For example, the following are equivalent:
|
71
66
|
|
72
|
-
Parent.cascade :arms, :legs
|
73
|
-
Parent.all! :arms, :legs
|
67
|
+
Parent.cascade :arms, :legs
|
68
|
+
Parent.all! :arms, :legs
|
74
69
|
|
75
70
|
this initiates, but does not set, two cascading properties: ```arms```, ```legs```
|
76
71
|
|
@@ -82,7 +77,7 @@ since no default was given, all are nil
|
|
82
77
|
|
83
78
|
Again, to set a default use brackets:
|
84
79
|
|
85
|
-
Parent.all! :arms, [:legs, 2]
|
80
|
+
Parent.all! :arms, [:legs, 2]
|
86
81
|
|
87
82
|
|
88
83
|
### Alternative syntax: block arguments
|
@@ -136,7 +131,7 @@ You can also set a property in a block using ```set_property```
|
|
136
131
|
|
137
132
|
## Quick Summary
|
138
133
|
|
139
|
-
|
134
|
+
NOTE: CC is equivalent to CascadingClasses
|
140
135
|
|
141
136
|
require the gem
|
142
137
|
|
@@ -176,12 +171,12 @@ get and set the property on any descendent
|
|
176
171
|
|
177
172
|
## What's the difference between ```extend CC``` and ```include CC```?
|
178
173
|
|
179
|
-
First, in either case you are dealing with class instance variables
|
174
|
+
First, in either case you are dealing with class instance variables.
|
180
175
|
|
181
176
|
A.cascade :eye_color
|
182
177
|
A.eye_color = "blue"
|
183
178
|
|
184
|
-
sets ```@eye_color``` on
|
179
|
+
sets ```@eye_color``` on ```A```.
|
185
180
|
|
186
181
|
But if you also want the properties to cascade to instance variables, you have three options. The first is to ```include CC```, which, by default, creates the properties on instances too
|
187
182
|
|
@@ -198,7 +193,9 @@ But if you also want the properties to cascade to instance variables, you have t
|
|
198
193
|
c = Child.new
|
199
194
|
p c.one # => 1
|
200
195
|
|
201
|
-
The other two ways to ensure instances have
|
196
|
+
The other two ways to ensure instances have cascading properties uses an additional argument:
|
197
|
+
|
198
|
+
either
|
202
199
|
|
203
200
|
Parent.cascade [:hair_color, "blue", true]
|
204
201
|
|
@@ -208,6 +205,52 @@ or
|
|
208
205
|
hair_color :default => "blue", :instances => true
|
209
206
|
end
|
210
207
|
|
208
|
+
will do the trick.
|
209
|
+
|
211
210
|
In either case, even if you ```extend CC```, all instance variables of all descendents will have the ```hair_color``` property.
|
212
211
|
|
213
|
-
|
212
|
+
## Custom getters and setters
|
213
|
+
|
214
|
+
The easiest way to apply custom names for getting and setting a property is with the :getter/:setter options.
|
215
|
+
|
216
|
+
Parent.cascade do
|
217
|
+
eye_color :start => "brown", :getter => :eyes, :setter => :eyes=
|
218
|
+
end
|
219
|
+
Child.eyes = "blue"
|
220
|
+
|
221
|
+
now you cannot use ```:eye_color``` or ```:eye_color=``` methods to get or set the property.
|
222
|
+
|
223
|
+
p Parent.eyes # => "brown"
|
224
|
+
p Parent.eye_color # => NoMethodError
|
225
|
+
|
226
|
+
p Child.eyes # => "blue"
|
227
|
+
p GrandChild.eyes # => "blue"
|
228
|
+
|
229
|
+
You can also have more than one getter or setter function
|
230
|
+
|
231
|
+
Parent.all! do
|
232
|
+
has_hair :begin => false, :getters => [:has_hair?, :hair?]
|
233
|
+
end
|
234
|
+
Child.has_hair = true
|
235
|
+
|
236
|
+
p Parent.has_hair? # => false
|
237
|
+
p Parent.hair? # => false
|
238
|
+
|
239
|
+
p Child.has_hair? # => true
|
240
|
+
p Child.hair? # => true
|
241
|
+
|
242
|
+
While not recommended, you can also apply custom getter/setter name in the array style syntax.
|
243
|
+
|
244
|
+
Parent.cascade [:has_hair, false, true, [:has_hair?, :hair?]]
|
245
|
+
|
246
|
+
this initializes the ```has_hair``` property on ```Parent``` to false and sets the getter functions to ```:has_hair?``` and ```:hair?```. Recall that the third argument in the block explicitly sets whether class instances are inherit the property.
|
247
|
+
|
248
|
+
If you wanted to apply a custom setter, it would be the fifth argument:
|
249
|
+
|
250
|
+
Parent.cascade [:has_hair, false, true, :hair?, :hair!]
|
251
|
+
|
252
|
+
Compare how much worse that looks compared to the block syntax:
|
253
|
+
|
254
|
+
Parent.cascade do
|
255
|
+
hair_color :default => false, :instances => true, :getter => :hair?, :setter => :hair!
|
256
|
+
end
|
@@ -2,18 +2,22 @@ require 'cascading_classes/dsl'
|
|
2
2
|
|
3
3
|
module CascadingClasses
|
4
4
|
|
5
|
-
def self.cascade_intern(klass, property)
|
5
|
+
def self.cascade_intern(klass, property, getter, setter)
|
6
6
|
Module.new do
|
7
7
|
|
8
|
-
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
self.class.send(
|
8
|
+
if getter
|
9
|
+
define_method getter do
|
10
|
+
val = instance_variable_get "@#{property}"
|
11
|
+
return val unless (val.nil? and self != klass)
|
12
|
+
(self.class == Class) ? superclass.send(getter) :
|
13
|
+
self.class.send(getter)
|
14
|
+
end
|
13
15
|
end
|
14
16
|
|
15
|
-
|
16
|
-
|
17
|
+
if setter
|
18
|
+
define_method setter do |v|
|
19
|
+
instance_variable_set "@#{property}", v
|
20
|
+
end
|
17
21
|
end
|
18
22
|
|
19
23
|
end
|
@@ -24,23 +28,30 @@ module CascadingClasses
|
|
24
28
|
res = {}
|
25
29
|
properties.each do |prop|
|
26
30
|
name, default, inst_too = prop, nil, apply_to_instances
|
31
|
+
getters, setters = [], []
|
27
32
|
if Array === prop
|
28
33
|
case prop.size
|
29
34
|
when 0 then next
|
30
35
|
when 1 then name = prop[0]
|
31
36
|
when 2 then name, default = prop[0..1]
|
32
|
-
else
|
37
|
+
else
|
38
|
+
name, default, inst_too = prop[0..2]
|
39
|
+
getters = [*prop[3]] if prop.size >= 4
|
40
|
+
setters = [*prop[4]] if prop.size >= 5
|
33
41
|
end
|
34
42
|
end
|
43
|
+
getters = [name.to_sym] if getters.empty?
|
44
|
+
setters = ["#{name}=".to_sym] if setters.empty?
|
35
45
|
inst_too = !!inst_too
|
36
|
-
res[name.to_sym] = [default, inst_too]
|
46
|
+
res[name.to_sym] = [default, inst_too, getters, setters]
|
37
47
|
end
|
38
48
|
|
39
49
|
if block_given?
|
40
50
|
a = CascadingClasses::DSL.new(apply_to_instances, &block)
|
41
|
-
names, defaults, inst =
|
42
|
-
a.instance_eval{ [@names, @defaults, @instances_too] }
|
43
|
-
names.each{|name|
|
51
|
+
names, defaults, inst, getters, setters =
|
52
|
+
a.instance_eval{ [@names, @defaults, @instances_too, @getters, @setters] }
|
53
|
+
names.each{|name|
|
54
|
+
res[name] = [defaults[name], inst[name], getters[name], setters[name]] }
|
44
55
|
end
|
45
56
|
|
46
57
|
res
|
@@ -62,13 +62,33 @@ module CascadingClasses
|
|
62
62
|
else
|
63
63
|
@apply_to_instances
|
64
64
|
end
|
65
|
+
|
66
|
+
@getters[name] = if args.include? :getter
|
67
|
+
[*args[:getter]]
|
68
|
+
elsif args.include? :getters
|
69
|
+
[*args[:getters]]
|
70
|
+
elsif args.include? :get
|
71
|
+
[*args[:get]]
|
72
|
+
else
|
73
|
+
[name.to_sym]
|
74
|
+
end
|
75
|
+
|
76
|
+
@setters[name] = if args.include? :setter
|
77
|
+
[*args[:setter]]
|
78
|
+
elsif args.include? :setters
|
79
|
+
[*args[:setters]]
|
80
|
+
elsif args.include? :set
|
81
|
+
[*args[:set]]
|
82
|
+
else
|
83
|
+
["#{name}=".to_sym]
|
84
|
+
end
|
65
85
|
end
|
66
86
|
|
67
87
|
def initialize(apply_to_instances, &block)
|
68
88
|
@apply_to_instances = apply_to_instances
|
69
89
|
@names = []
|
70
|
-
@defaults = {}
|
71
|
-
@
|
90
|
+
@defaults, @instances_too = {}, {}
|
91
|
+
@getters, @setters = {}, {}
|
72
92
|
|
73
93
|
return unless block_given?
|
74
94
|
if block.arity == 0
|
data/lib/cascading_classes.rb
CHANGED
@@ -33,7 +33,8 @@ module CascadingClasses
|
|
33
33
|
# todo: fill in rest
|
34
34
|
# todo: allow one of [:cascade, :all!] to be overwritten
|
35
35
|
def self.illegal_names
|
36
|
-
[:cascade, :all!, :instance_eval, :instance_exec,
|
36
|
+
[:cascade, :all!, :set_property, :instance_eval, :instance_exec,
|
37
|
+
:class_eval]
|
37
38
|
end
|
38
39
|
|
39
40
|
def self.apply(klass, instances_too)
|
@@ -43,11 +44,15 @@ module CascadingClasses
|
|
43
44
|
illegal_names = CascadingClasses.illegal_names
|
44
45
|
|
45
46
|
props = CascadingClasses.parse_options(klass, instances_too, *props, &block)
|
46
|
-
props.each{|prop, v|
|
47
|
-
|
47
|
+
props.each{|prop, v|
|
48
|
+
default, inst_too, getters, setters = v
|
49
|
+
getters.each{|getter|
|
50
|
+
raise NameError, "Illegal property getter: #{getter} for #{prop}" if
|
51
|
+
illegal_names.include? getter }
|
52
|
+
}
|
48
53
|
|
49
54
|
props.each do |prop, v|
|
50
|
-
default, inst_too = v
|
55
|
+
default, inst_too, getters, setters = v
|
51
56
|
|
52
57
|
klass.singleton_class.instance_eval do
|
53
58
|
undef_method prop.to_sym rescue nil
|
@@ -56,14 +61,27 @@ module CascadingClasses
|
|
56
61
|
|
57
62
|
klass.instance_eval{ instance_variable_set "@#{prop}", default }
|
58
63
|
|
59
|
-
mod = CascadingClasses.cascade_intern(klass, prop)
|
64
|
+
mod = CascadingClasses.cascade_intern(klass, prop, getters[0], setters[0])
|
60
65
|
klass.extend mod
|
66
|
+
klass.singleton_class.instance_eval do
|
67
|
+
getters[1..-1].each{|getter| alias_method getter, getters[0]} unless
|
68
|
+
getters[0].nil?
|
69
|
+
setters[1..-1].each{|setter| alias_method setter, setters[0]} unless
|
70
|
+
setters[0].nil?
|
71
|
+
end
|
72
|
+
|
61
73
|
if inst_too
|
62
74
|
klass.instance_eval do
|
63
75
|
undef_method prop.to_sym rescue nil
|
64
76
|
undef_method "#{prop}=".to_sym rescue nil
|
65
77
|
end
|
66
78
|
klass.send(:include, mod)
|
79
|
+
klass.instance_eval do
|
80
|
+
getters[1..-1].each{|getter| alias_method getter, getters[0]} unless
|
81
|
+
getters[0].nil?
|
82
|
+
setters[1..-1].each{|setter| alias_method setter, setters[0]} unless
|
83
|
+
setters[0].nil?
|
84
|
+
end
|
67
85
|
end
|
68
86
|
end
|
69
87
|
end
|
@@ -20,6 +20,26 @@ describe "when a class extends CascadingClasses and an alternative syntax is use
|
|
20
20
|
GrandChild = Class.new(Child)
|
21
21
|
end
|
22
22
|
|
23
|
+
after do
|
24
|
+
Object.send :remove_const, :Parent
|
25
|
+
Object.send :remove_const, :Child
|
26
|
+
Object.send :remove_const, :GrandChild
|
27
|
+
end
|
28
|
+
|
29
|
+
def standard
|
30
|
+
Parent.hair_color.must_equal "black"
|
31
|
+
Child.hair_color.must_equal "blond"
|
32
|
+
GrandChild.hair_color.must_equal "blond"
|
33
|
+
|
34
|
+
Parent.eye_color.must_equal nil
|
35
|
+
Child.eye_color.must_equal "brown"
|
36
|
+
GrandChild.eye_color.must_equal "brown"
|
37
|
+
|
38
|
+
Parent.piercings.must_equal false
|
39
|
+
Child.piercings.must_equal false
|
40
|
+
GrandChild.piercings.must_equal false
|
41
|
+
end
|
42
|
+
|
23
43
|
describe "when an alternative syntax is given (0)" do
|
24
44
|
before do
|
25
45
|
Parent.cascade [:hair_color, "black"], :eye_color, [:piercings, false]
|
@@ -29,17 +49,7 @@ describe "when a class extends CascadingClasses and an alternative syntax is use
|
|
29
49
|
end
|
30
50
|
|
31
51
|
it "should give the same result" do
|
32
|
-
|
33
|
-
Child.hair_color.must_equal "blond"
|
34
|
-
GrandChild.hair_color.must_equal "blond"
|
35
|
-
|
36
|
-
Parent.eye_color.must_equal nil
|
37
|
-
Child.eye_color.must_equal "brown"
|
38
|
-
GrandChild.eye_color.must_equal "brown"
|
39
|
-
|
40
|
-
Parent.piercings.must_equal false
|
41
|
-
Child.piercings.must_equal false
|
42
|
-
GrandChild.piercings.must_equal false
|
52
|
+
standard
|
43
53
|
end
|
44
54
|
end
|
45
55
|
|
@@ -52,17 +62,7 @@ describe "when a class extends CascadingClasses and an alternative syntax is use
|
|
52
62
|
end
|
53
63
|
|
54
64
|
it "should give the same result" do
|
55
|
-
|
56
|
-
Child.hair_color.must_equal "blond"
|
57
|
-
GrandChild.hair_color.must_equal "blond"
|
58
|
-
|
59
|
-
Parent.eye_color.must_equal nil
|
60
|
-
Child.eye_color.must_equal "brown"
|
61
|
-
GrandChild.eye_color.must_equal "brown"
|
62
|
-
|
63
|
-
Parent.piercings.must_equal false
|
64
|
-
Child.piercings.must_equal false
|
65
|
-
GrandChild.piercings.must_equal false
|
65
|
+
standard
|
66
66
|
end
|
67
67
|
end
|
68
68
|
|
@@ -78,17 +78,7 @@ describe "when a class extends CascadingClasses and an alternative syntax is use
|
|
78
78
|
end
|
79
79
|
|
80
80
|
it "should give the same result" do
|
81
|
-
|
82
|
-
Child.hair_color.must_equal "blond"
|
83
|
-
GrandChild.hair_color.must_equal "blond"
|
84
|
-
|
85
|
-
Parent.eye_color.must_equal nil
|
86
|
-
Child.eye_color.must_equal "brown"
|
87
|
-
GrandChild.eye_color.must_equal "brown"
|
88
|
-
|
89
|
-
Parent.piercings.must_equal false
|
90
|
-
Child.piercings.must_equal false
|
91
|
-
GrandChild.piercings.must_equal false
|
81
|
+
standard
|
92
82
|
end
|
93
83
|
end
|
94
84
|
|
@@ -104,17 +94,7 @@ describe "when a class extends CascadingClasses and an alternative syntax is use
|
|
104
94
|
end
|
105
95
|
|
106
96
|
it "should give the same result" do
|
107
|
-
|
108
|
-
Child.hair_color.must_equal "blond"
|
109
|
-
GrandChild.hair_color.must_equal "blond"
|
110
|
-
|
111
|
-
Parent.eye_color.must_equal nil
|
112
|
-
Child.eye_color.must_equal "brown"
|
113
|
-
GrandChild.eye_color.must_equal "brown"
|
114
|
-
|
115
|
-
Parent.piercings.must_equal false
|
116
|
-
Child.piercings.must_equal false
|
117
|
-
GrandChild.piercings.must_equal false
|
97
|
+
standard
|
118
98
|
end
|
119
99
|
end
|
120
100
|
|
@@ -130,17 +110,64 @@ describe "when a class extends CascadingClasses and an alternative syntax is use
|
|
130
110
|
end
|
131
111
|
|
132
112
|
it "should give the same result" do
|
133
|
-
|
134
|
-
|
135
|
-
|
113
|
+
standard
|
114
|
+
end
|
115
|
+
end
|
116
|
+
|
117
|
+
# getters/setters
|
118
|
+
describe "when an alternative getter/setter syntax is given" do
|
119
|
+
before do
|
120
|
+
Parent.cascade do
|
121
|
+
eye_color :getter => :eyes, :setter => :eyes=
|
122
|
+
hair_color :initial => "black", :getters => :hair, :setters => :hair=
|
123
|
+
piercings :start => false,
|
124
|
+
:getter => [:has_piercings?, :piercings?],
|
125
|
+
:setter => [:has_piercings=, :piercings=]
|
126
|
+
end
|
127
|
+
|
128
|
+
Child.hair = "blond"
|
129
|
+
Child.eyes = "brown"
|
130
|
+
end
|
131
|
+
|
132
|
+
it "should give the same result" do
|
133
|
+
Parent.hair.must_equal "black"
|
134
|
+
Child.hair.must_equal "blond"
|
135
|
+
GrandChild.hair.must_equal "blond"
|
136
|
+
|
137
|
+
Parent.eyes.must_equal nil
|
138
|
+
Child.eyes.must_equal "brown"
|
139
|
+
GrandChild.eyes.must_equal "brown"
|
140
|
+
|
141
|
+
Parent.has_piercings?.must_equal false
|
142
|
+
Child.piercings?.must_equal false
|
143
|
+
GrandChild.has_piercings?.must_equal false
|
144
|
+
end
|
145
|
+
end
|
146
|
+
|
147
|
+
describe "when an alternative syntax is given (2)" do
|
148
|
+
before do
|
149
|
+
Parent.cascade [:eye_color, nil, false, :eyes, :eyes=]
|
150
|
+
Parent.cascade [:hair_color, "black", false, :hair, :hair=]
|
151
|
+
Parent.cascade [:piercings, false, false,
|
152
|
+
[:has_piercings?, :piercings?],
|
153
|
+
[:has_piercings=, :piercings=] ]
|
154
|
+
|
155
|
+
Child.hair = "blond"
|
156
|
+
Child.eyes = "brown"
|
157
|
+
end
|
158
|
+
|
159
|
+
it "should give the same result" do
|
160
|
+
Parent.hair.must_equal "black"
|
161
|
+
Child.hair.must_equal "blond"
|
162
|
+
GrandChild.hair.must_equal "blond"
|
136
163
|
|
137
|
-
Parent.
|
138
|
-
Child.
|
139
|
-
GrandChild.
|
164
|
+
Parent.eyes.must_equal nil
|
165
|
+
Child.eyes.must_equal "brown"
|
166
|
+
GrandChild.eyes.must_equal "brown"
|
140
167
|
|
141
|
-
Parent.
|
142
|
-
Child.piercings
|
143
|
-
GrandChild.
|
168
|
+
Parent.has_piercings?.must_equal false
|
169
|
+
Child.piercings?.must_equal false
|
170
|
+
GrandChild.has_piercings?.must_equal false
|
144
171
|
end
|
145
172
|
end
|
146
173
|
end
|
data/spec/extended_spec.rb
CHANGED
@@ -27,6 +27,12 @@ describe "when a class extends CascadingClasses" do
|
|
27
27
|
GrandChild = Class.new(Child)
|
28
28
|
end
|
29
29
|
|
30
|
+
after do
|
31
|
+
Object.send :remove_const, :Parent
|
32
|
+
Object.send :remove_const, :Child
|
33
|
+
Object.send :remove_const, :GrandChild
|
34
|
+
end
|
35
|
+
|
30
36
|
describe "when a parent has a default" do
|
31
37
|
before do
|
32
38
|
Parent.cascade [:eyes, "brown"]
|
@@ -164,4 +170,146 @@ describe "when a class extends CascadingClasses" do
|
|
164
170
|
res.must_equal true
|
165
171
|
end
|
166
172
|
end
|
173
|
+
|
174
|
+
# getters/setters
|
175
|
+
describe "when a custom getter is given" do
|
176
|
+
before do
|
177
|
+
Parent.cascade do
|
178
|
+
eye_color :default => "brown", :getter => :color
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
it "is the only reader method" do
|
183
|
+
Parent.color.must_equal "brown"
|
184
|
+
|
185
|
+
Parent.send(:respond_to?, :eye_color).must_equal false
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
# :getters aliased to :getter
|
190
|
+
describe "when multiple getters are given" do
|
191
|
+
before do
|
192
|
+
Parent.cascade do
|
193
|
+
eye_color :default => "brown", :getters => [:color, :eyes]
|
194
|
+
end
|
195
|
+
|
196
|
+
it "those methods are the only readers" do
|
197
|
+
Parent.color.must_equal "brown"
|
198
|
+
Parent.eyes.must_equal "brown"
|
199
|
+
|
200
|
+
Parent.send(:respond_to?, :eye_color).must_equal false
|
201
|
+
end
|
202
|
+
end
|
203
|
+
end
|
204
|
+
|
205
|
+
describe "when a getter name is nil" do
|
206
|
+
before do
|
207
|
+
Parent.all! do
|
208
|
+
color :default => "red", :getter => nil
|
209
|
+
end
|
210
|
+
end
|
211
|
+
|
212
|
+
it "should not have a getter method" do
|
213
|
+
Parent.send(:respond_to?, :color).must_equal false
|
214
|
+
end
|
215
|
+
end
|
216
|
+
|
217
|
+
describe "when a getter name is false" do
|
218
|
+
before do
|
219
|
+
Parent.all!{
|
220
|
+
color :default => "red", :getter => false
|
221
|
+
}
|
222
|
+
end
|
223
|
+
|
224
|
+
it "should not have a getter method" do
|
225
|
+
Parent.send(:respond_to?, :color).must_equal false
|
226
|
+
end
|
227
|
+
end
|
228
|
+
|
229
|
+
describe "when a custom getter is given" do
|
230
|
+
before do
|
231
|
+
Parent.cascade do
|
232
|
+
eye_color :default => "black", :getter => :color
|
233
|
+
end
|
234
|
+
end
|
235
|
+
|
236
|
+
it "should also be the getter for child classes" do
|
237
|
+
Child.color.must_equal "black"
|
238
|
+
|
239
|
+
Child.send(:respond_to?, :eye_color).must_equal false
|
240
|
+
end
|
241
|
+
end
|
242
|
+
|
243
|
+
describe "when a custom setter is given" do
|
244
|
+
before do
|
245
|
+
Parent.cascade do
|
246
|
+
eye_color :default => "brown", :setter => :color=
|
247
|
+
end
|
248
|
+
end
|
249
|
+
|
250
|
+
it "is the only writer method" do
|
251
|
+
Parent.color = "blue"
|
252
|
+
Parent.eye_color.must_equal "blue"
|
253
|
+
|
254
|
+
Parent.send(:respond_to?, :eye_color=).must_equal false
|
255
|
+
end
|
256
|
+
end
|
257
|
+
|
258
|
+
# :setters aliased to :setters
|
259
|
+
describe "when multiple setters are given" do
|
260
|
+
before do
|
261
|
+
Parent.cascade do
|
262
|
+
eye_color :default => "brown", :setters => [:color=, :set_color]
|
263
|
+
end
|
264
|
+
|
265
|
+
it "those methods are the only readers" do
|
266
|
+
Parent.color = "blue"
|
267
|
+
Parent.color.must_equal "blue"
|
268
|
+
|
269
|
+
Parent.set_color "black"
|
270
|
+
Parent.color.must_equal "black"
|
271
|
+
|
272
|
+
Parent.send(:respond_to?, :eye_color=).must_equal false
|
273
|
+
end
|
274
|
+
end
|
275
|
+
end
|
276
|
+
|
277
|
+
describe "when a setter name is nil" do
|
278
|
+
before do
|
279
|
+
Parent.all!{
|
280
|
+
color :default => "red", :setter => nil
|
281
|
+
}
|
282
|
+
end
|
283
|
+
|
284
|
+
it "should not have a setter method" do
|
285
|
+
Parent.send(:respond_to?, :color=).must_equal false
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
describe "when a setter name is false" do
|
290
|
+
before do
|
291
|
+
Parent.all! do
|
292
|
+
color :default => "red", :setter => false
|
293
|
+
end
|
294
|
+
end
|
295
|
+
|
296
|
+
it "should not have a setter method" do
|
297
|
+
Parent.send(:respond_to?, :color=).must_equal false
|
298
|
+
end
|
299
|
+
end
|
300
|
+
|
301
|
+
describe "when a custom setter is given" do
|
302
|
+
before do
|
303
|
+
Parent.cascade do
|
304
|
+
eye_color :default => "black", :setter => :color=
|
305
|
+
end
|
306
|
+
end
|
307
|
+
|
308
|
+
it "should also be the getter for child classes" do
|
309
|
+
Child.color = "blue"
|
310
|
+
Child.eye_color.must_equal "blue"
|
311
|
+
|
312
|
+
Child.send(:respond_to?, :eye_color=).must_equal false
|
313
|
+
end
|
314
|
+
end
|
167
315
|
end
|
data/spec/included_spec.rb
CHANGED
@@ -24,7 +24,13 @@ describe "when CascadingClasses is included by a class" do
|
|
24
24
|
B = Class.new(A)
|
25
25
|
C = Class.new(B)
|
26
26
|
@a, @b, @c = A.new, B.new, C.new
|
27
|
-
end
|
27
|
+
end
|
28
|
+
|
29
|
+
after do
|
30
|
+
Object.send :remove_const, :A
|
31
|
+
Object.send :remove_const, :B
|
32
|
+
Object.send :remove_const, :C
|
33
|
+
end
|
28
34
|
|
29
35
|
describe "when CascadingClasses is included in a module" do
|
30
36
|
before do
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cascading_classes
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,10 +9,13 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2011-08-
|
12
|
+
date: 2011-08-09 00:00:00.000000000Z
|
13
13
|
dependencies: []
|
14
|
-
description:
|
15
|
-
|
14
|
+
description: ! 'Easily create properties whose values cascade down class trees.
|
15
|
+
|
16
|
+
|
17
|
+
Similar to active_support/core_ext/class/attribute.rb but better. Also, doesn''t
|
18
|
+
monkey-patch Class'
|
16
19
|
email: jeremy.gables@gmail.com
|
17
20
|
executables: []
|
18
21
|
extensions: []
|
@@ -27,7 +30,6 @@ files:
|
|
27
30
|
- spec/extended_spec.rb
|
28
31
|
- spec/included_spec.rb
|
29
32
|
- spec/alternative_syntax_spec.rb
|
30
|
-
- spec/note.txt
|
31
33
|
homepage: http://github.com/gables/cascading_classes
|
32
34
|
licenses: []
|
33
35
|
post_install_message:
|
@@ -57,4 +59,3 @@ test_files:
|
|
57
59
|
- spec/extended_spec.rb
|
58
60
|
- spec/included_spec.rb
|
59
61
|
- spec/alternative_syntax_spec.rb
|
60
|
-
- spec/note.txt
|
data/spec/note.txt
DELETED