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 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 two properties that will cascade down all descendents
15
+ now create properties that will cascade down all descendents
16
16
 
17
17
  Parent.cascade :eye_color, :hair_color
18
18
 
19
- set the properties on ```Parent```
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
- p Child.hair_color # => "black"
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 are easy. The first method is to bracket them in Array pairs. For example:
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, :head
73
- Parent.all! :arms, :legs, :head
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], [:head, :none]
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
- Note: CC is equivalent to CascadingClasses
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 and class methods.
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 the singleton class of ```A```.
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 cascaded properties is by including a third argument
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
- define_method property do
9
- val = instance_variable_get "@#{property}"
10
- return val unless (val.nil? and self != klass)
11
- (self.class == Class) ? superclass.send(property) :
12
- self.class.send(property)
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
- define_method "#{property}=" do |v|
16
- instance_variable_set "@#{property}", v
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 name, default, inst_too = prop[0..2]
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| res[name] = [defaults[name], inst[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
- @instances_too = {} # values are true/false
90
+ @defaults, @instances_too = {}, {}
91
+ @getters, @setters = {}, {}
72
92
 
73
93
  return unless block_given?
74
94
  if block.arity == 0
@@ -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, :class_eval]
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| raise NameError, "Illegal property name: #{prop}" if
47
- illegal_names.include? prop }
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
- Parent.hair_color.must_equal "black"
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
- Parent.hair_color.must_equal "black"
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
- Parent.hair_color.must_equal "black"
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
- Parent.hair_color.must_equal "black"
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
- Parent.hair_color.must_equal "black"
134
- Child.hair_color.must_equal "blond"
135
- GrandChild.hair_color.must_equal "blond"
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.eye_color.must_equal nil
138
- Child.eye_color.must_equal "brown"
139
- GrandChild.eye_color.must_equal "brown"
164
+ Parent.eyes.must_equal nil
165
+ Child.eyes.must_equal "brown"
166
+ GrandChild.eyes.must_equal "brown"
140
167
 
141
- Parent.piercings.must_equal false
142
- Child.piercings.must_equal false
143
- GrandChild.piercings.must_equal false
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
@@ -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
@@ -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.2.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-08 00:00:00.000000000Z
12
+ date: 2011-08-09 00:00:00.000000000Z
13
13
  dependencies: []
14
- description: Similar to active_support/core_ext/class/attribute.rb but better. Also,
15
- doesn't monkey-patch Class
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
@@ -1,2 +0,0 @@
1
- you should expect to see many "already initialized constant" warnings
2
- This happens because the same constants must get reloaded for every test