cascading_classes 0.2.0 → 0.3.0

Sign up to get free protection for your applications and to get access to all the features.
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