protobuf 2.1.3 → 2.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -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