cushion_defaults 0.4.0 → 0.5.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +14 -1
- data/README.md +131 -18
- data/lib/cushion_defaults/class_methods.rb +80 -4
- data/lib/cushion_defaults/configuration.rb +8 -3
- data/lib/cushion_defaults/defaults_hash.rb +1 -0
- data/lib/cushion_defaults.rb +2 -2
- metadata +3 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 725ea185c013e34737b4bf5f46e0fa08fff68428
|
4
|
+
data.tar.gz: 8414ae7cce652e15c91e654194c435ebe8aa0ed4
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: eaf552d0557b4c07c083fa3db1074f4ddc058b20d8039e35d1f1c772e5f49ce3ba1e1e5a78b92973d7f4565a3ed45ebbbad2f36eee2f2e1a8c2fe3af9bce3f82
|
7
|
+
data.tar.gz: 68c8e99dd1543ae61ba627678eddaf63e962f276b5ffceb2e38eb812ec67dca281afd9f4157cbf7acae57a10d3e114bc49bb98204d7315fdf850ef9869dc7887
|
data/CHANGELOG.md
CHANGED
@@ -52,4 +52,17 @@
|
|
52
52
|
|
53
53
|
-0.4.0 - NEW FEATURE: Proc Cushions
|
54
54
|
- You can now set a default to a proc that will be evaluated whenever an instance variable is absent.
|
55
|
-
- For more information, see "Proc Cushions" in README.md.
|
55
|
+
- For more information, see "Proc Cushions" in README.md.
|
56
|
+
|
57
|
+
## 0.5.x
|
58
|
+
|
59
|
+
-0.5.0
|
60
|
+
- NEW FEATURE: Bang Readers
|
61
|
+
- When called, a bang reader (e.g., +var!+) crystallizes +var+, if not set, to the default value for +var+.
|
62
|
+
- Especially useful for permanently fixing the value of a proc cushion.
|
63
|
+
- Key method: +ClassMethods#bang_the_cushion+
|
64
|
+
- NEW OPTION: bang_things_up
|
65
|
+
- If true, bang readers will automatically be set up every time a cushion_reader is created.
|
66
|
+
- Default: true
|
67
|
+
- Bugfix interaction between procs and #crystallize_defaults
|
68
|
+
- Expand README.md
|
data/README.md
CHANGED
@@ -22,20 +22,32 @@ I try to keep all of this up-to-date, but the latest information can always be f
|
|
22
22
|
3. Easily allow subclasses to inherit the default values of their ancestor classes or override them with their own default values. CushionDefaults is in this respect more flexible than using either constants or `@@defaults` variables. As an added bonus, changes to the defaults of a superclass cascade down and affect the defaults of subclasses.
|
23
23
|
4. Optionally, if you think of your defaults as configuration rather than logic, pull them out of your code and put them in class-specific YAML files that can be automatically loaded in.
|
24
24
|
5. Using the YAML technique, you can maintain multiple sets of defaults and load in the appropriate one depending on the environment.
|
25
|
-
6. If you follow the common pattern of setting instance variables to the default value (e.g., `@var = params[:var] || default_for_var`), you have no way of distinguishing between when `x@var` is set to the default value because that was actively selected (`params[:var]...`) and when it is set to the default because it otherwise would have been nil (`... || default_for_var`). This is especially important when defaults change occasionally (or even vary regularly!). CushionDefaults makes this situation easy to handle.
|
25
|
+
6. If you follow the common pattern of setting instance variables to the default value (e.g., `@var = params[:var] || default_for_var`), you have no way of distinguishing between when `x@var` is set to the default value because that was actively selected (`params[:var]...`) and when it is set to the default because it otherwise would have been nil (`... || default_for_var`). This is especially important when defaults change occasionally (or even vary regularly!). CushionDefaults makes this situation easy to handle.
|
26
|
+
|
27
|
+
## Give Me a Quick Example
|
26
28
|
|
27
29
|
```ruby
|
30
|
+
require 'color'
|
31
|
+
|
28
32
|
class Person
|
29
33
|
include CushionDefaults
|
30
34
|
self.defaults[:favorite_color] = 'blue'
|
31
|
-
|
35
|
+
self.defaults[:favorite_shade_of_gray] = do |instance|
|
36
|
+
Color::RGB.by_name(instance.favorite_color).to_grayscale.to_rgb
|
37
|
+
end
|
38
|
+
cushion :favorite_color, :favorite_shade_of_gray
|
32
39
|
end
|
33
40
|
|
34
41
|
ryan, julia = Person.new, Person.new
|
35
42
|
ryan.favorite_color = 'blue'
|
36
43
|
|
44
|
+
ryan.favorite_shade_of_gray # RGB [#808080], computed from favorite_color == 'blue'
|
45
|
+
ryan.favorite_shade_of_gray = Color::RGB.by_name('silver')
|
46
|
+
ryan.favorite_shade_of_gray # RGB [#cccccc]
|
47
|
+
|
37
48
|
ryan.favorite_color # 'blue'
|
38
49
|
ryan.has_specified?(:favorite_color) # true
|
50
|
+
|
39
51
|
julia.favorite_color # 'blue'
|
40
52
|
julia.has_specified?(:favorite_color) # false
|
41
53
|
|
@@ -44,7 +56,9 @@ Person.defaults[:favorite_color] = 'green'
|
|
44
56
|
ryan.favorite_color # 'blue'
|
45
57
|
julia.favorite_color # 'green'
|
46
58
|
```
|
59
|
+
|
47
60
|
## How Do I Get It?
|
61
|
+
|
48
62
|
`gem install 'cushion_defaults'` if you just want the gem.
|
49
63
|
|
50
64
|
If you want to help out the project or edit the source code, clone the repository (hosted at [GitHub](https://github.com/posgarou/cushion_defaults)), fork it, make changes, and make a pull request.
|
@@ -99,10 +113,12 @@ class Klass
|
|
99
113
|
self.defaults = {first: Klass, second: Klass, third: Klass}
|
100
114
|
cushion_defaults
|
101
115
|
end
|
116
|
+
|
102
117
|
class SubKlass < Klass
|
103
118
|
self.defaults += {second: SubKlass, fourth: SubKlass}
|
104
119
|
cushion :fourth
|
105
120
|
end
|
121
|
+
|
106
122
|
class SubSubKlass < SubKlass
|
107
123
|
self.defaults[:third] = SubSubKlass
|
108
124
|
end
|
@@ -114,14 +130,14 @@ z.first = 'custom'
|
|
114
130
|
Calling `#first`, `#second`, `#third`, and `#fourth`, then, would produce the following results on x, y, and z:
|
115
131
|
|
116
132
|
```ruby
|
117
|
-
|
133
|
+
[x.first, x.second, x.third]
|
118
134
|
# [Klass, Klass, Klass]
|
119
135
|
# x.fourth would return NoMethodError
|
120
136
|
|
121
|
-
|
137
|
+
[y.first, y.second, y.third, y.fourth]
|
122
138
|
# [Klass, SubKlass, Klass, SubKlass]
|
123
139
|
|
124
|
-
|
140
|
+
[z.first, z.second, z.third, z.fourth]
|
125
141
|
# ['custom', SubKlass, SubSubKlass, SubKlass]
|
126
142
|
```
|
127
143
|
|
@@ -135,7 +151,7 @@ z.second # 'totally new value'
|
|
135
151
|
|
136
152
|
### Adding and Removing Readers and Writers
|
137
153
|
|
138
|
-
Now, if we were to later add a new default to Plant
|
154
|
+
Now, if we were to later add a new default to our Plant class from up above
|
139
155
|
|
140
156
|
```ruby
|
141
157
|
Plant.defaults[:climate] = 'temperate'
|
@@ -144,6 +160,7 @@ Plant.defaults[:climate] = 'temperate'
|
|
144
160
|
and ran
|
145
161
|
|
146
162
|
```ruby
|
163
|
+
rhododendron = Plant.new
|
147
164
|
rhododendron.climate
|
148
165
|
```
|
149
166
|
|
@@ -209,6 +226,8 @@ update_readers: true
|
|
209
226
|
update_writers: true
|
210
227
|
```
|
211
228
|
|
229
|
+
For a complete list of options available (along with explanations), see the docs for CushionDefaults::Configuration, especially the method group "Option Reader/Writers."
|
230
|
+
|
212
231
|
### Proc Cushions
|
213
232
|
|
214
233
|
CushionDefaults now supports proc cushions, which offer a powerful new level of flexibility in getting and setting defaults.
|
@@ -219,38 +238,44 @@ Take the following example:
|
|
219
238
|
|
220
239
|
```ruby
|
221
240
|
class Language
|
222
|
-
attr_accessor :
|
241
|
+
attr_accessor :say_hello
|
223
242
|
def initialize(&block)
|
224
243
|
yield self if block_given?
|
225
244
|
end
|
226
245
|
end
|
227
246
|
|
228
247
|
$languages = {
|
229
|
-
en: Language.new { |l| l.
|
230
|
-
fr: Language.new { |l| l.
|
248
|
+
en: Language.new { |l| l.say_hello = 'Hello' },
|
249
|
+
fr: Language.new { |l| l.say_hello = 'Bonjour' }
|
231
250
|
}
|
232
251
|
|
233
252
|
class Person
|
234
253
|
include CushionDefaults
|
235
254
|
|
255
|
+
attr_accessor :name
|
256
|
+
|
257
|
+
def initialize(&block)
|
258
|
+
yield self if block_given?
|
259
|
+
end
|
260
|
+
|
236
261
|
self.defaults[:language] = $languages[:en]
|
237
262
|
|
238
|
-
# By default, return the greeting for the
|
263
|
+
# By default, return the greeting for the person's language and the person's name
|
239
264
|
self.defaults[:greeting] = proc do |instance|
|
240
|
-
instance.language.
|
265
|
+
"#{instance.language.say_hello}, #{instance.name}"
|
241
266
|
end
|
242
267
|
|
243
268
|
cushion_defaults
|
244
269
|
end
|
245
270
|
|
246
|
-
|
247
|
-
|
271
|
+
peter = Person.new { |p| p.name = 'Peter' }
|
272
|
+
peter.greeting # 'Hello, Peter'
|
248
273
|
|
249
|
-
pierre = Person.new
|
250
|
-
pierre.greeting # 'Hello', since languages[:en] is the default language
|
274
|
+
pierre = Person.new { |p| p.name = 'Pierre' }
|
275
|
+
pierre.greeting # 'Hello, Pierre', since languages[:en] is the default language
|
251
276
|
|
252
277
|
pierre.language = $languages[:fr]
|
253
|
-
pierre.greeting # 'Bonjour', since languages[:fr] is now pierre's greeting
|
278
|
+
pierre.greeting # 'Bonjour, Pierre', since languages[:fr] is now pierre's language, and #greeting gets its #say_hello
|
254
279
|
|
255
280
|
pierre.greeting = 'Salut!'
|
256
281
|
pierre.greeting # 'Salut!', since pierre has a custom greeting
|
@@ -279,9 +304,32 @@ passerby.when_i_noticed_you # Time.now
|
|
279
304
|
sleep(1.0)
|
280
305
|
|
281
306
|
passerby.when_i_noticed_you == Time.now # false—1 sec later
|
307
|
+
|
282
308
|
```
|
283
309
|
|
284
|
-
|
310
|
+
Alternatively, you can write a normal proc and call the variable's +bang_reader+ if you're worried the variable may not be set.
|
311
|
+
|
312
|
+
```ruby
|
313
|
+
class Person
|
314
|
+
include CushionDefaults
|
315
|
+
|
316
|
+
self.defaults[:when_i_noticed_you] = proc { Time.now }
|
317
|
+
|
318
|
+
cushion :when_i_noticed_you
|
319
|
+
end
|
320
|
+
|
321
|
+
passerby = Person.new
|
322
|
+
|
323
|
+
# since @when_i_noticed_you is undefined the bang_reader sets it to Time.now
|
324
|
+
passerby.when_i_noticed_you! # Time.now
|
325
|
+
|
326
|
+
# wait a sec
|
327
|
+
sleep(1.0)
|
328
|
+
|
329
|
+
passerby.when_i_noticed_you == Time.now # false—1 sec later
|
330
|
+
```
|
331
|
+
|
332
|
+
These techniques can provide sophisticated means of both setting cushions or defaults while allowing customizable values for particular instances.
|
285
333
|
|
286
334
|
### Freezing and Thawing Defaults
|
287
335
|
|
@@ -475,6 +523,48 @@ Plant.new.color # 'green'
|
|
475
523
|
|
476
524
|
(Crystallizing defaults should be carefully distinguished from freezing defaults: crystallizing defaults applies to specific instances, whereas freezing defaults applies to the class itself.)
|
477
525
|
|
526
|
+
### What About Persistence?
|
527
|
+
|
528
|
+
The key rule when using CushionDefaults with any sort of persistence is this: use instance variables, and not `cushion_reader`s, when preparing objects for storage.
|
529
|
+
|
530
|
+
If you use `cushion_reader`s when storing your objects, you run the risk of accidentally crystallizing your defaults. Take, for instance, the following (incorrect) code:
|
531
|
+
|
532
|
+
```ruby
|
533
|
+
class AccidentallyInLove
|
534
|
+
include CushionDefaults
|
535
|
+
self.defaults[:girl_for_me] = proc { %w(Sally Jane Dora Annabel).sample }
|
536
|
+
cushion :girl_for_me
|
537
|
+
|
538
|
+
def marshal_dump
|
539
|
+
# This is the problem: it returns the default for marshaling!
|
540
|
+
[girl_for_me]
|
541
|
+
end
|
542
|
+
def marshal_load array
|
543
|
+
self.girl_for_me = array.first
|
544
|
+
end
|
545
|
+
end
|
546
|
+
|
547
|
+
marco = AccidentallyInLove.new
|
548
|
+
|
549
|
+
# only 0.4% chance these are the same!
|
550
|
+
5.times { puts marco.girl_for_me }
|
551
|
+
|
552
|
+
marco = Marshal.load(Marshal.dump(marco))
|
553
|
+
|
554
|
+
# Marco settled down without realizing it
|
555
|
+
5.times { puts marco.girl_for_me }
|
556
|
+
```
|
557
|
+
|
558
|
+
Assuming your intent in marshaling isn't to crystallize the default and force him to settle down, you can either leave in place the default methods (which work) or overload `marshal_dump` as follows:
|
559
|
+
|
560
|
+
```ruby
|
561
|
+
def marshal_dump
|
562
|
+
[@girl_for_me]
|
563
|
+
end
|
564
|
+
```
|
565
|
+
|
566
|
+
(Note, however, that any sort of reconstruction of objects is incompatible with setting `Configuration.ignore_attempts_to_set_nil` to false.)
|
567
|
+
|
478
568
|
### Pushy and Polite Defaults
|
479
569
|
|
480
570
|
Pushy and polite defaults are an experimental feature. Rough documentation can be found in the docs, and more details will be forthcoming.
|
@@ -518,4 +608,27 @@ If you have the time, tell me why.
|
|
518
608
|
|
519
609
|
Not a useful concept? Don't like the implementation? Think the default configuration options should be different? Edit [the wiki](https://github.com/posgarou/cushion_defaults/wiki) and let me know.
|
520
610
|
|
521
|
-
If you have any specific suggestions for how to make CushionDefaults better, I'd love to hear them.
|
611
|
+
If you have any specific suggestions for how to make CushionDefaults better, I'd love to hear them.
|
612
|
+
|
613
|
+
## Should I Stay or Should I Go Now?
|
614
|
+
|
615
|
+
Ultimately that's your decision. Try it, and see if it works for your use case. That said, here are some general guidelines from my perspective.
|
616
|
+
|
617
|
+
### When *Should* I Use CushionDefaults?
|
618
|
+
|
619
|
+
When you need or want...
|
620
|
+
|
621
|
+
1. DRY defaults handling.
|
622
|
+
2. Flexibility.
|
623
|
+
3. A powerful feature set for handling (and overriding) inheritance of defaults.
|
624
|
+
4. To know when an instance variable is set to the default and when it is simply not specified.
|
625
|
+
5. The ability to manage and maintain multiple sets of defaults (while remaining DRY).
|
626
|
+
6. To separate your defaults (configuration) off from your codebase (logic).
|
627
|
+
7. To gracefully handle changing defaults.
|
628
|
+
8. To ensure that some or all of your defaults *don't* change.
|
629
|
+
|
630
|
+
### When *Shouldn't* I Use CushionDefaults?
|
631
|
+
|
632
|
+
1. *When speed is absolutely critical.* CushionDefaults is pretty fast (see `benchmarks/simple_benchmark.rb`), since it runs almost entirely on a series of hash lookups. But there's no way it could be as fast as `attr_accessor`: it just does more, and more computations means more time. If you have hundreds of thousands of calculations that you need performed lightning fast, you should look elsewhere.
|
633
|
+
2. *When working in a Rails environment.* CushionDefaults may eventually spawn a companion project CushionDefaults-Rails, but for now it's just not the right tool for a Rails job. There are plenty of libraries that would be better for this purpose, e.g., [default_value_for](https://github.com/FooBarWidget/default_value_for).
|
634
|
+
3. *When you want to keep your dependencies down.* Some people end up with 150 apps on their phones; others end up with 150 gems in their projects. CushionDefaults itself doesn't depend on any other gems (in production), but that still doesn't mean it's worth the extra overhead to use it in every project.
|
@@ -86,6 +86,9 @@ module CushionDefaults
|
|
86
86
|
# Note that if the default responds to :call (a proc, e.g.), then the default is instead called with the instance
|
87
87
|
# variable and the symbolic representation of the default requested. This allows for proc cushions.
|
88
88
|
#
|
89
|
+
# Will set up {#bang_reader}s if
|
90
|
+
# {CushionDefaults::Configuration#bang_things_up Configuration#bang_things_up} is true.
|
91
|
+
#
|
89
92
|
# The readers are named according to the same format as +attr_reader+.
|
90
93
|
# @param syms [*#to_sym] instance variables that should have +cushion_readers+
|
91
94
|
# @see Configuration#update_readers
|
@@ -106,7 +109,68 @@ module CushionDefaults
|
|
106
109
|
defaults[sym]
|
107
110
|
end
|
108
111
|
end
|
109
|
-
CushionDefaults.log("cushion_reader #{
|
112
|
+
CushionDefaults.log("cushion_reader #{sym_str} established for #{self}")
|
113
|
+
end
|
114
|
+
bang_reader *syms if CushionDefaults.conf.bang_things_up
|
115
|
+
end
|
116
|
+
|
117
|
+
# Identical to {#cushion_reader} with one important exception: after determining the default value, +bang_reader+
|
118
|
+
# goes on to crystallize this default value for the instance.
|
119
|
+
#
|
120
|
+
# This is especially useful with proc cushions, as the below examples make clear.
|
121
|
+
#
|
122
|
+
# Note that this method is equivalent to calling +instance.crystallize_default(:sym)+.
|
123
|
+
#
|
124
|
+
# Note also, finally, that bang_readers can exist and function even if no {#cushion_writer}s are defined.
|
125
|
+
#
|
126
|
+
# @param syms [*#to_sym] instance variables that should have +bang_readers+
|
127
|
+
# @see CushionDefaults::Configuration#bang_things_up Configuration#bang_things_up
|
128
|
+
# @see CushionDefaults::CushionDefaults#crystalize_default CushionDefaults#crystalize_default
|
129
|
+
#
|
130
|
+
# @example Simple Example #1: Flowers for cushion_reader
|
131
|
+
# class Flower
|
132
|
+
# include CushionDefaults
|
133
|
+
# self.defaults[:he_loves_me] = proc { (Time.now.sec % 2).zero? }
|
134
|
+
# cushion :he_loves_me
|
135
|
+
# end
|
136
|
+
#
|
137
|
+
# daisy = Flower.new
|
138
|
+
#
|
139
|
+
# daisy.he_loves_me # true
|
140
|
+
#
|
141
|
+
# # slight delay...
|
142
|
+
# daisy.he_loves_me # false
|
143
|
+
#
|
144
|
+
# # slight delay...
|
145
|
+
# daisy.he_loves_me! # true
|
146
|
+
#
|
147
|
+
# 5.times { daisy.he_loves_me } # [true, true, true, true, true]
|
148
|
+
#
|
149
|
+
# @example Simple Example #2: Wake Up Little Susie
|
150
|
+
# class Dreamer
|
151
|
+
# include CushionDefaults
|
152
|
+
# self.defaults[:time_awoken] = proc { Time.now }
|
153
|
+
# cushion :time_awoken
|
154
|
+
# end
|
155
|
+
#
|
156
|
+
# little_susie = Dreamer.new
|
157
|
+
#
|
158
|
+
# little_susie.time_awoken # returns Time.now, but doesn't set @time_awoken
|
159
|
+
# little_susie.time_awoken! # sets @time_awoken to Time.now
|
160
|
+
#
|
161
|
+
# little_susie.time_awoken # returns the @time_awoken set in the line above
|
162
|
+
# little_susie.time_awoken! # returns @time_awoken and does not set it to a new value
|
163
|
+
def bang_reader(*syms)
|
164
|
+
syms.each do |sym|
|
165
|
+
sym = sym.to_sym
|
166
|
+
sym_str = "#{sym}!"
|
167
|
+
if self_or_parent_instance_method?(sym)
|
168
|
+
CushionDefaults.log("#{self} or a parent class already has a bang method #{sym_str}", :warn)
|
169
|
+
end
|
170
|
+
define_method(sym_str.to_sym) do
|
171
|
+
crystallize_default(sym)
|
172
|
+
end
|
173
|
+
CushionDefaults.log("bang_reader #{sym_str} established for #{self}")
|
110
174
|
end
|
111
175
|
end
|
112
176
|
|
@@ -156,7 +220,7 @@ module CushionDefaults
|
|
156
220
|
end
|
157
221
|
end
|
158
222
|
|
159
|
-
# Undefines
|
223
|
+
# Undefines the reader for sym in this class (if present).
|
160
224
|
# @note This method will delete any method of the form +sym+, not just cushion_readers.
|
161
225
|
# @param sym [#to_sym] instance variable to delete reader for
|
162
226
|
def remove_reader(sym)
|
@@ -167,7 +231,18 @@ module CushionDefaults
|
|
167
231
|
end
|
168
232
|
end
|
169
233
|
|
170
|
-
# Undefines any
|
234
|
+
# Undefines any bang method for sym in this class (if present).
|
235
|
+
# @note This method will delete any method of the form +sym!+, not just bang readers.
|
236
|
+
# @param sym [#to_sym] instance variable to delete bang method for
|
237
|
+
def remove_bang(sym)
|
238
|
+
sym = "sym!".to_sym
|
239
|
+
if self_has_method?(sym)
|
240
|
+
undef_method(sym)
|
241
|
+
CushionDefaults.log("bang reader #{sym} removed from #{self}", :info)
|
242
|
+
end
|
243
|
+
end
|
244
|
+
|
245
|
+
# Undefines any writer for sym in this class (if present).
|
171
246
|
# @note This method will delete any method of the format 'sym=', not just cushion_writers.
|
172
247
|
# @param sym [#to_sym] instance variable to delete writer for
|
173
248
|
def remove_writer(sym)
|
@@ -178,7 +253,8 @@ module CushionDefaults
|
|
178
253
|
end
|
179
254
|
end
|
180
255
|
|
181
|
-
# Sets up both {#cushion_reader}s and {#cushion_writer}s for +syms+.
|
256
|
+
# Sets up both {#cushion_reader}s and {#cushion_writer}s for +syms+. Will set up {#bang_reader}s if
|
257
|
+
# {CushionDefaults::Configuration#bang_things_up Configuration#bang_things_up} is true.
|
182
258
|
# @param syms [*#to_sym] Those instance variables that should have {#cushion_reader}s and {#cushion_writer}s.
|
183
259
|
def cushion(*syms)
|
184
260
|
cushion_reader(*syms)
|
@@ -31,13 +31,17 @@ module CushionDefaults
|
|
31
31
|
# {#yaml_source_folder}. Def. nil.
|
32
32
|
attr_writer :yaml_source_full_path
|
33
33
|
|
34
|
-
# @return [boolean] if true, CushionDefaults makes log entries. Def. true.
|
35
|
-
attr_accessor :record_in_log
|
36
|
-
|
37
34
|
# @return [boolean] if true, CushionDefaults will complain (warning level) when it cannot find a YAML configuration
|
38
35
|
# file for a class. If false, it only posts this message at the debug level. Def. false.
|
39
36
|
attr_accessor :whiny_yaml
|
40
37
|
|
38
|
+
# @return [boolean] if true, all calls to {ClassMethods#cushion_reader}, implicit or explicit, will also call
|
39
|
+
# {ClassMethods#bang_reader}.
|
40
|
+
attr_accessor :bang_things_up
|
41
|
+
|
42
|
+
# @return [boolean] if true, CushionDefaults makes log entries. Def. true.
|
43
|
+
attr_accessor :record_in_log
|
44
|
+
|
41
45
|
# @return [boolean] if true, calls to cushion_writer methods will not set the instance variable if the value passed in
|
42
46
|
# is nil (thus allowing cushion_reader to still return the default value, rather than nil). Def. true.
|
43
47
|
# @example Ignored Call to cushion_writer When ignore_attempts_to_set_nil == true
|
@@ -127,6 +131,7 @@ module CushionDefaults
|
|
127
131
|
self.auto_load_from_yaml = true
|
128
132
|
self.yaml_source_folder = 'config/cushion_defaults/'
|
129
133
|
self.yaml_source_full_path = nil
|
134
|
+
self.bang_things_up = true
|
130
135
|
self.record_in_log = true
|
131
136
|
self.logger = Logger.new $stdout
|
132
137
|
self.log_lvl = Logger::INFO
|
@@ -232,6 +232,7 @@ module CushionDefaults
|
|
232
232
|
# @see ClassMethods#remove_writer
|
233
233
|
def remove_methods_as_needed(key)
|
234
234
|
@owner.remove_reader key.to_sym if CushionDefaults.conf.update_readers
|
235
|
+
@owner.remove_bang key.to_sym if CushionDefaults.conf.update_readers
|
235
236
|
@owner.remove_writer key.to_sym if CushionDefaults.conf.update_writers
|
236
237
|
end
|
237
238
|
|
data/lib/cushion_defaults.rb
CHANGED
@@ -28,7 +28,7 @@ require 'cushion_defaults/errors'
|
|
28
28
|
module CushionDefaults
|
29
29
|
|
30
30
|
# Version constant
|
31
|
-
VERSION = '0.
|
31
|
+
VERSION = '0.5.0'
|
32
32
|
|
33
33
|
# The path of the first file that +includes+ CushionDefaults.
|
34
34
|
CALLING_PATH = File.expand_path(File.dirname($0)) + '/'
|
@@ -175,7 +175,7 @@ module CushionDefaults
|
|
175
175
|
# acting if a nilish value is specified and the value for :default_key is nilish.
|
176
176
|
if !has_specified? default_key || (act_if_nilish && CushionDefaults.nilish?(instance_variable_get("@#{default_key}")))
|
177
177
|
default_value = default(default_key)
|
178
|
-
instance_variable_set("@#{default_key}", default_value)
|
178
|
+
instance_variable_set("@#{default_key}", default_value.respond_to?(:call) ? default_value.call(self, default_key) : default_value)
|
179
179
|
else
|
180
180
|
log("Did not update #{default_key}")
|
181
181
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cushion_defaults
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Mitchell
|
@@ -38,9 +38,8 @@ dependencies:
|
|
38
38
|
- - "~>"
|
39
39
|
- !ruby/object:Gem::Version
|
40
40
|
version: '0.8'
|
41
|
-
description:
|
42
|
-
|
43
|
-
variable is undefined.
|
41
|
+
description: Cushion your instance variables. Get a default if a variable isn’t defined.
|
42
|
+
DRY off your code.
|
44
43
|
email: posgarou@gmail.com
|
45
44
|
executables: []
|
46
45
|
extensions: []
|