cushion_defaults 0.5.1 → 0.5.2
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.
- 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: []
|