protobuf 2.1.3 → 2.2.0

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.
@@ -16,6 +16,18 @@ module Protobuf
16
16
  value == 1
17
17
  end
18
18
 
19
+ def define_getter
20
+ super
21
+
22
+ field = self
23
+ @message_class.class_eval do
24
+ define_method("#{field.getter_method_name}?") do
25
+ field.warn_if_deprecated
26
+ @values.fetch(field.name, field.default_value)
27
+ end
28
+ end
29
+ end
30
+
19
31
  def encode(value)
20
32
  [value ? 1 : 0].pack('C')
21
33
  end
@@ -6,11 +6,19 @@ require 'protobuf/message/encoder'
6
6
 
7
7
  module Protobuf
8
8
  class Message
9
-
9
+ ##
10
+ # Error Classes
11
+ #
10
12
  class FieldNotDefinedError < StandardError; end
11
13
 
14
+ ##
15
+ # Constants
16
+ #
12
17
  STRING_ENCODING = "ASCII-8BIT".freeze
13
18
 
19
+ ##
20
+ # Class Methods
21
+ #
14
22
  def self.all_fields
15
23
  @all_fields ||= begin
16
24
  all_fields_array = []
@@ -23,26 +31,6 @@ module Protobuf
23
31
  end
24
32
  end
25
33
 
26
- # Reserve field numbers for extensions. Don't use this method directly.
27
- def self.extensions(range)
28
- extension_fields.add_range(range)
29
- end
30
-
31
- # Define a required field. Don't use this method directly.
32
- def self.required(type, name, tag, options = {})
33
- define_field(:required, type, name, tag, options)
34
- end
35
-
36
- # Define a optional field. Don't use this method directly.
37
- def self.optional(type, name, tag, options = {})
38
- define_field(:optional, type, name, tag, options)
39
- end
40
-
41
- # Define a repeated field. Don't use this method directly.
42
- def self.repeated(type, name, tag, options = {})
43
- define_field(:repeated, type, name, tag, options)
44
- end
45
-
46
34
  # Define a field. Don't use this method directly.
47
35
  def self.define_field(rule, type, fname, tag, options)
48
36
  field_array = options[:extension] ? extension_fields : fields
@@ -57,8 +45,13 @@ module Protobuf
57
45
  field_array[tag] = field_definition
58
46
  end
59
47
 
60
- def self.extension_tag?(tag)
61
- extension_fields.include_tag?(tag)
48
+ # Reserve field numbers for extensions. Don't use this method directly.
49
+ def self.extensions(range)
50
+ extension_fields.add_range(range)
51
+ end
52
+
53
+ def self.extension_field_name_to_tag
54
+ @extension_fields_by_name ||= {}
62
55
  end
63
56
 
64
57
  # An extension field object.
@@ -66,8 +59,8 @@ module Protobuf
66
59
  @extension_fields ||= ::Protobuf::Field::ExtensionFields.new
67
60
  end
68
61
 
69
- def self.extension_field_name_to_tag
70
- @extension_fields_by_name ||= {}
62
+ def self.extension_tag?(tag)
63
+ extension_fields.include_tag?(tag)
71
64
  end
72
65
 
73
66
  # A collection of field object.
@@ -79,6 +72,18 @@ module Protobuf
79
72
  @field_name_to_tag ||= {}
80
73
  end
81
74
 
75
+ def self.get_ext_field_by_name(name)
76
+ # Check if the name has been used before, if not then set it to the sym value
77
+ extension_fields[extension_field_name_to_tag[name.to_sym]]
78
+ rescue TypeError, NoMethodError => e
79
+ name = 'nil' if name.nil?
80
+ raise FieldNotDefinedError.new("Field '#{name}' is not defined on message '#{self.name}'")
81
+ end
82
+
83
+ def self.get_ext_field_by_tag(tag)
84
+ extension_fields[tag]
85
+ end
86
+
82
87
  # Find a field object by +name+.
83
88
  def self.get_field_by_name(name)
84
89
  # Check if the name has been used before, if not then set it to the sym value
@@ -96,16 +101,19 @@ module Protobuf
96
101
  raise FieldNotDefinedError.new("Tag '#{tag}' does not reference a message field for '#{self.name}'")
97
102
  end
98
103
 
99
- def self.get_ext_field_by_name(name)
100
- # Check if the name has been used before, if not then set it to the sym value
101
- extension_fields[extension_field_name_to_tag[name.to_sym]]
102
- rescue TypeError, NoMethodError => e
103
- name = 'nil' if name.nil?
104
- raise FieldNotDefinedError.new("Field '#{name}' is not defined on message '#{self.name}'")
104
+ # Define a optional field. Don't use this method directly.
105
+ def self.optional(type, name, tag, options = {})
106
+ define_field(:optional, type, name, tag, options)
105
107
  end
106
108
 
107
- def self.get_ext_field_by_tag(tag)
108
- extension_fields[tag]
109
+ # Define a repeated field. Don't use this method directly.
110
+ def self.repeated(type, name, tag, options = {})
111
+ define_field(:repeated, type, name, tag, options)
112
+ end
113
+
114
+ # Define a required field. Don't use this method directly.
115
+ def self.required(type, name, tag, options = {})
116
+ define_field(:required, type, name, tag, options)
109
117
  end
110
118
 
111
119
  ##
@@ -117,20 +125,11 @@ module Protobuf
117
125
  values.each { |name, val| self[name] = val unless val.nil? }
118
126
  end
119
127
 
120
- def initialized?
121
- all_fields.all? { |field| field.initialized?(self) }
122
- end
123
-
124
- def has_field?(name)
125
- @values.has_key?(name)
126
- end
127
-
128
- def ==(obj)
129
- return false unless obj.is_a?(self.class)
130
- each_field do |field, value|
131
- return false unless value == obj.__send__(field.name)
132
- end
133
- true
128
+ ##
129
+ # Public Instance Methods
130
+ #
131
+ def all_fields
132
+ self.class.all_fields
134
133
  end
135
134
 
136
135
  def clear!
@@ -145,121 +144,96 @@ module Protobuf
145
144
  self
146
145
  end
147
146
 
148
- def dup
149
- copy_to(super, :dup)
150
- end
151
-
152
147
  def clone
153
148
  copy_to(super, :clone)
154
149
  end
155
150
 
156
- def copy_to(object, method)
157
- duplicate = proc { |obj|
158
- case obj
159
- when Message, String then obj.__send__(method)
160
- else obj
161
- end
162
- }
151
+ def dup
152
+ copy_to(super, :dup)
153
+ end
163
154
 
164
- object.__send__(:initialize)
165
- @values.each do |name, value|
166
- if value.is_a?(Field::FieldArray)
167
- object.__send__(name).replace(value.map {|v| duplicate.call(v)})
168
- else
169
- object.__send__("#{name}=", duplicate.call(value))
170
- end
155
+ # Iterate over a field collection.
156
+ # message.each_field do |field_object, value|
157
+ # # do something
158
+ # end
159
+ def each_field
160
+ all_fields.each do |field|
161
+ value = __send__(field.name)
162
+ yield(field, value)
171
163
  end
172
- object
173
164
  end
174
- private :copy_to
175
165
 
176
- def inspect
177
- to_hash.inspect
166
+ # Returns extension fields. See Message#fields method.
167
+ def extension_fields
168
+ self.class.extension_fields
178
169
  end
179
170
 
180
- def parse_from_string(string)
181
- parse_from(StringIO.new(string))
171
+ def fields
172
+ self.class.fields
182
173
  end
183
174
 
184
- def parse_from(stream)
185
- Decoder.decode(stream, self)
175
+ def get_ext_field_by_name(name) # :nodoc:
176
+ self.class.get_ext_field_by_name(name)
186
177
  end
187
178
 
188
- def serialize_to_string(string='')
189
- io = StringIO.new(string)
190
- serialize_to(io)
191
- result = io.string
192
- result.force_encoding(::Protobuf::Message::STRING_ENCODING) if result.respond_to?(:force_encoding)
193
- result
179
+ def get_ext_field_by_tag(tag) # :nodoc:
180
+ self.class.get_ext_field_by_tag(tag)
194
181
  end
195
- alias to_s serialize_to_string
196
182
 
197
- def serialize_to(stream)
198
- Encoder.encode(stream, self)
183
+ # Returns field object or +nil+.
184
+ def get_field_by_name(name)
185
+ self.class.get_field_by_name(name)
199
186
  end
200
187
 
201
- def set_field(tag, bytes)
202
- field = (get_field_by_tag(tag) || get_ext_field_by_tag(tag))
203
- field.set(self, bytes) if field
188
+ # Returns field object or +nil+.
189
+ def get_field_by_tag(tag)
190
+ self.class.get_field_by_tag(tag)
204
191
  end
205
192
 
206
- def [](name)
207
- if field = get_field_by_name(name) || get_ext_field_by_name(name)
208
- __send__(field.name)
209
- else
210
- raise NoMethodError, "No such field: #{name.inspect}"
211
- end
193
+ def has_field?(name)
194
+ @values.has_key?(name)
212
195
  end
213
196
 
214
- def []=(name, value)
215
- if field = get_field_by_name(name) || get_ext_field_by_name(name)
216
- __send__(field.setter_method_name, value)
217
- else
218
- raise NoMethodError, "No such field: #{name.inspect}"
219
- end
197
+ def initialized?
198
+ all_fields.all? { |field| field.initialized?(self) }
220
199
  end
221
200
 
222
- # Returns a hash; which key is a tag number, and value is a field object.
223
- def all_fields
224
- self.class.all_fields
201
+ def inspect
202
+ to_hash.inspect
225
203
  end
226
204
 
227
- def fields
228
- self.class.fields
205
+ def parse_from_string(string)
206
+ parse_from(StringIO.new(string))
229
207
  end
230
208
 
231
- # Returns field object or +nil+.
232
- def get_field_by_name(name)
233
- self.class.get_field_by_name(name)
209
+ def parse_from(stream)
210
+ Decoder.decode(stream, self)
234
211
  end
235
212
 
236
- # Returns field object or +nil+.
237
- def get_field_by_tag(tag)
238
- self.class.get_field_by_tag(tag)
213
+ def respond_to_has?(key)
214
+ self.respond_to?(key) && self.has_field?(key)
239
215
  end
240
216
 
241
- # Returns extension fields. See Message#fields method.
242
- def extension_fields
243
- self.class.extension_fields
217
+ def respond_to_has_and_present?(key)
218
+ self.respond_to_has?(key) &&
219
+ (self.__send__(key).present? || [true, false].include?(self.__send__(key)))
244
220
  end
245
221
 
246
- def get_ext_field_by_name(name) # :nodoc:
247
- self.class.get_ext_field_by_name(name)
222
+ def serialize_to(stream)
223
+ Encoder.encode(stream, self)
248
224
  end
249
225
 
250
- def get_ext_field_by_tag(tag) # :nodoc:
251
- self.class.get_ext_field_by_tag(tag)
226
+ def serialize_to_string(string='')
227
+ io = StringIO.new(string)
228
+ serialize_to(io)
229
+ result = io.string
230
+ result.force_encoding(::Protobuf::Message::STRING_ENCODING) if result.respond_to?(:force_encoding)
231
+ result
252
232
  end
253
233
 
254
- # Iterate over a field collection.
255
- # message.each_field do |field_object, value|
256
- # # do something
257
- # end
258
- def each_field
259
- all_fields.each do |field|
260
- value = __send__(field.name)
261
- yield(field, value)
262
- end
234
+ def set_field(tag, bytes)
235
+ field = (get_field_by_tag(tag) || get_ext_field_by_tag(tag))
236
+ field.set(self, bytes) if field
263
237
  end
264
238
 
265
239
  # Return a hash-representation of the given fields for this message type.
@@ -274,11 +248,73 @@ module Protobuf
274
248
 
275
249
  return result
276
250
  end
277
- alias_method :to_hash_value, :to_hash
278
251
 
279
252
  def to_json
280
253
  to_hash.to_json
281
254
  end
282
255
 
256
+ def ==(obj)
257
+ return false unless obj.is_a?(self.class)
258
+ each_field do |field, value|
259
+ return false unless value == obj.__send__(field.name)
260
+ end
261
+ true
262
+ end
263
+
264
+ def [](name)
265
+ if field = get_field_by_name(name) || get_ext_field_by_name(name)
266
+ __send__(field.name)
267
+ else
268
+ raise NoMethodError, "No such field: #{name.inspect}"
269
+ end
270
+ end
271
+
272
+ def []=(name, value)
273
+ if field = get_field_by_name(name) || get_ext_field_by_name(name)
274
+ __send__(field.setter_method_name, value)
275
+ else
276
+ raise NoMethodError, "No such field: #{name.inspect}"
277
+ end
278
+ end
279
+
280
+ ##
281
+ # Instance Aliases
282
+ #
283
+ alias_method :to_hash_value, :to_hash
284
+ alias_method :to_s, :serialize_to_string
285
+ alias_method :responds_to_has?, :respond_to_has?
286
+ alias_method :respond_to_and_has?, :respond_to_has?
287
+ alias_method :responds_to_and_has?, :respond_to_has?
288
+ alias_method :respond_to_has_present?, :respond_to_has_and_present?
289
+ alias_method :respond_to_and_has_present?, :respond_to_has_and_present?
290
+ alias_method :respond_to_and_has_and_present?, :respond_to_has_and_present?
291
+ alias_method :responds_to_has_present?, :respond_to_has_and_present?
292
+ alias_method :responds_to_and_has_present?, :respond_to_has_and_present?
293
+ alias_method :responds_to_and_has_and_present?, :respond_to_has_and_present?
294
+
295
+ ##
296
+ # Private Instance Methods
297
+ #
298
+ private
299
+
300
+ def copy_to(object, method)
301
+ duplicate = proc { |obj|
302
+ case obj
303
+ when Message, String then obj.__send__(method)
304
+ else obj
305
+ end
306
+ }
307
+
308
+ object.__send__(:initialize)
309
+ @values.each do |name, value|
310
+ if value.is_a?(Field::FieldArray)
311
+ object.__send__(name).replace(value.map {|v| duplicate.call(v)})
312
+ else
313
+ object.__send__("#{name}=", duplicate.call(value))
314
+ end
315
+ end
316
+ object
317
+ end
318
+
283
319
  end
284
320
  end
@@ -22,7 +22,7 @@ module Protobuf
22
22
  end
23
23
 
24
24
  def enable_gc!
25
- ::GC.enable if ::Protobuf.gc_pause_server_request?
25
+ ::GC.enable && ::GC.start if ::Protobuf.gc_pause_server_request?
26
26
  end
27
27
 
28
28
  # no-op, implemented by including class if desired.
@@ -26,6 +26,20 @@ module Protobuf
26
26
  @filters ||= Hash.new { |h,k| h[k] = [] }
27
27
  end
28
28
 
29
+ # Filters hash keyed based on filter type (e.g. :before, :after, :around),
30
+ # whose values are Sets.
31
+ #
32
+ def rescue_filters
33
+ @rescue_filters ||= {}
34
+ end
35
+
36
+ def rescue_from(*ex_klasses, &block)
37
+ options = ex_klasses.last.is_a?(Hash) ? ex_klasses.pop : {}
38
+ callable = options.delete(:with) { block }
39
+ raise ArgumentError, 'Option :with missing from rescue_from options' if callable.nil?
40
+ ex_klasses.each { |ex_klass| rescue_filters[ex_klass] = callable }
41
+ end
42
+
29
43
  private
30
44
 
31
45
  def define_filter(type, filter, options = {})
@@ -146,14 +160,18 @@ module Protobuf
146
160
  return ! skip_invoke
147
161
  end
148
162
 
163
+ def rescue_filters
164
+ self.class.rescue_filters
165
+ end
166
+
149
167
  # Loop over the unwrapped filters and invoke them. An unwrapped filter
150
168
  # is either a before or after filter, not an around filter.
151
169
  #
152
170
  def run_unwrapped_filters(unwrapped_filters, rpc_method, stop_on_false_return = false)
153
171
  unwrapped_filters.each do |filter|
154
172
  if invoke_filter?(rpc_method, filter)
155
- rv = call_or_send(filter[:callable])
156
- return false if stop_on_false_return && rv === false
173
+ return_value = call_or_send(filter[:callable])
174
+ return false if stop_on_false_return && return_value == false
157
175
  end
158
176
  end
159
177
 
@@ -205,35 +223,41 @@ module Protobuf
205
223
  # be used instead of the other run methods directly.
206
224
  #
207
225
  def run_filters(rpc_method)
208
- continue = run_unwrapped_filters(filters[:before], rpc_method, true)
209
- if continue
210
- run_around_filters(rpc_method)
211
- run_unwrapped_filters(filters[:after], rpc_method)
226
+ run_rescue_filters do
227
+ continue = run_unwrapped_filters(filters[:before], rpc_method, true)
228
+ if continue
229
+ run_around_filters(rpc_method)
230
+ run_unwrapped_filters(filters[:after], rpc_method)
231
+ end
232
+ end
233
+ end
234
+
235
+ def run_rescue_filters
236
+ if rescue_filters.keys.empty?
237
+ yield
238
+ else
239
+ begin
240
+ yield
241
+ rescue *rescue_filters.keys => ex
242
+ call_or_send(rescue_filters[ex.class], ex)
243
+ end
212
244
  end
213
245
  end
214
246
 
215
247
  # Call the object if it is callable, otherwise invoke the method using
216
248
  # __send__ assuming that we respond_to it. Return the call's return value.
217
249
  #
218
- def call_or_send(callable, &block)
219
- rv = case
220
- when callable.respond_to?(:call) then
221
- if callable.arity == 1
222
- callable.call(self, &block)
223
- else
224
- callable.call(&block)
225
- end
226
- when respond_to?(callable, true) then
227
- if method(callable).arity == 1
228
- __send__(callable, self, &block)
229
- else
230
- __send__(callable, &block)
231
- end
232
- else
233
- raise "Object #{callable} is not callable"
234
- end
235
-
236
- return rv
250
+ def call_or_send(callable, *args, &block)
251
+ return_value = case
252
+ when callable.respond_to?(:call) then
253
+ callable.call(self, *args, &block)
254
+ when respond_to?(callable, true) then
255
+ __send__(callable, *args, &block)
256
+ else
257
+ raise "Object #{callable} is not callable"
258
+ end
259
+
260
+ return return_value
237
261
  end
238
262
 
239
263
  end
@@ -1,4 +1,4 @@
1
1
  module Protobuf
2
- VERSION = '2.1.3'
2
+ VERSION = '2.2.0'
3
3
  PROTOC_VERSION = '2.4.1'
4
4
  end
@@ -20,6 +20,78 @@ describe Protobuf::Message do
20
20
  end
21
21
  end
22
22
 
23
+ describe "boolean predicate methods" do
24
+ subject { Test::ResourceFindRequest.new(:name => "resource") }
25
+
26
+ it { should respond_to(:active?) }
27
+
28
+ it "sets the predicate to true when the boolean value is true" do
29
+ subject.active = true
30
+ subject.active?.should be_true
31
+ end
32
+
33
+ it "sets the predicate to false when the boolean value is false" do
34
+ subject.active = false
35
+ subject.active?.should be_false
36
+ end
37
+
38
+ it "does not put predicate methods on non-boolean fields" do
39
+ Test::ResourceFindRequest.new(:name => "resource").should_not respond_to(:name?)
40
+ end
41
+ end
42
+
43
+ describe "#respond_to_and_has?" do
44
+ subject { Test::EnumTestMessage.new(:non_default_enum => 2) }
45
+
46
+ it "is false when the message does not have the field" do
47
+ subject.respond_to_and_has?(:other_field).should be_false
48
+ end
49
+
50
+ it "is true when the message has the field" do
51
+ subject.respond_to_and_has?(:non_default_enum).should be_true
52
+ end
53
+ end
54
+
55
+ describe "#respond_to_has_and_present?" do
56
+ subject { Test::EnumTestMessage.new(:non_default_enum => 2) }
57
+
58
+ it "is false when the message does not have the field" do
59
+ subject.respond_to_and_has_and_present?(:other_field).should be_false
60
+ end
61
+
62
+ it "is false when the field is repeated and a value is not present" do
63
+ subject.respond_to_and_has_and_present?(:repeated_enums).should be_false
64
+ end
65
+
66
+ it "is false when the field is repeated and the value is empty array" do
67
+ subject.repeated_enums = []
68
+ subject.respond_to_and_has_and_present?(:repeated_enums).should be_false
69
+ end
70
+
71
+ it "is true when the field is repeated and a value is present" do
72
+ subject.repeated_enums = [2]
73
+ subject.respond_to_and_has_and_present?(:repeated_enums).should be_true
74
+ end
75
+
76
+ it "is true when the message has the field" do
77
+ subject.respond_to_and_has_and_present?(:non_default_enum).should be_true
78
+ end
79
+
80
+ context "#API" do
81
+ subject { Test::EnumTestMessage.new(:non_default_enum => 2) }
82
+
83
+ it { should respond_to(:respond_to_and_has_and_present?) }
84
+ it { should respond_to(:responds_to_and_has_and_present?) }
85
+ it { should respond_to(:responds_to_has?) }
86
+ it { should respond_to(:respond_to_has?) }
87
+ it { should respond_to(:respond_to_has_present?) }
88
+ it { should respond_to(:responds_to_has_present?) }
89
+ it { should respond_to(:respond_to_and_has_present?) }
90
+ it { should respond_to(:responds_to_and_has_present?) }
91
+ end
92
+
93
+ end
94
+
23
95
  describe '#to_hash' do
24
96
  context 'generating values for an ENUM field' do
25
97
  it 'converts the enum to its tag representation' do
@@ -23,10 +23,12 @@ class FilterTest
23
23
  def self.clear_filters!
24
24
  @defined_filters = nil
25
25
  @filters = nil
26
+ @rescue_filters = nil
26
27
  end
27
28
  end
28
29
 
29
30
  describe Protobuf::Rpc::ServiceFilters do
31
+ let(:params) { {} }
30
32
  subject { FilterTest.new(params) }
31
33
  after(:each) { FilterTest.clear_filters! }
32
34
 
@@ -353,4 +355,97 @@ describe Protobuf::Rpc::ServiceFilters do
353
355
  end
354
356
  end
355
357
 
358
+ describe '#rescue_from' do
359
+ before do
360
+ class CustomError1 < StandardError; end
361
+ class CustomError2 < StandardError; end
362
+ class CustomError3 < StandardError; end
363
+ end
364
+
365
+ before do
366
+ class FilterTest
367
+ private
368
+
369
+ def filter_with_error1
370
+ @called << :filter_with_error1
371
+ raise CustomError1, 'Filter 1 failed'
372
+ end
373
+
374
+ def filter_with_error2
375
+ @called << :filter_with_error2
376
+ raise CustomError1, 'Filter 2 failed'
377
+ end
378
+
379
+ def filter_with_error3
380
+ @called << :filter_with_error3
381
+ raise CustomError3, 'Filter 3 failed'
382
+ end
383
+
384
+ def custom_error_occurred(ex)
385
+ @ex_class = ex.class
386
+ @called << :custom_error_occurred
387
+ end
388
+ end
389
+ end
390
+
391
+ let(:params) { { :ex_class => nil } }
392
+
393
+ context 'when defining multiple errors with a given callback' do
394
+ before do
395
+ FilterTest.rescue_from(CustomError1, CustomError2, CustomError3, :with => :custom_error_occurred)
396
+ end
397
+ before { FilterTest.before_filter(:filter_with_error3) }
398
+
399
+ it 'short-circuits the call stack' do
400
+ expect {
401
+ subject.should_not_receive(:endpoint)
402
+ subject.__send__(:run_filters, :endpoint)
403
+ subject.called.should eq([ :filter_with_error3, :custom_error_occurred ])
404
+ subject.ex_class.should eq CustomError3
405
+ }.to_not raise_error(CustomError3)
406
+ end
407
+ end
408
+
409
+ context 'when defined with options' do
410
+ context 'when :with option is not given' do
411
+ specify do
412
+ expect { FilterTest.rescue_from(CustomError1) }.to raise_error(ArgumentError, /with/)
413
+ end
414
+ end
415
+
416
+ context 'when error occurs inside filter' do
417
+ before { FilterTest.rescue_from(CustomError1, :with => :custom_error_occurred) }
418
+ before { FilterTest.before_filter(:filter_with_error1) }
419
+
420
+ it 'short-circuits the call stack' do
421
+ expect {
422
+ subject.should_not_receive(:endpoint)
423
+ subject.__send__(:run_filters, :endpoint)
424
+ subject.called.should eq([ :filter_with_error1, :custom_error_occurred ])
425
+ subject.ex_class.should eq CustomError1
426
+ }.to_not raise_error(CustomError1)
427
+ end
428
+ end
429
+ end
430
+
431
+ context 'when defined with block' do
432
+ before do
433
+ FilterTest.rescue_from(CustomError1) do |service, ex|
434
+ service.ex_class = ex.class
435
+ service.called << :block_rescue_handler
436
+ end
437
+ end
438
+ before { FilterTest.before_filter(:filter_with_error1) }
439
+
440
+ it 'short-circuits the call stack' do
441
+ expect {
442
+ subject.should_not_receive(:endpoint)
443
+ subject.__send__(:run_filters, :endpoint)
444
+ subject.called.should eq([ :filter_with_error1, :block_rescue_handler ])
445
+ subject.ex_class.should eq CustomError1
446
+ }.to_not raise_error(CustomError1)
447
+ end
448
+ end
449
+ end
450
+
356
451
  end
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: protobuf
3
3
  version: !ruby/object:Gem::Version
4
- version: 2.1.3
4
+ version: 2.2.0
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -10,7 +10,7 @@ authors:
10
10
  autorequire:
11
11
  bindir: bin
12
12
  cert_chain: []
13
- date: 2012-11-08 00:00:00.000000000 Z
13
+ date: 2012-11-12 00:00:00.000000000 Z
14
14
  dependencies:
15
15
  - !ruby/object:Gem::Dependency
16
16
  name: activesupport
@@ -516,7 +516,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
516
516
  version: '0'
517
517
  segments:
518
518
  - 0
519
- hash: 324802600983446856
519
+ hash: 510252424392908935
520
520
  required_rubygems_version: !ruby/object:Gem::Requirement
521
521
  none: false
522
522
  requirements:
@@ -525,7 +525,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
525
525
  version: '0'
526
526
  segments:
527
527
  - 0
528
- hash: 324802600983446856
528
+ hash: 510252424392908935
529
529
  requirements: []
530
530
  rubyforge_project:
531
531
  rubygems_version: 1.8.24