garcun 0.0.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.
Files changed (139) hide show
  1. checksums.yaml +7 -0
  2. data/.gitattributes +17 -0
  3. data/.gitignore +197 -0
  4. data/.rspec +2 -0
  5. data/Gemfile +22 -0
  6. data/LICENSE +201 -0
  7. data/README.md +521 -0
  8. data/Rakefile +47 -0
  9. data/garcun.gemspec +83 -0
  10. data/lib/garcon.rb +290 -0
  11. data/lib/garcon/chef/chef_helpers.rb +343 -0
  12. data/lib/garcon/chef/coerce/coercer.rb +134 -0
  13. data/lib/garcon/chef/coerce/coercions/boolean_definitions.rb +34 -0
  14. data/lib/garcon/chef/coerce/coercions/date_definitions.rb +32 -0
  15. data/lib/garcon/chef/coerce/coercions/date_time_definitions.rb +32 -0
  16. data/lib/garcon/chef/coerce/coercions/fixnum_definitions.rb +34 -0
  17. data/lib/garcon/chef/coerce/coercions/float_definitions.rb +32 -0
  18. data/lib/garcon/chef/coerce/coercions/hash_definitions.rb +29 -0
  19. data/lib/garcon/chef/coerce/coercions/integer_definitions.rb +31 -0
  20. data/lib/garcon/chef/coerce/coercions/string_definitions.rb +45 -0
  21. data/lib/garcon/chef/coerce/coercions/time_definitions.rb +32 -0
  22. data/lib/garcon/chef/handler/devreporter.rb +127 -0
  23. data/lib/garcon/chef/log.rb +64 -0
  24. data/lib/garcon/chef/node.rb +100 -0
  25. data/lib/garcon/chef/provider/civilize.rb +209 -0
  26. data/lib/garcon/chef/provider/development.rb +159 -0
  27. data/lib/garcon/chef/provider/download.rb +420 -0
  28. data/lib/garcon/chef/provider/house_keeping.rb +265 -0
  29. data/lib/garcon/chef/provider/node_cache.rb +31 -0
  30. data/lib/garcon/chef/provider/partial.rb +183 -0
  31. data/lib/garcon/chef/provider/recovery.rb +80 -0
  32. data/lib/garcon/chef/provider/zip_file.rb +271 -0
  33. data/lib/garcon/chef/resource/attribute.rb +52 -0
  34. data/lib/garcon/chef/resource/base_dsl.rb +174 -0
  35. data/lib/garcon/chef/resource/blender.rb +140 -0
  36. data/lib/garcon/chef/resource/lazy_eval.rb +66 -0
  37. data/lib/garcon/chef/resource/resource_name.rb +109 -0
  38. data/lib/garcon/chef/secret_bag.rb +204 -0
  39. data/lib/garcon/chef/validations.rb +76 -0
  40. data/lib/garcon/chef_inclusions.rb +151 -0
  41. data/lib/garcon/configuration.rb +138 -0
  42. data/lib/garcon/core_ext.rb +39 -0
  43. data/lib/garcon/core_ext/array.rb +27 -0
  44. data/lib/garcon/core_ext/binding.rb +64 -0
  45. data/lib/garcon/core_ext/boolean.rb +66 -0
  46. data/lib/garcon/core_ext/duration.rb +271 -0
  47. data/lib/garcon/core_ext/enumerable.rb +34 -0
  48. data/lib/garcon/core_ext/file.rb +127 -0
  49. data/lib/garcon/core_ext/filetest.rb +62 -0
  50. data/lib/garcon/core_ext/hash.rb +279 -0
  51. data/lib/garcon/core_ext/kernel.rb +159 -0
  52. data/lib/garcon/core_ext/lazy.rb +222 -0
  53. data/lib/garcon/core_ext/method_access.rb +243 -0
  54. data/lib/garcon/core_ext/module.rb +92 -0
  55. data/lib/garcon/core_ext/nil.rb +53 -0
  56. data/lib/garcon/core_ext/numeric.rb +44 -0
  57. data/lib/garcon/core_ext/object.rb +342 -0
  58. data/lib/garcon/core_ext/pathname.rb +152 -0
  59. data/lib/garcon/core_ext/process.rb +41 -0
  60. data/lib/garcon/core_ext/random.rb +497 -0
  61. data/lib/garcon/core_ext/string.rb +312 -0
  62. data/lib/garcon/core_ext/struct.rb +49 -0
  63. data/lib/garcon/core_ext/symbol.rb +170 -0
  64. data/lib/garcon/core_ext/time.rb +234 -0
  65. data/lib/garcon/exceptions.rb +101 -0
  66. data/lib/garcon/inflections.rb +237 -0
  67. data/lib/garcon/inflections/defaults.rb +79 -0
  68. data/lib/garcon/inflections/inflections.rb +182 -0
  69. data/lib/garcon/inflections/rules_collection.rb +37 -0
  70. data/lib/garcon/secret.rb +271 -0
  71. data/lib/garcon/stash/format.rb +114 -0
  72. data/lib/garcon/stash/journal.rb +226 -0
  73. data/lib/garcon/stash/queue.rb +83 -0
  74. data/lib/garcon/stash/serializer.rb +86 -0
  75. data/lib/garcon/stash/store.rb +435 -0
  76. data/lib/garcon/task.rb +31 -0
  77. data/lib/garcon/task/atomic.rb +151 -0
  78. data/lib/garcon/task/atomic_boolean.rb +127 -0
  79. data/lib/garcon/task/condition.rb +99 -0
  80. data/lib/garcon/task/copy_on_notify_observer_set.rb +154 -0
  81. data/lib/garcon/task/copy_on_write_observer_set.rb +153 -0
  82. data/lib/garcon/task/count_down_latch.rb +92 -0
  83. data/lib/garcon/task/delay.rb +196 -0
  84. data/lib/garcon/task/dereferenceable.rb +144 -0
  85. data/lib/garcon/task/event.rb +119 -0
  86. data/lib/garcon/task/executor.rb +275 -0
  87. data/lib/garcon/task/executor_options.rb +59 -0
  88. data/lib/garcon/task/future.rb +107 -0
  89. data/lib/garcon/task/immediate_executor.rb +84 -0
  90. data/lib/garcon/task/ivar.rb +171 -0
  91. data/lib/garcon/task/lazy_reference.rb +74 -0
  92. data/lib/garcon/task/monotonic_time.rb +69 -0
  93. data/lib/garcon/task/obligation.rb +256 -0
  94. data/lib/garcon/task/observable.rb +101 -0
  95. data/lib/garcon/task/priority_queue.rb +234 -0
  96. data/lib/garcon/task/processor_count.rb +128 -0
  97. data/lib/garcon/task/read_write_lock.rb +304 -0
  98. data/lib/garcon/task/safe_task_executor.rb +58 -0
  99. data/lib/garcon/task/single_thread_executor.rb +97 -0
  100. data/lib/garcon/task/thread_pool/cached.rb +71 -0
  101. data/lib/garcon/task/thread_pool/executor.rb +294 -0
  102. data/lib/garcon/task/thread_pool/fixed.rb +61 -0
  103. data/lib/garcon/task/thread_pool/worker.rb +90 -0
  104. data/lib/garcon/task/timer.rb +44 -0
  105. data/lib/garcon/task/timer_set.rb +194 -0
  106. data/lib/garcon/task/timer_task.rb +377 -0
  107. data/lib/garcon/task/waitable_list.rb +58 -0
  108. data/lib/garcon/utility/ansi.rb +199 -0
  109. data/lib/garcon/utility/at_random.rb +77 -0
  110. data/lib/garcon/utility/crypto.rb +292 -0
  111. data/lib/garcon/utility/equalizer.rb +146 -0
  112. data/lib/garcon/utility/faker/extensions/array.rb +22 -0
  113. data/lib/garcon/utility/faker/extensions/symbol.rb +9 -0
  114. data/lib/garcon/utility/faker/faker.rb +164 -0
  115. data/lib/garcon/utility/faker/faker/company.rb +17 -0
  116. data/lib/garcon/utility/faker/faker/hacker.rb +30 -0
  117. data/lib/garcon/utility/faker/faker/version.rb +3 -0
  118. data/lib/garcon/utility/faker/locales/en-US.yml +83 -0
  119. data/lib/garcon/utility/faker/locales/en.yml +21 -0
  120. data/lib/garcon/utility/file_helper.rb +170 -0
  121. data/lib/garcon/utility/hookers.rb +178 -0
  122. data/lib/garcon/utility/interpolation.rb +90 -0
  123. data/lib/garcon/utility/memstash.rb +364 -0
  124. data/lib/garcon/utility/misc.rb +54 -0
  125. data/lib/garcon/utility/msg_from_god.rb +62 -0
  126. data/lib/garcon/utility/retry.rb +238 -0
  127. data/lib/garcon/utility/timeout.rb +58 -0
  128. data/lib/garcon/utility/uber/builder.rb +91 -0
  129. data/lib/garcon/utility/uber/callable.rb +7 -0
  130. data/lib/garcon/utility/uber/delegates.rb +13 -0
  131. data/lib/garcon/utility/uber/inheritable_attr.rb +37 -0
  132. data/lib/garcon/utility/uber/options.rb +101 -0
  133. data/lib/garcon/utility/uber/uber_version.rb +3 -0
  134. data/lib/garcon/utility/uber/version.rb +33 -0
  135. data/lib/garcon/utility/url_helper.rb +100 -0
  136. data/lib/garcon/utils.rb +29 -0
  137. data/lib/garcon/version.rb +62 -0
  138. data/lib/garcun.rb +24 -0
  139. metadata +680 -0
@@ -0,0 +1,92 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ class Module
21
+
22
+ # Create an instance of Object and extend it with +self+.
23
+ #
24
+ # mod = Module.new do
25
+ # def foo; "foo"; end
26
+ # end
27
+ #
28
+ # obj = mod.to_obj
29
+ #
30
+ # obj.foo #=> "foo"
31
+ #
32
+ def to_obj
33
+ o = Object.new
34
+ o.extend self
35
+ o
36
+ end
37
+
38
+ # Creates a new method wrapping the previous of the same name.
39
+ # Reference to the old method is passed into the new definition
40
+ # block as the first parameter.
41
+ #
42
+ # class WrapExample
43
+ # def foo
44
+ # "foo"
45
+ # end
46
+ #
47
+ # wrap_method(:foo) do |old_meth, *args|
48
+ # old_meth.call + '!'
49
+ # end
50
+ # end
51
+ #
52
+ # example = WrapExample.new
53
+ # example.foo #=> 'foo!'
54
+ #
55
+ # Keep in mind that this cannot be used to wrap methods
56
+ # that take a block.
57
+ #
58
+ def wrap_method( sym, &blk )
59
+ old = instance_method(sym)
60
+ define_method(sym) { |*args| blk.call(old.bind(self), *args) }
61
+ end
62
+ alias_method :wrap, :wrap_method
63
+
64
+ unless method_defined?(:set)
65
+ # Sets an option to the given value. If the value is a proc,
66
+ # the proc will be called every time the option is accessed.
67
+ #
68
+ def set(option, value=self, &block)
69
+ raise ArgumentError if block && value != self
70
+ value = block if block
71
+ if value.kind_of?(Proc)
72
+ if value.arity == 1
73
+ yield self
74
+ else
75
+ (class << self; self; end).module_eval do
76
+ define_method(option, &value)
77
+ define_method("#{option}?"){ !!__send__(option) }
78
+ define_method("#{option}="){ |val| set(option, Proc.new{val}) }
79
+ end
80
+ end
81
+ elsif value == self
82
+ option.each{ |k,v| set(k, v) }
83
+ elsif respond_to?("#{option}=")
84
+ __send__("#{option}=", value)
85
+ else
86
+ set(option, Proc.new{value})
87
+ end
88
+ self
89
+ end
90
+ end
91
+ end
92
+
@@ -0,0 +1,53 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ # Add #blank? method to NilClass class.
21
+ class NilClass
22
+ # Nil is always blank
23
+ #
24
+ # @example
25
+ # nil.blank? # => true
26
+ #
27
+ # @return [TrueClass]
28
+ #
29
+ # @api public
30
+ def blank?
31
+ true
32
+ end
33
+
34
+ # Calling `try` on `nil` always returns `nil`. It becomes especially helpful
35
+ # when navigating through associations that may return `nil`.
36
+ #
37
+ def try(*args)
38
+ nil
39
+ end
40
+
41
+ def try!(*args)
42
+ nil
43
+ end
44
+
45
+ # Since NilClass is immutable it cannot be duplicated.
46
+ # For this reason #try_dup returns +self+.
47
+ #
48
+ # nil.dup! #=> nil
49
+ #
50
+ def dup! ; self ; end
51
+ def dup? ; false ; end
52
+ def clone? ; false ; end
53
+ end
@@ -0,0 +1,44 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+ # Add #blank? method to Numeric class.
21
+ class Numeric
22
+ # Numerics are never blank
23
+ #
24
+ # @example
25
+ # 0.blank? # => false
26
+ # 1.blank? # => false
27
+ # 6.54321.blank? # => false
28
+ #
29
+ # @return [FalseClass]
30
+ #
31
+ # @api public
32
+ def blank?
33
+ false
34
+ end
35
+
36
+ # Since Numeric is immutable it cannot be duplicated.
37
+ # For this reason #try_dup returns +self+.
38
+ #
39
+ # 1.dup! #=> 1
40
+ #
41
+ def dup! ; self ; end
42
+ def dup? ; false ; end
43
+ def clone? ; false ; end
44
+ end
@@ -0,0 +1,342 @@
1
+ # encoding: UTF-8
2
+ #
3
+ # Author: Stefano Harding <riddopic@gmail.com>
4
+ # License: Apache License, Version 2.0
5
+ # Copyright: (C) 2014-2015 Stefano Harding
6
+ #
7
+ # Licensed under the Apache License, Version 2.0 (the "License");
8
+ # you may not use this file except in compliance with the License.
9
+ # You may obtain a copy of the License at
10
+ #
11
+ # http://www.apache.org/licenses/LICENSE-2.0
12
+ #
13
+ # Unless required by applicable law or agreed to in writing, software
14
+ # distributed under the License is distributed on an "AS IS" BASIS,
15
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16
+ # See the License for the specific language governing permissions and
17
+ # limitations under the License.
18
+ #
19
+
20
+
21
+ # Add #blank?, #present?, #try and #try! methods to Object class.
22
+ class Object
23
+
24
+ # Returns true if the object is nil or empty (if applicable)
25
+ #
26
+ # @example
27
+ # [].blank? # => true
28
+ # [1].blank? # => false
29
+ # [nil].blank? # => false
30
+ #
31
+ # @return [Boolean]
32
+ #
33
+ def blank?
34
+ nil? || (respond_to?(:empty?) && empty?)
35
+ end
36
+
37
+ # Returns true if the object is NOT nil or empty
38
+ #
39
+ # @example
40
+ # [].present? # => false
41
+ # [1].present? # => true
42
+ # [nil].present? # => true
43
+ #
44
+ # @return [Boolean]
45
+ #
46
+ def present?
47
+ !blank?
48
+ end
49
+
50
+ # Invokes the public method whose name goes as first argument just like
51
+ # `public_send` does, except that if the receiver does not respond to it the
52
+ # call returns `nil` rather than raising an exception.
53
+ #
54
+ # @note
55
+ # `try` is defined on `Object`. Therefore, it won't work with instances
56
+ # of classes that do not have `Object` among their ancestors, like direct
57
+ # subclasses of `BasicObject`.
58
+ #
59
+ # @param [String] object
60
+ #
61
+ # @param [Symbol] method
62
+ #
63
+ # @return [Object]
64
+ #
65
+ def try(*a, &b)
66
+ try!(*a, &b) if a.empty? || respond_to?(a.first)
67
+ end
68
+
69
+ # Same as #try, but will raise a NoMethodError exception if the receiver is
70
+ # not `nil` and does not implement the tried method.
71
+ #
72
+ # @raise NoMethodError
73
+ # If the receiver is not `nil` and does not implement the tried method.
74
+ #
75
+ # @return [Object]
76
+ #
77
+ def try!(*a, &b)
78
+ if a.empty? && block_given?
79
+ if b.arity.zero?
80
+ instance_eval(&b)
81
+ else
82
+ yield self
83
+ end
84
+ else
85
+ public_send(*a, &b)
86
+ end
87
+ end
88
+
89
+ # If receiver is callable, calls it and returns result. If not, just returns
90
+ # receiver itself.
91
+ #
92
+ # @return [Object]
93
+ #
94
+ def try_call(*args)
95
+ if self.respond_to?(:call)
96
+ self.call(*args)
97
+ else
98
+ self
99
+ end
100
+ end
101
+
102
+ # An identity method that provides access to an object's 'self'.
103
+ #
104
+ # Example
105
+ # [1,2,3,4,5,1,2,2,3].group_by(&:itself)
106
+ # #=> {1=>[1, 1], 2=>[2, 2, 2], 3=>[3, 3], 4=>[4], 5=>[5]}
107
+ #
108
+ def itself
109
+ self
110
+ end
111
+
112
+ # Override this in a child class if it cannot be dup'ed.
113
+ #
114
+ # obj1 = Object.new
115
+ # obj2 = obj1.dup!
116
+ # obj2.equal?(obj1) #=> false
117
+ #
118
+ # @return [Object]
119
+ #
120
+ def dup!
121
+ dup
122
+ end
123
+
124
+ # Alternative name for #dup!
125
+ #
126
+ # @return [Object]
127
+ #
128
+ def try_dup
129
+ dup!
130
+ end
131
+
132
+ # Can you safely call #dup on this object?
133
+ #
134
+ # Returns `false` for `nil`, `false`, `true`, symbols, and numbers;
135
+ # `true` otherwise.
136
+ #
137
+ # @return [Object]
138
+ #
139
+ def dup? ; true ; end
140
+ def clone? ; true ; end
141
+
142
+ # Extracts the singleton class, so that metaprogramming can be done on it.
143
+ #
144
+ # @example [Setup]
145
+ # class MyString < String; end
146
+ #
147
+ # MyString.instance_eval do
148
+ # define_method :foo do
149
+ # puts self
150
+ # end
151
+ # end
152
+ #
153
+ # MyString.meta_class.instance_eval do
154
+ # define_method :bar do
155
+ # puts self
156
+ # end
157
+ # end
158
+ #
159
+ # def String.add_meta_var(var)
160
+ # self.meta_class.instance_eval do
161
+ # define_method var do
162
+ # puts "HELLO"
163
+ # end
164
+ # end
165
+ # end
166
+ #
167
+ # @example
168
+ # MyString.new("Hello").foo # => "Hello"
169
+ #
170
+ # @example
171
+ # MyString.new("Hello").bar
172
+ # # => NoMethodError: undefined method `bar' for "Hello":MyString
173
+ #
174
+ # @example
175
+ # MyString.foo
176
+ # # => NoMethodError: undefined method `foo' for MyString:Class
177
+ #
178
+ # @example
179
+ # MyString.bar
180
+ # # => MyString
181
+ #
182
+ # @example
183
+ # String.bar
184
+ # # => NoMethodError: undefined method `bar' for String:Class
185
+ #
186
+ # @example
187
+ # MyString.add_meta_var(:x)
188
+ # MyString.x # => HELLO
189
+ #
190
+ # @details [Description of Examples]
191
+ # As you can see, using #meta_class allows you to execute code (and here,
192
+ # define a method) on the metaclass itself. It also allows you to define
193
+ # class methods that can be run on subclasses, and then be able to execute
194
+ # code on the metaclass of the subclass (here MyString).
195
+ #
196
+ # In this case, we were able to define a class method (add_meta_var) on
197
+ # String that was executable by the MyString subclass. It was then able to
198
+ # define a method on the subclass by adding it to the MyString metaclass.
199
+ #
200
+ # @return [Class]
201
+ # The meta class.
202
+ #
203
+ def meta_class() class << self; self end end
204
+
205
+ # @param [String] name
206
+ # The name of the constant to get, e.g. "Garcon::Check".
207
+ #
208
+ # @return [Object]
209
+ # The constant corresponding to the name.
210
+ #
211
+ def full_const_get(name)
212
+ list = name.split('::')
213
+ list.shift if list.first.blank?
214
+ obj = self
215
+ list.each do |x|
216
+ obj = obj.const_defined?(x) ? obj.const_get(x) : obj.const_missing(x)
217
+ end
218
+ obj
219
+ end
220
+
221
+ # @param [String] name
222
+ # The name of the constant to get, e.g. "Garcon::Check".
223
+ #
224
+ # @param [Object] value
225
+ # The value to assign to the constant.
226
+ #
227
+ # @return [Object]
228
+ # The constant corresponding to the name.
229
+ #
230
+ def full_const_set(name, value)
231
+ list = name.split('::')
232
+ toplevel = list.first.blank?
233
+ list.shift if toplevel
234
+ last = list.pop
235
+ obj = list.empty? ? Object : Object.full_const_get(list.join('::'))
236
+ obj.const_set(last, value) if obj && !obj.const_defined?(last)
237
+ end
238
+
239
+ # Defines module from a string name (e.g. Foo::Bar::Baz). If module already
240
+ # exists, no exception raised.
241
+ #
242
+ # @param [String] name
243
+ # The name of the full module name to make
244
+ #
245
+ # @return [nil]
246
+ #
247
+ def make_module(string)
248
+ current_module = self
249
+ string.split('::').each do |part|
250
+ current_module = if current_module.const_defined?(part)
251
+ current_module.const_get(part)
252
+ else
253
+ current_module.const_set(part, Module.new)
254
+ end
255
+ end
256
+ current_module
257
+ end
258
+
259
+ # @param [Symbol, Class, Array] duck
260
+ # The thing to compare the object to.
261
+ #
262
+ # @note
263
+ # The behavior of the method depends on the type of duck as follows:
264
+ # Symbol:: Check whether the object respond_to?(duck).
265
+ # Class:: Check whether the object is_a?(duck).
266
+ # Array:: Check whether the object quacks_like? at least one of the
267
+ # options in the array.
268
+ #
269
+ # @return [Boolean]
270
+ # True if the object quacks like a duck.
271
+ #
272
+ def quacks_like?(duck)
273
+ case duck
274
+ when Symbol
275
+ self.respond_to?(duck)
276
+ when Class
277
+ self.is_a?(duck)
278
+ when Array
279
+ duck.any? { |d| self.quacks_like?(d) }
280
+ else
281
+ false
282
+ end
283
+ end
284
+
285
+ # @example 1.in?([1,2,3]) # => true
286
+ #
287
+ # @example 1.in?(1,2,3) # => true
288
+ #
289
+ # @param [#include?] arrayish
290
+ # Container to check, to see if it includes the object.
291
+ #
292
+ # @param [Array] *more
293
+ # additional args, will be flattened into arrayish
294
+ #
295
+ # @return [Boolean]
296
+ # True if the object is included in arrayish (+ more)
297
+ #
298
+ def in?(arrayish, *more)
299
+ arrayish = more.unshift(arrayish) unless more.empty?
300
+ arrayish.include?(self)
301
+ end
302
+
303
+ # Get or set state of object. You can think of #object_state as an in-code
304
+ # form of marshalling.
305
+ #
306
+ # class StateExample
307
+ # attr_reader :a, :b
308
+ # def initialize(a,b)
309
+ # @a, @b = a, b
310
+ # end
311
+ # end
312
+ #
313
+ # obj = StateExample.new(1,2)
314
+ # obj.a #=> 1
315
+ # obj.b #=> 2
316
+ #
317
+ # obj.object_state #=> {:a=>1, :b=>2}
318
+ #
319
+ # obj.object_state(:a=>3, :b=>4)
320
+ # obj.a #=> 3
321
+ # obj.b #=> 4
322
+ #
323
+ # For most object's this is essentially the same as `instance.to_h`.
324
+ # But for data structures like Array and Hash it returns a snapshot of their
325
+ # contents, not the state of their instance variables.
326
+ #
327
+ def object_state(data = nil)
328
+ if data
329
+ instance_variables.each do |iv|
330
+ name = iv.to_s.sub(/^[@]/, '').to_sym
331
+ instance_variable_set(iv, data[name])
332
+ end
333
+ else
334
+ data = {}
335
+ instance_variables.each do |iv|
336
+ name = iv.to_s.sub(/^[@]/, '').to_sym
337
+ data[name] = instance_variable_get(iv)
338
+ end
339
+ data
340
+ end
341
+ end
342
+ end