cassilds-model 0.0.4 → 0.0.5

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.
@@ -21,10 +21,10 @@ unless Object.respond_to? :tap
21
21
  end
22
22
 
23
23
  require 'cassandra-model/types'
24
- require 'active_support/callbacks'
25
24
  require 'cassandra-model/config'
26
25
  require 'cassandra-model/connection'
26
+ require 'cassandra-model/callbacks'
27
27
  require 'cassandra-model/persistence'
28
28
  require 'cassandra-model/batches'
29
29
  require 'cassandra-model/base'
30
- #require 'cassandra-model/railtie'
30
+ #require 'cassandra-model/railtie'
@@ -3,7 +3,7 @@ require 'simple_uuid'
3
3
  module CassandraModel
4
4
  class Base
5
5
  extend Forwardable
6
- include ActiveSupport::Callbacks
6
+ include CassandraModel::Callbacks
7
7
  include CassandraModel::Persistence
8
8
  include CassandraModel::Batches
9
9
 
@@ -180,4 +180,4 @@ module CassandraModel
180
180
  alias :eql? ==
181
181
  end
182
182
 
183
- end
183
+ end
@@ -1,49 +1,279 @@
1
1
  module CassandraModel
2
+ # Callbacks are hooks into the lifecycle of an object that allow you to trigger logic
3
+ # before or after an alteration of the object state.
4
+ #
5
+ # Mixing in this module allows you to define callbacks in your class.
6
+ #
7
+ # Example:
8
+ # class Storage
9
+ # include CustomCallbacks::Callbacks
10
+ #
11
+ # define_callbacks :before_save, :after_save
12
+ # end
13
+ #
14
+ # class ConfigStorage < Storage
15
+ # before_save :saving_message
16
+ # def saving_message
17
+ # puts "saving..."
18
+ # end
19
+ #
20
+ # after_save do |object|
21
+ # puts "saved"
22
+ # end
23
+ #
24
+ # def save
25
+ # run_callbacks(:before_save)
26
+ # puts "- save"
27
+ # run_callbacks(:after_save)
28
+ # end
29
+ # end
30
+ #
31
+ # config = ConfigStorage.new
32
+ # config.save
33
+ #
34
+ # Output:
35
+ # saving...
36
+ # - save
37
+ # saved
38
+ #
39
+ # Callbacks from parent classes are inherited.
40
+ #
41
+ # Example:
42
+ # class Storage
43
+ # include CustomCallbacks::Callbacks
44
+ #
45
+ # define_callbacks :before_save, :after_save
46
+ #
47
+ # before_save :prepare
48
+ # def prepare
49
+ # puts "preparing save"
50
+ # end
51
+ # end
52
+ #
53
+ # class ConfigStorage < Storage
54
+ # before_save :saving_message
55
+ # def saving_message
56
+ # puts "saving..."
57
+ # end
58
+ #
59
+ # after_save do |object|
60
+ # puts "saved"
61
+ # end
62
+ #
63
+ # def save
64
+ # run_callbacks(:before_save)
65
+ # puts "- save"
66
+ # run_callbacks(:after_save)
67
+ # end
68
+ # end
69
+ #
70
+ # config = ConfigStorage.new
71
+ # config.save
72
+ #
73
+ # Output:
74
+ # preparing save
75
+ # saving...
76
+ # - save
77
+ # saved
2
78
  module Callbacks
3
- def self.included(base)
4
- base.extend ClassMethods
5
- base.send :include, InstanceMethods
6
- end
79
+ class CallbackChain < Array
80
+ def self.build(kind, *methods, &block)
81
+ methods, options = extract_options(*methods, &block)
82
+ methods.map! { |method| Callback.new(kind, method, options) }
83
+ new(methods)
84
+ end
7
85
 
8
- module ClassMethods
9
- def define_callbacks(*callbacks)
10
- callbacks.each do |callback|
11
- [:before, :after].each do |chain|
12
- callback_name = "#{chain}_#{callback}"
13
- instance_eval <<-EVAL, __FILE__, __LINE__ + 1
14
- def #{callback_name}(*args)
15
- callbacks[:#{callback_name}] += args
16
- end
17
- EVAL
86
+ def run(object, options = {}, &terminator)
87
+ enumerator = options[:enumerator] || :each
88
+
89
+ unless block_given?
90
+ send(enumerator) { |callback| callback.call(object) }
91
+ else
92
+ send(enumerator) do |callback|
93
+ result = callback.call(object)
94
+ break result if terminator.call(result, object)
18
95
  end
19
96
  end
20
97
  end
21
98
 
22
- def callbacks
23
- @callbacks ||= Hash.new {|h, k| h[k] = [] }
99
+ # TODO: Decompose into more Array like behavior
100
+ def replace_or_append!(chain)
101
+ if index = index(chain)
102
+ self[index] = chain
103
+ else
104
+ self << chain
105
+ end
106
+ self
107
+ end
108
+
109
+ def find(callback, &block)
110
+ select { |c| c == callback && (!block_given? || yield(c)) }.first
24
111
  end
112
+
113
+ def delete(callback)
114
+ super(callback.is_a?(Callback) ? callback : find(callback))
115
+ end
116
+
117
+ private
118
+ def self.extract_options(*methods, &block)
119
+ methods.flatten!
120
+ options = methods.extract_options!
121
+ methods << block if block_given?
122
+ return methods, options
123
+ end
124
+
125
+ def extract_options(*methods, &block)
126
+ self.class.extract_options(*methods, &block)
127
+ end
25
128
  end
26
129
 
27
- module InstanceMethods
28
- def run_callbacks(name, &block)
29
- _run_callbacks(:before, name)
30
- result = block.call
31
- _run_callbacks(:after, name, result)
32
- result
130
+ class Callback
131
+ attr_reader :kind, :method, :identifier, :options
132
+
133
+ def initialize(kind, method, options = {})
134
+ @kind = kind
135
+ @method = method
136
+ @identifier = options[:identifier]
137
+ @options = options
138
+ end
139
+
140
+ def ==(other)
141
+ case other
142
+ when Callback
143
+ (self.identifier && self.identifier == other.identifier) || self.method == other.method
144
+ else
145
+ (self.identifier && self.identifier == other) || self.method == other
146
+ end
147
+ end
148
+
149
+ def eql?(other)
150
+ self == other
151
+ end
152
+
153
+ def dup
154
+ self.class.new(@kind, @method, @options.dup)
155
+ end
156
+
157
+ def hash
158
+ if @identifier
159
+ @identifier.hash
160
+ else
161
+ @method.hash
162
+ end
163
+ end
164
+
165
+ def call(*args, &block)
166
+ evaluate_method(method, *args, &block) if should_run_callback?(*args)
167
+ rescue LocalJumpError
168
+ raise ArgumentError,
169
+ "Cannot yield from a Proc type filter. The Proc must take two " +
170
+ "arguments and execute #call on the second argument."
33
171
  end
34
172
 
35
173
  private
36
- def _run_callbacks(chain, name, value = nil)
37
- callback_name = "#{chain}_#{name}".to_sym
38
- self.class.callbacks[callback_name].each do |callback|
39
- next unless callback.is_a? Symbol
40
- if self.class.instance_method(callback).arity > 0
41
- self.send(callback, value)
42
- else
43
- self.send(callback)
174
+ def evaluate_method(method, *args, &block)
175
+ case method
176
+ when Symbol
177
+ object = args.shift
178
+ object.send(method, *args, &block)
179
+ when String
180
+ eval(method, args.first.instance_eval { binding })
181
+ when Proc, Method
182
+ method.call(*args, &block)
183
+ else
184
+ if method.respond_to?(kind)
185
+ method.send(kind, *args, &block)
186
+ else
187
+ raise ArgumentError,
188
+ "Callbacks must be a symbol denoting the method to call, a string to be evaluated, " +
189
+ "a block to be invoked, or an object responding to the callback method."
190
+ end
44
191
  end
45
192
  end
193
+
194
+ def should_run_callback?(*args)
195
+ [options[:if]].flatten.compact.all? { |a| evaluate_method(a, *args) } &&
196
+ ![options[:unless]].flatten.compact.any? { |a| evaluate_method(a, *args) }
197
+ end
198
+ end
199
+
200
+ def self.included(base)
201
+ base.extend ClassMethods
202
+ end
203
+
204
+ module ClassMethods
205
+ def define_callbacks(*callbacks)
206
+ callbacks.each do |callback|
207
+ class_eval <<-"end_eval"
208
+ def self.#{callback}(*methods, &block) # def self.before_save(*methods, &block)
209
+ callbacks = CallbackChain.build(:#{callback}, *methods, &block) # callbacks = CallbackChain.build(:before_save, *methods, &block)
210
+ @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new
211
+ @#{callback}_callbacks.concat callbacks # @before_save_callbacks.concat callbacks
212
+ end # end
213
+ #
214
+ def self.#{callback}_callback_chain # def self.before_save_callback_chain
215
+ @#{callback}_callbacks ||= CallbackChain.new # @before_save_callbacks ||= CallbackChain.new
216
+ #
217
+ if superclass.respond_to?(:#{callback}_callback_chain) # if superclass.respond_to?(:before_save_callback_chain)
218
+ CallbackChain.new( # CallbackChain.new(
219
+ superclass.#{callback}_callback_chain + # superclass.before_save_callback_chain +
220
+ @#{callback}_callbacks # @before_save_callbacks
221
+ ) # )
222
+ else # else
223
+ @#{callback}_callbacks # @before_save_callbacks
224
+ end # end
225
+ end # end
226
+ end_eval
227
+ end
46
228
  end
47
229
  end
230
+
231
+ # Runs all the callbacks defined for the given options.
232
+ #
233
+ # If a block is given it will be called after each callback receiving as arguments:
234
+ #
235
+ # * the result from the callback
236
+ # * the object which has the callback
237
+ #
238
+ # If the result from the block evaluates to false, the callback chain is stopped.
239
+ #
240
+ # Example:
241
+ # class Storage
242
+ # include CustomCallbacks::Callbacks
243
+ #
244
+ # define_callbacks :before_save, :after_save
245
+ # end
246
+ #
247
+ # class ConfigStorage < Storage
248
+ # before_save :pass
249
+ # before_save :pass
250
+ # before_save :stop
251
+ # before_save :pass
252
+ #
253
+ # def pass
254
+ # puts "pass"
255
+ # end
256
+ #
257
+ # def stop
258
+ # puts "stop"
259
+ # return false
260
+ # end
261
+ #
262
+ # def save
263
+ # result = run_callbacks(:before_save) { |result, object| result == false }
264
+ # puts "- save" if result
265
+ # end
266
+ # end
267
+ #
268
+ # config = ConfigStorage.new
269
+ # config.save
270
+ #
271
+ # Output:
272
+ # pass
273
+ # pass
274
+ # stop
275
+ def run_callbacks(kind, options = {}, &block)
276
+ self.class.send("#{kind}_callback_chain").run(self, options, &block)
277
+ end
48
278
  end
49
- end
279
+ end
@@ -11,5 +11,4 @@ module CassandraModel
11
11
  end
12
12
  end
13
13
  end
14
-
15
14
  end
@@ -1,3 +1,3 @@
1
1
  class CassandraModel
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: cassilds-model
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.4
4
+ version: 0.0.5
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,11 +10,11 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2011-08-16 00:00:00.000000000Z
13
+ date: 2011-08-19 00:00:00.000000000Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: shoulda
17
- requirement: &10607820 !ruby/object:Gem::Requirement
17
+ requirement: &24681920 !ruby/object:Gem::Requirement
18
18
  none: false
19
19
  requirements:
20
20
  - - ! '>='
@@ -22,10 +22,10 @@ dependencies:
22
22
  version: '0'
23
23
  type: :runtime
24
24
  prerelease: false
25
- version_requirements: *10607820
25
+ version_requirements: *24681920
26
26
  - !ruby/object:Gem::Dependency
27
27
  name: cassilds
28
- requirement: &10607400 !ruby/object:Gem::Requirement
28
+ requirement: &24681500 !ruby/object:Gem::Requirement
29
29
  none: false
30
30
  requirements:
31
31
  - - ! '>='
@@ -33,10 +33,10 @@ dependencies:
33
33
  version: '0'
34
34
  type: :runtime
35
35
  prerelease: false
36
- version_requirements: *10607400
36
+ version_requirements: *24681500
37
37
  - !ruby/object:Gem::Dependency
38
38
  name: simple_uuid
39
- requirement: &10606840 !ruby/object:Gem::Requirement
39
+ requirement: &24680940 !ruby/object:Gem::Requirement
40
40
  none: false
41
41
  requirements:
42
42
  - - ! '>='
@@ -44,7 +44,7 @@ dependencies:
44
44
  version: '0'
45
45
  type: :runtime
46
46
  prerelease: false
47
- version_requirements: *10606840
47
+ version_requirements: *24680940
48
48
  description: Cassandra-model allows you to map ColumnFamily/SuperColumnFamily in Cassandra
49
49
  to Ruby objects. It was designed to be fast and simple.
50
50
  email: