hoodie 0.5.5 → 1.0.1
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/.gitignore +1 -0
- data/Gemfile +19 -0
- data/Rakefile +8 -23
- data/hoodie.gemspec +0 -23
- data/lib/hoodie.rb +40 -48
- data/lib/hoodie/configuration.rb +39 -2
- data/lib/hoodie/core_ext/blank.rb +6 -6
- data/lib/hoodie/core_ext/hash.rb +108 -13
- data/lib/hoodie/core_ext/string.rb +5 -3
- data/lib/hoodie/core_ext/try.rb +4 -3
- data/lib/hoodie/inflections.rb +18 -0
- data/lib/hoodie/inflections/defaults.rb +17 -0
- data/lib/hoodie/inflections/inflections.rb +17 -0
- data/lib/hoodie/inflections/rules_collection.rb +17 -0
- data/lib/hoodie/logging.rb +22 -4
- data/lib/hoodie/stash.rb +83 -80
- data/lib/hoodie/stash/disk_store.rb +142 -118
- data/lib/hoodie/stash/mem_store.rb +10 -9
- data/lib/hoodie/stash/memoizable.rb +46 -0
- data/lib/hoodie/utils.rb +13 -183
- data/lib/hoodie/utils/ansi.rb +199 -0
- data/lib/hoodie/utils/crypto.rb +288 -0
- data/lib/hoodie/utils/equalizer.rb +146 -0
- data/lib/hoodie/utils/file_helper.rb +225 -0
- data/lib/hoodie/utils/konstruktor.rb +77 -0
- data/lib/hoodie/utils/machine.rb +83 -0
- data/lib/hoodie/utils/os.rb +56 -0
- data/lib/hoodie/utils/retry.rb +235 -0
- data/lib/hoodie/utils/timeout.rb +54 -0
- data/lib/hoodie/utils/url_helper.rb +104 -0
- data/lib/hoodie/version.rb +4 -4
- metadata +13 -234
- data/lib/hoodie/identity_map.rb +0 -96
- data/lib/hoodie/memoizable.rb +0 -43
- data/lib/hoodie/obfuscate.rb +0 -121
- data/lib/hoodie/observable.rb +0 -309
- data/lib/hoodie/os.rb +0 -43
- data/lib/hoodie/proxy.rb +0 -68
- data/lib/hoodie/rash.rb +0 -125
- data/lib/hoodie/timers.rb +0 -355
data/lib/hoodie/identity_map.rb
DELETED
@@ -1,96 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
#
|
3
|
-
# Author: Stefano Harding <riddopic@gmail.com>
|
4
|
-
#
|
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
|
16
|
-
# implied. See the License for the specific language governing
|
17
|
-
# permissions and limitations under the License.
|
18
|
-
#
|
19
|
-
|
20
|
-
module Hoodie
|
21
|
-
module IdentityMap
|
22
|
-
def self.enabled=(flag)
|
23
|
-
Thread.current[:identity_map_enabled] = flag
|
24
|
-
end
|
25
|
-
|
26
|
-
def self.enabled
|
27
|
-
Thread.current[:identity_map_enabled]
|
28
|
-
end
|
29
|
-
|
30
|
-
def self.enabled?
|
31
|
-
enabled == true
|
32
|
-
end
|
33
|
-
|
34
|
-
def self.repository
|
35
|
-
Thread.current[:identity_map] ||= {}
|
36
|
-
end
|
37
|
-
|
38
|
-
def self.clear
|
39
|
-
repository.clear
|
40
|
-
end
|
41
|
-
|
42
|
-
def self.include?(object)
|
43
|
-
repository.keys.include?(object.id)
|
44
|
-
end
|
45
|
-
|
46
|
-
def self.use
|
47
|
-
old, self.enabled = enabled, true
|
48
|
-
yield if block_given?
|
49
|
-
ensure
|
50
|
-
self.enabled = old
|
51
|
-
clear
|
52
|
-
end
|
53
|
-
|
54
|
-
def self.without
|
55
|
-
old, self.enabled = enabled, false
|
56
|
-
yield if block_given?
|
57
|
-
ensure
|
58
|
-
self.enabled = old
|
59
|
-
end
|
60
|
-
|
61
|
-
module ClassMethods
|
62
|
-
def get(id, options = nil)
|
63
|
-
get_from_identity_map(id) || super
|
64
|
-
end
|
65
|
-
|
66
|
-
def get_from_identity_map(id)
|
67
|
-
IdentityMap.repository[id] if IdentityMap.enabled?
|
68
|
-
end
|
69
|
-
private :get_from_identity_map
|
70
|
-
|
71
|
-
def load(id, attrs)
|
72
|
-
if IdentityMap.enabled? && instance = IdentityMap.repository[id]
|
73
|
-
instance
|
74
|
-
else
|
75
|
-
super.tap { |doc| doc.add_to_identity_map }
|
76
|
-
end
|
77
|
-
end
|
78
|
-
end
|
79
|
-
|
80
|
-
def save(options={})
|
81
|
-
super.tap { |result| add_to_identity_map if result }
|
82
|
-
end
|
83
|
-
|
84
|
-
def delete
|
85
|
-
super.tap { remove_from_identity_map }
|
86
|
-
end
|
87
|
-
|
88
|
-
def add_to_identity_map
|
89
|
-
IdentityMap.repository[id] = self if IdentityMap.enabled?
|
90
|
-
end
|
91
|
-
|
92
|
-
def remove_from_identity_map
|
93
|
-
IdentityMap.repository.delete(id) if IdentityMap.enabled?
|
94
|
-
end
|
95
|
-
end
|
96
|
-
end
|
data/lib/hoodie/memoizable.rb
DELETED
@@ -1,43 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
#
|
3
|
-
# Author: Stefano Harding <riddopic@gmail.com>
|
4
|
-
#
|
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
|
-
require 'hoodie/stash' unless defined?(Stash)
|
21
|
-
|
22
|
-
# Memoization is an optimization that saves the return value of a
|
23
|
-
# method so it doesn't need to be re-computed every time that method
|
24
|
-
# is called.
|
25
|
-
module Memoizable
|
26
|
-
# Create a new memoized method. To use, extend class with Memoizable,
|
27
|
-
# then, in initialize, call memoize
|
28
|
-
#
|
29
|
-
# @return [undefined]
|
30
|
-
#
|
31
|
-
def memoize(methods, cache = nil)
|
32
|
-
cache ||= Stash.new
|
33
|
-
methods.each do |name|
|
34
|
-
uncached_name = "#{name}_uncached".to_sym
|
35
|
-
singleton_class.class_eval do
|
36
|
-
alias_method uncached_name, name
|
37
|
-
define_method(name) do |*a, &b|
|
38
|
-
cache.cache(name) { send uncached_name, *a, &b }
|
39
|
-
end
|
40
|
-
end
|
41
|
-
end
|
42
|
-
end
|
43
|
-
end
|
data/lib/hoodie/obfuscate.rb
DELETED
@@ -1,121 +0,0 @@
|
|
1
|
-
# encoding: UTF-8
|
2
|
-
#
|
3
|
-
# Author: Stefano Harding <riddopic@gmail.com>
|
4
|
-
#
|
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
|
-
module Hoodie
|
21
|
-
begin
|
22
|
-
require 'openssl'
|
23
|
-
INCOMPREHENSIBLE_ERROR = nil
|
24
|
-
rescue LoadError => err
|
25
|
-
raise unless err.to_s.include?('openssl')
|
26
|
-
warn 'Oea pieoYreb h wYoerh dl hwsnhoib r Lrbea tbte wbnaetvoouahe h rbe.'
|
27
|
-
warn "olorbvtelYShnSben irrSwoet eto eihSrLoS'do n See wLiape."
|
28
|
-
INCOMPREHENSIBLE_ERROR = err
|
29
|
-
end
|
30
|
-
|
31
|
-
require 'digest/sha2'
|
32
|
-
require 'base64'
|
33
|
-
|
34
|
-
# Befuddle and enlighten values in StashCache::Store
|
35
|
-
#
|
36
|
-
module Obfuscate
|
37
|
-
ESOTERIC_TYPE = 'aes-256-cbc' unless defined?(ESOTERIC_TYPE)
|
38
|
-
|
39
|
-
def self.check_platform_can_discombobulate!
|
40
|
-
return true unless INCOMPREHENSIBLE_ERROR
|
41
|
-
fail INCOMPREHENSIBLE_ERROR.class, "b0rked! #{INCOMPREHENSIBLE_ERROR}"
|
42
|
-
end
|
43
|
-
|
44
|
-
# Befuddle the given string
|
45
|
-
#
|
46
|
-
# @param plaintext the text to befuddle
|
47
|
-
# @param [String] befuddle_pass secret passphrase to befuddle with
|
48
|
-
#
|
49
|
-
# @return [String] befuddleed text, suitable for deciphering with
|
50
|
-
# Obfuscate#enlighten (decrypt)
|
51
|
-
#
|
52
|
-
def self.befuddle(plaintext, befuddle_pass, options = {})
|
53
|
-
cipher = new_cipher :befuddle, befuddle_pass, options
|
54
|
-
cipher.iv = iv = cipher.random_iv
|
55
|
-
ciphertext = cipher.update(plaintext)
|
56
|
-
ciphertext << cipher.final
|
57
|
-
Base64.encode64(combine_iv_and_ciphertext(iv, ciphertext))
|
58
|
-
end
|
59
|
-
|
60
|
-
# Enlighten the given string, using the key and id supplied
|
61
|
-
#
|
62
|
-
# @param ciphertext the text to enlighten, probably produced with
|
63
|
-
# Obfuscate#befuddle (encrypt)
|
64
|
-
# @param [String] befuddle_pass secret sauce to enlighten with
|
65
|
-
#
|
66
|
-
# @return [String] the enlightened plaintext
|
67
|
-
#
|
68
|
-
def self.enlighten(enc_ciphertext, befuddle_pass, options = {})
|
69
|
-
iv_and_ciphertext = Base64.decode64(enc_ciphertext)
|
70
|
-
cipher = new_cipher :enlighten, befuddle_pass, options
|
71
|
-
cipher.iv, ciphertext = separate_iv_and_ciphertext(cipher, iv_and_ciphertext)
|
72
|
-
plaintext = cipher.update(ciphertext)
|
73
|
-
plaintext << cipher.final
|
74
|
-
plaintext
|
75
|
-
end
|
76
|
-
|
77
|
-
protected # A T T E N Z I O N E A R E A P R O T E T T A
|
78
|
-
|
79
|
-
# Cipher create machine do, befuddle engage, enlighten. Dials set
|
80
|
-
# direction to infinity
|
81
|
-
#
|
82
|
-
# @param [:befuddle, :enlighten] to befuddle or enlighten
|
83
|
-
# @param [String] befuddle_pass secret sauce to enlighten with
|
84
|
-
#
|
85
|
-
def self.new_cipher(direction, befuddle_pass, options = {})
|
86
|
-
check_platform_can_discombobulate!
|
87
|
-
cipher = OpenSSL::Cipher::Cipher.new(ESOTERIC_TYPE)
|
88
|
-
case direction
|
89
|
-
when :befuddle
|
90
|
-
cipher.encrypt
|
91
|
-
when :enlighten
|
92
|
-
cipher.decrypt
|
93
|
-
else fail "Bad cipher direction #{direction}"
|
94
|
-
end
|
95
|
-
cipher.key = befuddle_key(befuddle_pass, options)
|
96
|
-
cipher
|
97
|
-
end
|
98
|
-
|
99
|
-
# vector inspect encoder serialize prepend initialization message
|
100
|
-
def self.combine_iv_and_ciphertext(iv, message)
|
101
|
-
message.force_encoding('BINARY') if message.respond_to?(:force_encoding)
|
102
|
-
iv.force_encoding('BINARY') if iv.respond_to?(:force_encoding)
|
103
|
-
iv + message
|
104
|
-
end
|
105
|
-
|
106
|
-
# front vector initialization, encoded pull message
|
107
|
-
def self.separate_iv_and_ciphertext(cipher, iv_and_ciphertext)
|
108
|
-
idx = cipher.iv_len
|
109
|
-
[iv_and_ciphertext[0..(idx - 1)], iv_and_ciphertext[idx..-1]]
|
110
|
-
end
|
111
|
-
|
112
|
-
# Convert the befuddle_pass passphrase into the key used for
|
113
|
-
# befuddletion
|
114
|
-
def self.befuddle_key(befuddle_pass, _options = {})
|
115
|
-
befuddle_pass = befuddle_pass.to_s
|
116
|
-
fail 'Missing befuddled password!' if befuddle_pass.empty?
|
117
|
-
# 256 beers on the wall, keys for cipher required of aes cbc
|
118
|
-
Digest::SHA256.digest(befuddle_pass)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
end
|
data/lib/hoodie/observable.rb
DELETED
@@ -1,309 +0,0 @@
|
|
1
|
-
|
2
|
-
module Garcon
|
3
|
-
module Observable
|
4
|
-
|
5
|
-
# @return [Object] the added observer
|
6
|
-
#
|
7
|
-
def add_observer(*args, &block)
|
8
|
-
observers.add_observer(*args, &block)
|
9
|
-
end
|
10
|
-
|
11
|
-
# as #add_observer but it can be used for chaining
|
12
|
-
#
|
13
|
-
# @return [Observable] self
|
14
|
-
#
|
15
|
-
def with_observer(*args, &block)
|
16
|
-
add_observer(*args, &block)
|
17
|
-
self
|
18
|
-
end
|
19
|
-
|
20
|
-
# @return [Object] the deleted observer
|
21
|
-
#
|
22
|
-
def delete_observer(*args)
|
23
|
-
observers.delete_observer(*args)
|
24
|
-
end
|
25
|
-
|
26
|
-
# @return [Observable] self
|
27
|
-
#
|
28
|
-
def delete_observers
|
29
|
-
observers.delete_observers
|
30
|
-
self
|
31
|
-
end
|
32
|
-
|
33
|
-
# @return [Integer] the observers count
|
34
|
-
#
|
35
|
-
def count_observers
|
36
|
-
observers.count_observers
|
37
|
-
end
|
38
|
-
|
39
|
-
protected # A T T E N Z I O N E A R E A P R O T E T T A
|
40
|
-
|
41
|
-
attr_accessor :observers
|
42
|
-
end
|
43
|
-
|
44
|
-
# A thread safe observer set implemented using copy-on-read approach.
|
45
|
-
# Observers are added and removed from a thread safe collection; every time
|
46
|
-
# a notification is required the internal data structure is copied to
|
47
|
-
# prevent concurrency issues
|
48
|
-
#
|
49
|
-
class CopyOnNotifyObserverSet
|
50
|
-
|
51
|
-
def initialize
|
52
|
-
@mutex = Mutex.new
|
53
|
-
@observers = {}
|
54
|
-
end
|
55
|
-
|
56
|
-
# Adds an observer to this set, if a block is passed, the observer will be
|
57
|
-
# created by this method and no other params should be passed.
|
58
|
-
#
|
59
|
-
# @param [Object] observer
|
60
|
-
# the observer to add
|
61
|
-
# @param [Symbol] func
|
62
|
-
# the function to call on the observer during notification.
|
63
|
-
# Default is :update
|
64
|
-
#
|
65
|
-
# @return [Object]
|
66
|
-
# the added observer
|
67
|
-
#
|
68
|
-
def add_observer(observer = nil, func = :update, &block)
|
69
|
-
if observer.nil? && block.nil?
|
70
|
-
raise ArgumentError, 'should pass observer as a first argument or block'
|
71
|
-
elsif observer && block
|
72
|
-
raise ArgumentError, 'cannot provide both an observer and a block'
|
73
|
-
end
|
74
|
-
|
75
|
-
if block
|
76
|
-
observer = block
|
77
|
-
func = :call
|
78
|
-
end
|
79
|
-
|
80
|
-
begin
|
81
|
-
@mutex.lock
|
82
|
-
@observers[observer] = func
|
83
|
-
ensure
|
84
|
-
@mutex.unlock
|
85
|
-
end
|
86
|
-
observer
|
87
|
-
end
|
88
|
-
|
89
|
-
# @param [Object] observer the observer to remove
|
90
|
-
#
|
91
|
-
# @return [Object] the deleted observer
|
92
|
-
#
|
93
|
-
def delete_observer(observer)
|
94
|
-
@mutex.lock
|
95
|
-
@observers.delete(observer)
|
96
|
-
@mutex.unlock
|
97
|
-
observer
|
98
|
-
end
|
99
|
-
|
100
|
-
# Deletes all observers
|
101
|
-
#
|
102
|
-
# @return [CopyOnWriteObserverSet] self
|
103
|
-
#
|
104
|
-
def delete_observers
|
105
|
-
@mutex.lock
|
106
|
-
@observers.clear
|
107
|
-
@mutex.unlock
|
108
|
-
self
|
109
|
-
end
|
110
|
-
|
111
|
-
# @return [Integer] the observers count
|
112
|
-
#
|
113
|
-
def count_observers
|
114
|
-
@mutex.lock
|
115
|
-
result = @observers.count
|
116
|
-
@mutex.unlock
|
117
|
-
result
|
118
|
-
end
|
119
|
-
|
120
|
-
# Notifies all registered observers with optional args.
|
121
|
-
#
|
122
|
-
# @param [Object] args
|
123
|
-
# arguments to be passed to each observer
|
124
|
-
#
|
125
|
-
# @return [CopyOnWriteObserverSet] self
|
126
|
-
#
|
127
|
-
def notify_observers(*args, &block)
|
128
|
-
observers = duplicate_observers
|
129
|
-
notify_to(observers, *args, &block)
|
130
|
-
self
|
131
|
-
end
|
132
|
-
|
133
|
-
# Notifies all registered observers with optional args and deletes them.
|
134
|
-
#
|
135
|
-
# @param [Object] args
|
136
|
-
# arguments to be passed to each observer
|
137
|
-
#
|
138
|
-
# @return [CopyOnWriteObserverSet] self
|
139
|
-
#
|
140
|
-
def notify_and_delete_observers(*args, &block)
|
141
|
-
observers = duplicate_and_clear_observers
|
142
|
-
notify_to(observers, *args, &block)
|
143
|
-
self
|
144
|
-
end
|
145
|
-
|
146
|
-
private # P R O P R I E T À P R I V A T A Vietato L'accesso
|
147
|
-
|
148
|
-
def duplicate_and_clear_observers
|
149
|
-
@mutex.lock
|
150
|
-
observers = @observers.dup
|
151
|
-
@observers.clear
|
152
|
-
@mutex.unlock
|
153
|
-
observers
|
154
|
-
end
|
155
|
-
|
156
|
-
def duplicate_observers
|
157
|
-
@mutex.lock
|
158
|
-
observers = @observers.dup
|
159
|
-
@mutex.unlock
|
160
|
-
observers
|
161
|
-
end
|
162
|
-
|
163
|
-
def notify_to(observers, *args)
|
164
|
-
if block_given? && !args.empty?
|
165
|
-
raise ArgumentError, 'cannot give arguments and a block'
|
166
|
-
end
|
167
|
-
observers.each do |observer, function|
|
168
|
-
args = yield if block_given?
|
169
|
-
observer.send(function, *args)
|
170
|
-
end
|
171
|
-
end
|
172
|
-
end
|
173
|
-
|
174
|
-
# A thread safe observer set implemented using copy-on-write approach. Every
|
175
|
-
# time an observer is added or removed the whole internal data structure is
|
176
|
-
# duplicated and replaced with a new one.
|
177
|
-
#
|
178
|
-
class CopyOnWriteObserverSet
|
179
|
-
|
180
|
-
def initialize
|
181
|
-
@mutex = Mutex.new
|
182
|
-
@observers = {}
|
183
|
-
end
|
184
|
-
|
185
|
-
# Adds an observer to this set, if a block is passed, the observer will be
|
186
|
-
# created by this method and no other params should be passed.
|
187
|
-
#
|
188
|
-
# @param [Object] observer
|
189
|
-
# the observer to add
|
190
|
-
# @param [Symbol] func
|
191
|
-
# the function to call on the observer during notification
|
192
|
-
# Default is :update
|
193
|
-
# @return [Object]
|
194
|
-
# the added observer
|
195
|
-
#
|
196
|
-
def add_observer(observer = nil, func = :update, &block)
|
197
|
-
if observer.nil? && block.nil?
|
198
|
-
raise ArgumentError, 'should pass observer as a first argument or block'
|
199
|
-
elsif observer && block
|
200
|
-
raise ArgumentError, 'cannot provide both an observer and a block'
|
201
|
-
end
|
202
|
-
|
203
|
-
if block
|
204
|
-
observer = block
|
205
|
-
func = :call
|
206
|
-
end
|
207
|
-
|
208
|
-
begin
|
209
|
-
@mutex.lock
|
210
|
-
new_observers = @observers.dup
|
211
|
-
new_observers[observer] = func
|
212
|
-
@observers = new_observers
|
213
|
-
observer
|
214
|
-
ensure
|
215
|
-
@mutex.unlock
|
216
|
-
end
|
217
|
-
end
|
218
|
-
|
219
|
-
# @param [Object] observer the observer to remove
|
220
|
-
#
|
221
|
-
# @return [Object] the deleted observer
|
222
|
-
#
|
223
|
-
def delete_observer(observer)
|
224
|
-
@mutex.lock
|
225
|
-
new_observers = @observers.dup
|
226
|
-
new_observers.delete(observer)
|
227
|
-
@observers = new_observers
|
228
|
-
observer
|
229
|
-
ensure
|
230
|
-
@mutex.unlock
|
231
|
-
end
|
232
|
-
|
233
|
-
# Deletes all observers
|
234
|
-
#
|
235
|
-
# @return [CopyOnWriteObserverSet] self
|
236
|
-
#
|
237
|
-
def delete_observers
|
238
|
-
self.observers = {}
|
239
|
-
self
|
240
|
-
end
|
241
|
-
|
242
|
-
|
243
|
-
# @return [Integer] the observers count
|
244
|
-
#
|
245
|
-
def count_observers
|
246
|
-
observers.count
|
247
|
-
end
|
248
|
-
|
249
|
-
# Notifies all registered observers with optional args.
|
250
|
-
#
|
251
|
-
# @param [Object] args
|
252
|
-
# arguments to be passed to each observer
|
253
|
-
#
|
254
|
-
# @return [CopyOnWriteObserverSet] self
|
255
|
-
#
|
256
|
-
def notify_observers(*args, &block)
|
257
|
-
notify_to(observers, *args, &block)
|
258
|
-
self
|
259
|
-
end
|
260
|
-
|
261
|
-
# Notifies all registered observers with optional args and deletes them.
|
262
|
-
#
|
263
|
-
# @param [Object] args
|
264
|
-
# arguments to be passed to each observer
|
265
|
-
#
|
266
|
-
# @return [CopyOnWriteObserverSet] self
|
267
|
-
#
|
268
|
-
def notify_and_delete_observers(*args, &block)
|
269
|
-
old = clear_observers_and_return_old
|
270
|
-
notify_to(old, *args, &block)
|
271
|
-
self
|
272
|
-
end
|
273
|
-
|
274
|
-
private # P R O P R I E T À P R I V A T A Vietato L'accesso
|
275
|
-
|
276
|
-
def notify_to(observers, *args)
|
277
|
-
if block_given? && !args.empty?
|
278
|
-
raise ArgumentError, 'cannot give arguments and a block'
|
279
|
-
end
|
280
|
-
observers.each do |observer, function|
|
281
|
-
args = yield if block_given?
|
282
|
-
observer.send(function, *args)
|
283
|
-
end
|
284
|
-
end
|
285
|
-
|
286
|
-
def observers
|
287
|
-
@mutex.lock
|
288
|
-
@observers
|
289
|
-
ensure
|
290
|
-
@mutex.unlock
|
291
|
-
end
|
292
|
-
|
293
|
-
def observers=(new_set)
|
294
|
-
@mutex.lock
|
295
|
-
@observers = new_set
|
296
|
-
ensure
|
297
|
-
@mutex.unlock
|
298
|
-
end
|
299
|
-
|
300
|
-
def clear_observers_and_return_old
|
301
|
-
@mutex.lock
|
302
|
-
old_observers = @observers
|
303
|
-
@observers = {}
|
304
|
-
old_observers
|
305
|
-
ensure
|
306
|
-
@mutex.unlock
|
307
|
-
end
|
308
|
-
end
|
309
|
-
end
|