cushion_defaults 0.5.1 → 0.5.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/CHANGELOG.md +63 -49
- data/README.md +21 -3
- data/lib/cushion_defaults/class_methods.rb +44 -45
- data/lib/cushion_defaults/configuration.rb +6 -6
- data/lib/cushion_defaults/defaults_hash.rb +14 -14
- data/lib/cushion_defaults.rb +45 -41
- metadata +4 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: bca05c80623f43fc5f8d61f016ffb6ee18f832cb
|
4
|
+
data.tar.gz: daa36bc9f2da343a5e4699bd42e6c415da8e80cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 46c86103b998e49862173cc1456e1c14b6615426e9c1816ac50fa9e964b8386c3b13e27fb403cd597cfd2b65df6e6fbdb7bb556e86de0473ca2a91f7ba172cb5
|
7
|
+
data.tar.gz: 8b149e6f6e9d07047c9768348263ebd90acd1ad7242d2bd3368157accadb26e709ec4c5bf9e5daaf8e9c28df6a4c27a0e73f4856a3210668a45cc35890266f89
|
data/CHANGELOG.md
CHANGED
@@ -1,74 +1,88 @@
|
|
1
1
|
# CHANGELOG
|
2
2
|
|
3
|
-
## 0.
|
3
|
+
## 0.5.x
|
4
4
|
|
5
|
-
- 0.
|
6
|
-
- 0.0.
|
7
|
-
-
|
8
|
-
- Specify GitHub homepage.
|
9
|
-
- 0.0.2
|
10
|
-
- Improve `cushion_reader` speed by approx. 15%.
|
11
|
-
- Specify Ruby version >= 2.0.0.
|
12
|
-
- 0.0.3
|
13
|
-
- Fix various bugs related to YAML config loading.
|
14
|
-
- Improve examples.
|
5
|
+
- 0.5.2: PERFORMANCE
|
6
|
+
- Another 40% shaved off `cushion_reader` execution times. (In total, execution speed is ~180% faster than v. 0.0.0.)
|
7
|
+
- Between roughly 18% and 75% shaved off `cushion_writer` (depending on input).
|
15
8
|
|
16
|
-
|
9
|
+
- 0.5.1
|
10
|
+
- DEPENDENCY: Support now added for Ruby >= 1.9.3
|
11
|
+
- CONFIGURATION: Default log level now WARN (was INFO)
|
12
|
+
- BUGFIX: Remove unnecessary warning on adding `bang_readers`
|
13
|
+
- PERFORMANCE: Moderate performance gains (approx. 20%) on `cushion_reader`
|
17
14
|
|
18
|
-
- 0.
|
19
|
-
- NEW FEATURE:
|
20
|
-
-
|
21
|
-
-
|
22
|
-
-
|
23
|
-
-
|
24
|
-
-
|
25
|
-
|
26
|
-
-
|
15
|
+
- 0.5.0
|
16
|
+
- NEW FEATURE: Bang Readers
|
17
|
+
- When called, a bang reader (e.g., `var!`) crystallizes `var`, if not set, to the default value for `var`.
|
18
|
+
- Especially useful for permanently fixing the value of a proc cushion.
|
19
|
+
- Key method: `ClassMethods#bang_reader`
|
20
|
+
- NEW OPTION: bang_things_up
|
21
|
+
- If true, bang readers will automatically be set up every time a cushion_reader is created.
|
22
|
+
- Default: true
|
23
|
+
- BUGFIX: fix interaction between procs and #crystallize_defaults
|
24
|
+
- DOCUMENTATION: Expand README.md
|
25
|
+
|
26
|
+
## 0.4.x
|
27
|
+
|
28
|
+
- 0.4.0 - NEW FEATURE: Proc Cushions
|
29
|
+
- You can now set a default to a proc that will be evaluated whenever an instance variable is absent.
|
30
|
+
- For more information, see "Proc Cushions" in README.md.
|
31
|
+
|
32
|
+
## 0.3.x
|
33
|
+
|
34
|
+
- 0.3.1: BUGFIX: Corrected fatal error in #freeze_defaults, #deep_freeze_defaults, and #thaw_defaults
|
35
|
+
|
36
|
+
- 0.3.0 - NEW FEATURE: Freezing and thawing defaults.
|
37
|
+
- You may wish to prevent a default from further modification, either permanently or temporarily. This can prevent silly mistakes that are otherwise difficult to track down. CushionDefaults now makes this possible via a freezing and thawing API.
|
38
|
+
- For more information, see especially:
|
39
|
+
- ClassMethods#freeze_default
|
40
|
+
- ClassMethods#deep_freeze_default
|
41
|
+
- ClassMethods#thaw_default
|
27
42
|
|
28
43
|
## 0.2.x
|
29
44
|
|
30
45
|
- 0.2.0
|
31
46
|
- Place Configuration within the CushionDefaults module.
|
47
|
+
|
32
48
|
- IMPROVEMENT: `cushion_defaults.gemspec`
|
33
49
|
- Clarify and expand `cushion_defaults.gemspec`. Was insufficient before.
|
34
50
|
- Now specifies development dependencies.
|
35
51
|
- Add Gemfile for bundler
|
52
|
+
|
36
53
|
- IMPROVEMENT: Testing
|
37
54
|
- `test/` renamed to `spec/`
|
38
55
|
- Add `.rspec` and `spec/spec_helper.rb`
|
56
|
+
|
39
57
|
- DOCUMENTATION: Numerous expansions
|
40
58
|
|
41
|
-
## 0.
|
59
|
+
## 0.1.x
|
42
60
|
|
43
|
-
- 0.
|
44
|
-
-
|
45
|
-
-
|
46
|
-
- ClassMethods#freeze_default
|
47
|
-
- ClassMethods#deep_freeze_default
|
48
|
-
- ClassMethods#thaw_default
|
49
|
-
- 0.3.1: BUGFIX: Corrected fatal error in #freeze_defaults, #deep_freeze_defaults, and #thaw_defaults
|
61
|
+
- 0.1.1
|
62
|
+
- Greatly improve and expand documentation.
|
63
|
+
- Switch from rdoc to Yard
|
50
64
|
|
51
|
-
|
65
|
+
- 0.1.0
|
66
|
+
- NEW FEATURE: Logging
|
67
|
+
- Add `config.record_in_log` (boolean), `config.log_lvl (int)`, and `config.logger` (Logger or similar) options.
|
68
|
+
- Add logging throughout the module at various levels.
|
69
|
+
- Logging enabled by default at info level.
|
52
70
|
|
53
|
-
-
|
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.
|
71
|
+
- Improve performance of `cushion_reader` by approx. 115%.
|
56
72
|
|
57
|
-
## 0.
|
73
|
+
## 0.0.x
|
58
74
|
|
59
|
-
-0.
|
60
|
-
-
|
61
|
-
|
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: fix interaction between procs and #crystallize_defaults
|
68
|
-
- DOCUMENTATION: Expand README.md
|
75
|
+
- 0.0.3
|
76
|
+
- Fix various bugs related to YAML config loading.
|
77
|
+
- Improve examples.
|
69
78
|
|
70
|
-
-0.
|
71
|
-
-
|
72
|
-
-
|
73
|
-
|
74
|
-
|
79
|
+
- 0.0.2
|
80
|
+
- Improve `cushion_reader` speed by approx. 15%.
|
81
|
+
- Specify Ruby version >= 2.0.0.
|
82
|
+
|
83
|
+
- 0.0.1
|
84
|
+
- Include MIT License.
|
85
|
+
- Specify GitHub homepage.
|
86
|
+
|
87
|
+
|
88
|
+
- 0.0.0: Initial version.
|
data/README.md
CHANGED
@@ -27,32 +27,50 @@ I try to keep all of this up-to-date, but the latest information can always be f
|
|
27
27
|
## Give Me a Quick Example
|
28
28
|
|
29
29
|
```ruby
|
30
|
+
require 'cushion_defaults' # This will be assumed henceforth.
|
30
31
|
require 'color'
|
31
32
|
|
32
33
|
class Person
|
33
34
|
include CushionDefaults
|
35
|
+
|
36
|
+
# Set the cushion or default value for @favorite_color to the static value 'blue'
|
34
37
|
self.defaults[:favorite_color] = 'blue'
|
35
|
-
|
38
|
+
|
39
|
+
# Set the cushion for @favorite_shade_of_gray to the following proc.
|
40
|
+
# As long as @favorite_shade_of_gray is not set, this proc will be evaluated at each call to #favorite_shade_of_gray.
|
41
|
+
# If we wanted to fix or crystallize the value, we could call the bang version #favorite_shade_of_gray!
|
42
|
+
self.defaults[:favorite_shade_of_gray] = proc do |instance|
|
36
43
|
Color::RGB.by_name(instance.favorite_color).to_grayscale.to_rgb
|
37
44
|
end
|
45
|
+
|
46
|
+
# #cushion sets up a cushion_reader and cushion_writer for each of the symbols passed in
|
38
47
|
cushion :favorite_color, :favorite_shade_of_gray
|
39
48
|
end
|
40
49
|
|
41
50
|
ryan, julia = Person.new, Person.new
|
51
|
+
|
42
52
|
ryan.favorite_color = 'blue'
|
43
53
|
|
44
|
-
|
45
|
-
ryan.favorite_shade_of_gray
|
54
|
+
# This value is computed by the proc cushion defined above, since ryan's @favorite_shade_of_gray isn't defined
|
55
|
+
ryan.favorite_shade_of_gray # RGB [#808080]
|
56
|
+
|
57
|
+
ryan.favorite_shade_of_gray = Color::RGB.by_name('silver') # RGB [#cccccc]
|
58
|
+
|
59
|
+
# Since ryan's @favorite_shade_of_gray is defined now, the proc isn't called
|
46
60
|
ryan.favorite_shade_of_gray # RGB [#cccccc]
|
47
61
|
|
48
62
|
ryan.favorite_color # 'blue'
|
49
63
|
ryan.has_specified?(:favorite_color) # true
|
50
64
|
|
51
65
|
julia.favorite_color # 'blue'
|
66
|
+
|
67
|
+
# When we call julia.favorite_color, we're only getting the default color
|
52
68
|
julia.has_specified?(:favorite_color) # false
|
53
69
|
|
70
|
+
# Now we set the default value for @favorite_color to a new value.
|
54
71
|
Person.defaults[:favorite_color] = 'green'
|
55
72
|
|
73
|
+
# ryan has a custom favorite color, so it doesn't affect him, but julia returns 'green' now
|
56
74
|
ryan.favorite_color # 'blue'
|
57
75
|
julia.favorite_color # 'green'
|
58
76
|
```
|
@@ -2,15 +2,15 @@ module CushionDefaults
|
|
2
2
|
# A series of class methods to be plopped into any class that includes CushionDefaults.
|
3
3
|
module ClassMethods
|
4
4
|
|
5
|
-
# Reader for the
|
5
|
+
# Reader for the @defaults@ @DefaultsHash@.
|
6
6
|
attr_reader :defaults
|
7
7
|
|
8
8
|
# @!attribute [w] defaults
|
9
|
-
# Wipe @defaults and replace it with the keys/vals of
|
9
|
+
# Wipe @defaults and replace it with the keys/vals of @replacement_hash@.
|
10
10
|
#
|
11
11
|
# If you only want to add one or more defaults, then write instead self.defaults += {new_key: val}.
|
12
12
|
#
|
13
|
-
# Note that all keys are coerced into
|
13
|
+
# Note that all keys are coerced into @Symbols@.
|
14
14
|
def defaults=(replacement_hash)
|
15
15
|
# Need to copy over keys/vals to ensure @defaults remains a DefaultsHash and retains identity
|
16
16
|
|
@@ -24,9 +24,9 @@ module CushionDefaults
|
|
24
24
|
end
|
25
25
|
end
|
26
26
|
|
27
|
-
# Equivalent to
|
27
|
+
# Equivalent to @@defaults[key] = val@
|
28
28
|
# @param key [#to_sym] key for new default.
|
29
|
-
# @param val [Object] Default value for
|
29
|
+
# @param val [Object] Default value for @key@.
|
30
30
|
def set_default(key, val)
|
31
31
|
@defaults[key.to_sym] = val
|
32
32
|
end
|
@@ -34,14 +34,14 @@ module CushionDefaults
|
|
34
34
|
# @!group Mass Default Setting Methods
|
35
35
|
|
36
36
|
# Load in the defaults for this class from a YAML file.
|
37
|
-
# If
|
38
|
-
# the current class. By default, the yaml file for
|
37
|
+
# If @file_name@ is specified, this YAML file is loaded. Otherwise, {Configuration#yaml_file_for} is evaluated for
|
38
|
+
# the current class. By default, the yaml file for @Klass@ is expected to be at @config/cushion_defaults/klass.yaml@.
|
39
39
|
# @param file_name [String] name of the YAML file to be loaded in for this class
|
40
40
|
# @see Configuration#auto_load_from_yaml
|
41
41
|
# @see Configuration#whiny_yaml
|
42
42
|
def defaults_from_yaml(file_name = nil)
|
43
43
|
if file_name
|
44
|
-
yaml_path = "#{CushionDefaults
|
44
|
+
yaml_path = "#{CushionDefaults.conf.yaml_source_full_path}#{file_name}.yaml"
|
45
45
|
else
|
46
46
|
yaml_path = CushionDefaults.conf.yaml_file_for(self)
|
47
47
|
end
|
@@ -75,7 +75,7 @@ module CushionDefaults
|
|
75
75
|
|
76
76
|
# @!group Reader/Writer
|
77
77
|
|
78
|
-
# Sets up a cushion_reader for each :sym in
|
78
|
+
# Sets up a cushion_reader for each :sym in @syms@.
|
79
79
|
#
|
80
80
|
# Each reader method checks if its instance variable (:sym) is defined. If it is, it returns that. If not, it
|
81
81
|
# returns the default value.
|
@@ -89,8 +89,8 @@ module CushionDefaults
|
|
89
89
|
# Will set up {#bang_reader}s if
|
90
90
|
# {CushionDefaults::Configuration#bang_things_up Configuration#bang_things_up} is true.
|
91
91
|
#
|
92
|
-
# The readers are named according to the same format as
|
93
|
-
# @param syms [*#to_sym] instance variables that should have
|
92
|
+
# The readers are named according to the same format as @attr_reader@.
|
93
|
+
# @param syms [*#to_sym] instance variables that should have @cushion_readers@
|
94
94
|
# @see Configuration#update_readers
|
95
95
|
def cushion_reader(*syms)
|
96
96
|
syms.each do |sym|
|
@@ -98,14 +98,14 @@ module CushionDefaults
|
|
98
98
|
if self_or_parent_instance_method?(sym)
|
99
99
|
CushionDefaults.log("#{self} or a parent class already has what looks like a getter method for #{sym_str}", :warn)
|
100
100
|
end
|
101
|
-
|
101
|
+
instance_variable_sym = "@#{sym}".to_sym
|
102
102
|
|
103
103
|
# significant performance gains from using this rather than #defaults in method below
|
104
104
|
defaults_cache = @defaults
|
105
105
|
|
106
106
|
define_method(sym) do
|
107
|
-
if instance_variable_defined?(
|
108
|
-
instance_variable_get(
|
107
|
+
if instance_variable_defined?(instance_variable_sym) && (CushionDefaults.conf.no_pushies? || defaults_cache.not_pushy?(sym))
|
108
|
+
instance_variable_get(instance_variable_sym)
|
109
109
|
else
|
110
110
|
# much faster to save as var
|
111
111
|
da_default = defaults_cache[sym]
|
@@ -117,16 +117,16 @@ module CushionDefaults
|
|
117
117
|
bang_reader *syms if CushionDefaults.conf.bang_things_up
|
118
118
|
end
|
119
119
|
|
120
|
-
# Identical to {#cushion_reader} with one important exception: after determining the default value,
|
120
|
+
# Identical to {#cushion_reader} with one important exception: after determining the default value, @bang_reader@
|
121
121
|
# goes on to crystallize this default value for the instance.
|
122
122
|
#
|
123
123
|
# This is especially useful with proc cushions, as the below examples make clear.
|
124
124
|
#
|
125
|
-
# Note that this method is equivalent to calling
|
125
|
+
# Note that this method is equivalent to calling @instance.crystallize_default(:sym)@.
|
126
126
|
#
|
127
127
|
# Note also, finally, that bang_readers can exist and function even if no {#cushion_writer}s are defined.
|
128
128
|
#
|
129
|
-
# @param syms [*#to_sym] instance variables that should have
|
129
|
+
# @param syms [*#to_sym] instance variables that should have @bang_readers@
|
130
130
|
# @see CushionDefaults::Configuration#bang_things_up Configuration#bang_things_up
|
131
131
|
# @see CushionDefaults::CushionDefaults#crystalize_default CushionDefaults#crystalize_default
|
132
132
|
#
|
@@ -177,7 +177,7 @@ module CushionDefaults
|
|
177
177
|
end
|
178
178
|
end
|
179
179
|
|
180
|
-
# Sets up a cushion_writer for each :sym in
|
180
|
+
# Sets up a cushion_writer for each :sym in @syms@.
|
181
181
|
#
|
182
182
|
# Each writer method carries out one of several checks.
|
183
183
|
#
|
@@ -191,20 +191,20 @@ module CushionDefaults
|
|
191
191
|
#
|
192
192
|
# Finally, assuming it was not flagged as nilish, the variable is set to the new value.
|
193
193
|
#
|
194
|
-
# The writers are named according to the same format as
|
195
|
-
# @param syms [*#to_sym] instance variables that should have
|
194
|
+
# The writers are named according to the same format as @attr_writer@.
|
195
|
+
# @param syms [*#to_sym] instance variables that should have @cushion_writers@
|
196
196
|
# @see Configuration#update_writers
|
197
197
|
# @see Configuration#ignore_attempts_to_set_nil
|
198
198
|
# @see Configuration#blank_str_is_nil
|
199
199
|
# @see Configuration#whiny_ignores
|
200
200
|
def cushion_writer(*syms)
|
201
201
|
syms.each do |sym|
|
202
|
-
method_name = "#{sym}="
|
202
|
+
method_name = "#{sym}=".to_sym
|
203
203
|
if self_or_parent_instance_method?(method_name)
|
204
204
|
CushionDefaults.log("#{self} or a parent class already has what looks like a setter method for #{sym}", :warn)
|
205
205
|
end
|
206
206
|
|
207
|
-
|
207
|
+
instance_variable_sym = "@#{sym}".to_sym
|
208
208
|
|
209
209
|
defaults_cache = @defaults
|
210
210
|
|
@@ -213,12 +213,11 @@ module CushionDefaults
|
|
213
213
|
if CushionDefaults.conf.whiny_ignores
|
214
214
|
CushionDefaults.log("You are attempting to set a nilish value for #{sym}. This will not be recorded, and any value set will be deleted.", :warn)
|
215
215
|
end
|
216
|
-
remove_instance_variable(instance_variable_string) if instance_variable_defined?(instance_variable_string)
|
217
216
|
else
|
218
217
|
if CushionDefaults.conf.we_have_a_pushy? && defaults_cache.pushy?(sym)
|
219
218
|
CushionDefaults.log("You are setting a value for #{sym}, but this is a pushy default and this value will not be returned by any cushion_readers.", :warn)
|
220
219
|
end
|
221
|
-
instance_variable_set(
|
220
|
+
instance_variable_set(instance_variable_sym, y)
|
222
221
|
end
|
223
222
|
end
|
224
223
|
CushionDefaults.log("cushion_writer #{sym}= established for #{self}")
|
@@ -226,7 +225,7 @@ module CushionDefaults
|
|
226
225
|
end
|
227
226
|
|
228
227
|
# Undefines the reader for sym in this class (if present).
|
229
|
-
# @note This method will delete any method of the form
|
228
|
+
# @note This method will delete any method of the form @sym@, not just cushion_readers.
|
230
229
|
# @param sym [#to_sym] instance variable to delete reader for
|
231
230
|
def remove_reader(sym)
|
232
231
|
sym = sym.to_sym
|
@@ -237,7 +236,7 @@ module CushionDefaults
|
|
237
236
|
end
|
238
237
|
|
239
238
|
# Undefines any bang method for sym in this class (if present).
|
240
|
-
# @note This method will delete any method of the form
|
239
|
+
# @note This method will delete any method of the form @sym!@, not just bang readers.
|
241
240
|
# @param sym [#to_sym] instance variable to delete bang method for
|
242
241
|
def remove_bang(sym)
|
243
242
|
sym = "sym!".to_sym
|
@@ -258,7 +257,7 @@ module CushionDefaults
|
|
258
257
|
end
|
259
258
|
end
|
260
259
|
|
261
|
-
# Sets up both {#cushion_reader}s and {#cushion_writer}s for
|
260
|
+
# Sets up both {#cushion_reader}s and {#cushion_writer}s for @syms@. Will set up {#bang_reader}s if
|
262
261
|
# {CushionDefaults::Configuration#bang_things_up Configuration#bang_things_up} is true.
|
263
262
|
# @param syms [*#to_sym] Those instance variables that should have {#cushion_reader}s and {#cushion_writer}s.
|
264
263
|
def cushion(*syms)
|
@@ -267,24 +266,24 @@ module CushionDefaults
|
|
267
266
|
cushion_writer(*syms)
|
268
267
|
end
|
269
268
|
|
270
|
-
# Defines {#cushion_reader}s for all of this class'
|
269
|
+
# Defines {#cushion_reader}s for all of this class' @defaults@.
|
271
270
|
#
|
272
|
-
# Only defines
|
271
|
+
# Only defines @cushion_readers@ for defaults specified for this class. All other readers are assumed to have been defined
|
273
272
|
# further up the class tree.
|
274
273
|
#
|
275
|
-
# Thus, if class
|
276
|
-
# within class
|
274
|
+
# Thus, if class @A@ defines the default @var1@, and class @B@ defines the default @var2@, calling this method
|
275
|
+
# within class @B@ will only generate a reader for @var2@.
|
277
276
|
def cushion_readers_for_defaults
|
278
277
|
cushion_reader *defaults.keys
|
279
278
|
end
|
280
279
|
|
281
|
-
# Defines {#cushion_reader}s and {#cushion_writer}s for all of this class'
|
280
|
+
# Defines {#cushion_reader}s and {#cushion_writer}s for all of this class' @defaults@.
|
282
281
|
#
|
283
|
-
# Only defines
|
282
|
+
# Only defines @cushion_readers@ and @cushion_writers@ for this class defaults. All other getters are assumed to
|
284
283
|
# have been defined further up the class tree.
|
285
284
|
#
|
286
|
-
# Thus, if class
|
287
|
-
# within class
|
285
|
+
# Thus, if class @A@ defines the default @var1@, and class @B@ defines the default @var2@, calling this method
|
286
|
+
# within class @B@ will only generate a getter for @var2@.
|
288
287
|
#
|
289
288
|
# See also:
|
290
289
|
# - #cushion
|
@@ -324,12 +323,12 @@ module CushionDefaults
|
|
324
323
|
freeze_default *defaults.keys
|
325
324
|
end
|
326
325
|
|
327
|
-
# In addition to preventing the
|
328
|
-
# the value to which
|
326
|
+
# In addition to preventing the @default[:sym]@ from being set to a new value (see {#freeze_default}), also freezes
|
327
|
+
# the value to which @default[:sym]@ is currently set.
|
329
328
|
#
|
330
329
|
# Does not throw an error when you attempt to freeze an already-frozen default, but it does log at warning level.
|
331
330
|
#
|
332
|
-
# Equivalent to calling:
|
331
|
+
# Equivalent to calling: @freeze_default :sym; defaults[:sym].freeze@
|
333
332
|
#
|
334
333
|
# @api freeze
|
335
334
|
def deep_freeze_default(*syms)
|
@@ -349,9 +348,9 @@ module CushionDefaults
|
|
349
348
|
|
350
349
|
# Thaws a frozen default, allowing it to be set to a new value.
|
351
350
|
#
|
352
|
-
# Note that if the value of the
|
353
|
-
# thaw_default allows you to set
|
354
|
-
# value to which
|
351
|
+
# Note that if the value of the @default[:sym]@ is itself frozen (using {#deep_freeze_default} or @Object#freeze@),
|
352
|
+
# thaw_default allows you to set @default[:sym]@ to a *new* value but does not and cannot allow you to modify the
|
353
|
+
# value to which @default[:sym]@ points until and unless @default[:sym]@ is set to a new value.
|
355
354
|
#
|
356
355
|
# Does not throw an error when you attempt to thaw a non-frozen default, but it does log at warning level.
|
357
356
|
#
|
@@ -390,10 +389,10 @@ module CushionDefaults
|
|
390
389
|
|
391
390
|
# @!endgroup
|
392
391
|
|
393
|
-
# Ensure that if class
|
392
|
+
# Ensure that if class @Klass@ includes @CushionDefaults@, then any class that subclasses @Klass@ will include it as
|
394
393
|
# well.
|
395
394
|
#
|
396
|
-
# Called automatically whenever any class that includes
|
395
|
+
# Called automatically whenever any class that includes @CushionDefaults@ is inherited.
|
397
396
|
# @api private
|
398
397
|
def inherited(inheritor)
|
399
398
|
inheritor.send :include, CushionDefaults
|
@@ -401,13 +400,13 @@ module CushionDefaults
|
|
401
400
|
|
402
401
|
protected
|
403
402
|
|
404
|
-
# Check whether this class or any parent class includes the instance method denoted by
|
403
|
+
# Check whether this class or any parent class includes the instance method denoted by @sym@
|
405
404
|
# @param sym [#to_sym] method in question
|
406
405
|
def self_or_parent_instance_method?(sym)
|
407
406
|
instance_methods(true).include?(sym.to_sym)
|
408
407
|
end
|
409
408
|
|
410
|
-
# Check whether this class includes the instance method denoted by
|
409
|
+
# Check whether this class includes the instance method denoted by @sym@
|
411
410
|
# @param sym [#to_sym] method in question
|
412
411
|
def self_has_method?(sym)
|
413
412
|
instance_methods(false).include?(sym.to_sym)
|
@@ -1,9 +1,9 @@
|
|
1
1
|
require 'logger'
|
2
2
|
|
3
3
|
module CushionDefaults
|
4
|
-
# Effectively a singleton class,
|
4
|
+
# Effectively a singleton class, @Configuration@ keeps track of various configuration options for @CushionDefaults@.
|
5
5
|
#
|
6
|
-
# In addition, it also keeps track of certain state data for
|
6
|
+
# In addition, it also keeps track of certain state data for @CushionDefaults@.
|
7
7
|
#
|
8
8
|
# For configuration options, see the attribute writers.
|
9
9
|
#
|
@@ -96,7 +96,7 @@ module CushionDefaults
|
|
96
96
|
# Returns or computes the folder where class-specific yaml files are expected to reside.
|
97
97
|
# @return [String] path to yaml config files.
|
98
98
|
def yaml_source_full_path
|
99
|
-
@yaml_source_full_path || CushionDefaults::CALLING_PATH
|
99
|
+
@yaml_source_full_path || "#{CushionDefaults::CALLING_PATH}#{yaml_source_folder}"
|
100
100
|
end
|
101
101
|
|
102
102
|
# @!endgroup
|
@@ -107,7 +107,7 @@ module CushionDefaults
|
|
107
107
|
@we_have_a_pushy = false
|
108
108
|
end
|
109
109
|
|
110
|
-
# Update configuration options with those values contained within
|
110
|
+
# Update configuration options with those values contained within @loaded_config@.
|
111
111
|
#
|
112
112
|
# @param loaded_config [Hash] hash of config options and settings
|
113
113
|
def from_hash(loaded_config)
|
@@ -166,7 +166,7 @@ module CushionDefaults
|
|
166
166
|
# @param klass [Class] class in question.
|
167
167
|
# @return [String] expected path to the YAML file
|
168
168
|
def yaml_file_for(klass)
|
169
|
-
"#{CushionDefaults::configuration.yaml_source_full_path}#{underscore(klass.to_s)
|
169
|
+
"#{CushionDefaults::configuration.yaml_source_full_path}#{underscore(klass.to_s)}.yaml}"
|
170
170
|
end
|
171
171
|
|
172
172
|
|
@@ -207,7 +207,7 @@ module CushionDefaults
|
|
207
207
|
|
208
208
|
protected
|
209
209
|
|
210
|
-
# Specifies the formatter for logger. Will not be called if a logger is assigned with
|
210
|
+
# Specifies the formatter for logger. Will not be called if a logger is assigned with @should_assign_formatter@ set to
|
211
211
|
# false.
|
212
212
|
def assign_formatter_to_logger
|
213
213
|
logger.formatter = proc do |severity, _time, progname, msg|
|
@@ -1,16 +1,16 @@
|
|
1
1
|
module CushionDefaults
|
2
|
-
# Slight expansion of
|
2
|
+
# Slight expansion of @Hash@.
|
3
3
|
#
|
4
|
-
# Records a link to
|
5
|
-
# value for
|
4
|
+
# Records a link to @owner@ and will traverse up the chain of owners looking for a default value for @x@ if no default
|
5
|
+
# value for @x@ is specified.
|
6
6
|
#
|
7
7
|
# In general, a program should treat this class like a normal Hash, with two salient differences:
|
8
8
|
# - The {DefaultsHash#+} method has been overridden.
|
9
9
|
# - The {DefaultsHash#has_ish_key?}, which returns true if this or a parent has the key specified.
|
10
10
|
class DefaultsHash < Hash
|
11
|
-
#
|
11
|
+
# @default_proc@ does most of the work.
|
12
12
|
|
13
|
-
# Must be initialized with an
|
13
|
+
# Must be initialized with an @owner@ class.
|
14
14
|
|
15
15
|
# Set of defaults marked as pushy.
|
16
16
|
attr_reader :pushy_defaults
|
@@ -22,7 +22,7 @@ module CushionDefaults
|
|
22
22
|
# @param owner [Class] class for which this DefaultsHash holds the defaults.
|
23
23
|
def initialize(owner)
|
24
24
|
self.default_proc = proc { |_hash, key| super_defaults[key] }
|
25
|
-
# look in the superclass'
|
25
|
+
# look in the superclass' @defaults@ hash, if a key is not found in this class' @defaults@ hash
|
26
26
|
@owner = owner
|
27
27
|
@pushy_defaults = Set.new
|
28
28
|
@polite_defaults = Set.new
|
@@ -35,7 +35,7 @@ module CushionDefaults
|
|
35
35
|
#
|
36
36
|
# Note that this also enables +=.
|
37
37
|
#
|
38
|
-
# If
|
38
|
+
# If @key@ is in @self@ and @y@, then the value of @y@ will replace that in @self@ in the resulting @Hash@.
|
39
39
|
#
|
40
40
|
# @note This method was incorrectly programmed to modify self in place. In a future release, this will be changed,
|
41
41
|
# and the current behavior should not be depended upon.
|
@@ -97,16 +97,16 @@ module CushionDefaults
|
|
97
97
|
CushionDefaults.log("All defaults cleared for #{@owner}.", :info)
|
98
98
|
end
|
99
99
|
|
100
|
-
# Determine if this
|
101
|
-
#
|
100
|
+
# Determine if this @DefaultsHash@ "ish" has a key. In other words, whether it or any Hashes up the chain of
|
101
|
+
# @super_defaults@ has the key @key@.
|
102
102
|
#
|
103
103
|
# @see #ish_keys
|
104
104
|
def has_ish_key?(key)
|
105
|
-
# Obviously, this method gives much better performance than calling
|
105
|
+
# Obviously, this method gives much better performance than calling @ish_keys.include?(key)@.
|
106
106
|
if has_key?(key)
|
107
107
|
true
|
108
|
-
|
109
|
-
|
108
|
+
# super_defaults could theoretically be either a DefaultsHash or a regular Hash
|
109
|
+
elsif super_defaults
|
110
110
|
if super_defaults.respond_to? :has_ish_key?
|
111
111
|
super_defaults.has_ish_key?(key)
|
112
112
|
else
|
@@ -117,7 +117,7 @@ module CushionDefaults
|
|
117
117
|
end
|
118
118
|
end
|
119
119
|
|
120
|
-
# Returns the keys of this class'
|
120
|
+
# Returns the keys of this class' @defaults@ as well as those of parent classes (if extant).
|
121
121
|
#
|
122
122
|
# @see #has_ish_key?
|
123
123
|
def ish_keys
|
@@ -238,7 +238,7 @@ module CushionDefaults
|
|
238
238
|
|
239
239
|
protected
|
240
240
|
|
241
|
-
# Return (unless cached) a reference to the superclass'
|
241
|
+
# Return (unless cached) a reference to the superclass' @defaults@ hash.
|
242
242
|
def super_defaults
|
243
243
|
@super_defaults ||= @owner.superclass.respond_to?(:defaults) ? @owner.superclass.defaults : {}
|
244
244
|
end
|
data/lib/cushion_defaults.rb
CHANGED
@@ -5,19 +5,22 @@ require 'cushion_defaults/class_methods'
|
|
5
5
|
require 'cushion_defaults/defaults_hash'
|
6
6
|
require 'cushion_defaults/errors'
|
7
7
|
|
8
|
-
#
|
9
|
-
# introduction, you are strongly encouraged to consult the {file:README.md readme}.
|
8
|
+
# h2. The Basics
|
10
9
|
#
|
11
|
-
#
|
10
|
+
# Base module. Should be included in any class that needs the functionality offered by CushionDefaults.
|
11
|
+
#
|
12
|
+
# For a detailed introduction, you are strongly encouraged to consult the "README":file.readme.html.
|
13
|
+
#
|
14
|
+
# There are also several short example programs in the @examples/@ folder. (If anyone has any more examples to include,
|
12
15
|
# please pass them along!)
|
13
16
|
#
|
14
17
|
# And if you would like to run a very simple benchmark of how CushionDefaults compares to similar methods, run
|
15
|
-
#
|
18
|
+
# @benchmarks/simple_benchmark.rb@.
|
16
19
|
#
|
17
|
-
#
|
20
|
+
# h2. Automatic Inclusion in Child Classes
|
18
21
|
#
|
19
|
-
#
|
20
|
-
# subclass
|
22
|
+
# When included in a superclass @Klass@, CushionDefaults automatically includes itself in all subclassses that subsequently
|
23
|
+
# subclass @Klass@.
|
21
24
|
# @example Inclusion in Child Class
|
22
25
|
# class Klass
|
23
26
|
# include CushionDefaults
|
@@ -28,26 +31,29 @@ require 'cushion_defaults/errors'
|
|
28
31
|
module CushionDefaults
|
29
32
|
|
30
33
|
# Version constant
|
31
|
-
VERSION = '0.5.
|
34
|
+
VERSION = '0.5.2'
|
32
35
|
|
33
|
-
# The path of the first file that
|
36
|
+
# The path of the first file that includes CushionDefaults.
|
34
37
|
CALLING_PATH = File.expand_path(File.dirname($0)) + '/'
|
35
38
|
|
36
39
|
# Location CushionDefaults looks here for an (optional) config file, as well as off of the {CALLING_PATH}.
|
37
|
-
CONFIG_LOCATION = CALLING_PATH
|
40
|
+
CONFIG_LOCATION = "#{CALLING_PATH}config/cushion_defaults.yaml"
|
41
|
+
|
42
|
+
# Establish our configuration object
|
43
|
+
@conf = Configuration.new
|
38
44
|
|
39
|
-
#
|
45
|
+
# Return CushionDefaults' {Configuration} object.
|
40
46
|
# @return [Configuration] the module's configuration object
|
41
47
|
# @see Configuration
|
42
|
-
def self.
|
43
|
-
@
|
48
|
+
def self.conf
|
49
|
+
@conf
|
44
50
|
end
|
45
51
|
|
46
|
-
#
|
52
|
+
# Return CushionDefaults' {Configuration} object.
|
47
53
|
# @return [Configuration] the module's configuration object
|
48
54
|
# @see Configuration
|
49
|
-
def self.
|
50
|
-
|
55
|
+
def self.configuration
|
56
|
+
@conf
|
51
57
|
end
|
52
58
|
|
53
59
|
# Logs a message to the logger at {Configuration#logger} as long as {Configuration#record_in_log} is true.
|
@@ -56,44 +62,42 @@ module CushionDefaults
|
|
56
62
|
# :warn, :error, :fatal, :unknown
|
57
63
|
# @param caller_method_name [String] name of the method whose actions are being logged. If nil, the name is determined
|
58
64
|
# programmatically.
|
59
|
-
def self.log(str, level=:debug, caller_method_name=
|
65
|
+
def self.log(str, level=:debug, caller_method_name=caller[0].to_s)
|
60
66
|
|
61
|
-
# conf.record_in_log tells us whether we should be logging at all
|
62
|
-
return unless conf.record_in_log
|
67
|
+
# @conf.record_in_log tells us whether we should be logging at all
|
68
|
+
return unless @conf.record_in_log
|
63
69
|
|
64
70
|
# If caller_method_name is nil, magically get the name of the calling method
|
65
|
-
caller_method_name
|
66
|
-
conf.logger.progname = caller_method_name unless caller_method_name == ''
|
71
|
+
@conf.logger.progname = caller_method_name unless caller_method_name == ''
|
67
72
|
|
68
73
|
case level
|
69
74
|
when :debug, 0
|
70
|
-
conf.logger.debug {str}
|
75
|
+
@conf.logger.debug {str}
|
71
76
|
when :fatal, 4
|
72
|
-
conf.logger.fatal {str}
|
77
|
+
@conf.logger.fatal {str}
|
73
78
|
when :error, 3
|
74
|
-
conf.logger.error {str}
|
79
|
+
@conf.logger.error {str}
|
75
80
|
when :warn, 2
|
76
|
-
conf.logger.warn {str}
|
81
|
+
@conf.logger.warn {str}
|
77
82
|
when :info, 1
|
78
|
-
conf.logger.info {str}
|
83
|
+
@conf.logger.info {str}
|
79
84
|
else
|
80
|
-
conf.logger.unknown {str}
|
85
|
+
@conf.logger.unknown {str}
|
81
86
|
end
|
82
87
|
end
|
83
88
|
|
84
89
|
# Determine whether a value should be treated as nil or nil-like. If {Configuration#ignore_attempts_to_set_nil} is
|
85
90
|
# false, this method always returns false. If that setting is true, then it examines {Configuration#blank_str_is_nil}.
|
86
|
-
# If that setting is true, it returns true if value is nil or '' (like ActiveSupport's
|
91
|
+
# If that setting is true, it returns true if value is nil or '' (like ActiveSupport's @#blank?@)
|
87
92
|
# @param value [Object] value to examine
|
88
93
|
# @return [boolean] as specified above
|
89
94
|
#
|
90
95
|
# @api private
|
91
96
|
def self.nilish?(value)
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
end
|
97
|
+
# @conf is guaranteed to be defined by the call to self.preliminary_setup below
|
98
|
+
# Using the instance variable here gives us surprising performance gains
|
99
|
+
|
100
|
+
@conf.ignore_attempts_to_set_nil && (value.nil? || (value.is_a?(String) && @conf.blank_str_is_nil && value.empty?))
|
97
101
|
end
|
98
102
|
|
99
103
|
# Yield the module's configuration object for manipulation.
|
@@ -113,7 +117,7 @@ module CushionDefaults
|
|
113
117
|
#
|
114
118
|
# @see Configuration
|
115
119
|
def self.configure
|
116
|
-
yield(
|
120
|
+
yield(@conf)
|
117
121
|
end
|
118
122
|
|
119
123
|
# Add class methods and set up an @defaults {DefaultsHash} when the module is included in a class. Called
|
@@ -131,14 +135,14 @@ module CushionDefaults
|
|
131
135
|
|
132
136
|
base.extend(ClassMethods)
|
133
137
|
|
134
|
-
if
|
138
|
+
if @conf.auto_load_from_yaml
|
135
139
|
base.defaults_from_yaml
|
136
140
|
else
|
137
141
|
base.initialize_defaults_hash
|
138
142
|
end
|
139
143
|
end
|
140
144
|
|
141
|
-
# Get class {DefaultsHash}. If
|
145
|
+
# Get class {DefaultsHash}. If @x@ is a @Klass@, then @x#defaults@ returns @Klass.defaults@.
|
142
146
|
# @return [DefaultsHash] the defaults for self.class
|
143
147
|
def defaults
|
144
148
|
self.class.defaults
|
@@ -153,17 +157,17 @@ module CushionDefaults
|
|
153
157
|
defaults[sym]
|
154
158
|
end
|
155
159
|
|
156
|
-
# Wraps (in somewhat more convenient form)
|
160
|
+
# Wraps (in somewhat more convenient form) @Object#instance_variable_defined?@.
|
157
161
|
# @param sym [#to_s] String or coercable object that denotes the instance variable in question
|
158
162
|
# @return [boolean] true if the instance variable denoted by sym is defined, false otherwise
|
159
163
|
def has_specified?(sym)
|
160
164
|
instance_variable_defined?("@#{sym}")
|
161
165
|
end
|
162
166
|
|
163
|
-
# 'Crystallize' the default: i.e., if this instance does not have
|
167
|
+
# 'Crystallize' the default: i.e., if this instance does not have @sym@ specified, then set the value of @sym@
|
164
168
|
# explicitly to the default value.
|
165
169
|
#
|
166
|
-
# This is most useful if you want to update the default value for
|
170
|
+
# This is most useful if you want to update the default value for @sym@ but do not want to affect one or more already
|
167
171
|
# exsiting instances of the class.
|
168
172
|
#
|
169
173
|
# @param default_key [#to_sym] default to crystallize for this object
|
@@ -185,7 +189,7 @@ module CushionDefaults
|
|
185
189
|
|
186
190
|
# Loads the optional config file, looking at the various locations specified therein.
|
187
191
|
def self.preliminary_setup
|
188
|
-
local_conf_path = CALLING_PATH +
|
192
|
+
local_conf_path = CALLING_PATH + @conf.yaml_source_folder + 'cushion_defaults.yaml'
|
189
193
|
if File.exists?(CONFIG_LOCATION)
|
190
194
|
t = File.open(CONFIG_LOCATION)
|
191
195
|
log("Found and opened config file at #{CONFIG_LOCATION}", :info)
|
@@ -197,7 +201,7 @@ module CushionDefaults
|
|
197
201
|
log("No config file found. Looked at #{CONFIG_LOCATION} and #{local_conf_path}.", :info)
|
198
202
|
end
|
199
203
|
|
200
|
-
conf.from_hash(YAML::load(t)) if t
|
204
|
+
@conf.from_hash(YAML::load(t)) if t
|
201
205
|
end
|
202
206
|
|
203
207
|
self.preliminary_setup
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: cushion_defaults
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.5.
|
4
|
+
version: 0.5.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Ryan Mitchell
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2014-12-
|
11
|
+
date: 2014-12-12 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: rspec
|
@@ -24,8 +24,8 @@ dependencies:
|
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '2.11'
|
27
|
-
description: Cushion your
|
28
|
-
DRY off your code.
|
27
|
+
description: Cushion your attributes. Return a static or dynamic default if your @variable
|
28
|
+
isn’t defined. DRY off your code.
|
29
29
|
email: posgarou@gmail.com
|
30
30
|
executables: []
|
31
31
|
extensions: []
|