coaster 1.0.5 → 1.2.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 71910814edd2fcc1011e2f7bbc0d5003d3ffacca49d8a60f4869859d7c911afd
4
- data.tar.gz: 5898b403bcb2263ff96c70721f724b5f91d9e52dff474f90a9ea854effba5676
3
+ metadata.gz: c85271d1d65e61c492464d2e3bc610bad2fa784ba3da758e246c599ba655262c
4
+ data.tar.gz: b2715ff440d638cdd164338a1c55b4c689cdad95e54a65b66c29d8ad5e7d7d75
5
5
  SHA512:
6
- metadata.gz: dd1a8ee8e2f472633ef7ea34588cde48d77cb053ad186aac02702c806afbb4dd8829ece4892e456413ca6c840afa77d637f9fa2e068922319b4a4bd850ded75e
7
- data.tar.gz: 8996da8e600df0d704353b89daba9f2c97b4261e4b77c7be32aa32644cb8c8018ef8b4f323de6186f5e6deeabe44f304ca0979a4c1b96abf714300487e0d11db
6
+ metadata.gz: f74c50dce4b7d64a44ec89a67814d2ce2ee1b9c8b89b75aae0fe4dbe05182ac444ac7903f1a5585d227cdb890f566727506722c9878ed12bcd1a583aea42080f
7
+ data.tar.gz: 19fd1dad72c06d49b5f3a380519a5f1ec7677c201d0485e6eceea866739513989decadafd396733dcffb66392b9ef8dd609feb2a510d307c9ab6e60e36a6faa8
@@ -5,7 +5,7 @@ require 'active_support/core_ext/string'
5
5
  require 'active_support/core_ext/hash/slice'
6
6
 
7
7
  module Coaster
8
- mattr_accessor :logger
8
+ mattr_writer :logger
9
9
  mattr_writer :default_fingerprint
10
10
 
11
11
  DEFAULT_FINGERPRINT = [:default, :class].freeze
@@ -18,6 +18,16 @@ module Coaster
18
18
  def default_fingerprint
19
19
  @@default_fingerprint ||= DEFAULT_FINGERPRINT
20
20
  end
21
+
22
+ def logger
23
+ return @@logger if defined?(@@logger) && @@logger
24
+ return Rails.logger if defined?(Rails)
25
+ nil
26
+ end
27
+ end
28
+
29
+ def logger
30
+ self.class.logger
21
31
  end
22
32
  end
23
33
 
@@ -4,7 +4,7 @@ class Object
4
4
  class << self
5
5
  def _translate(*args)
6
6
  options = args.last.is_a?(Hash) ? args.pop : {}
7
- options.merge!(_translate_params)
7
+ options = _translate_params.merge(options)
8
8
  options = options.to_hash.symbolize_keys!
9
9
 
10
10
  key = args.shift
@@ -45,7 +45,10 @@ class Object
45
45
 
46
46
  if key_class.superclass == Object || key_class == Object
47
47
  return options[:description] if options[:description].present?
48
- Coaster.logger && Coaster.logger.warn(result)
48
+ if Coaster.logger
49
+ Coaster.logger.info(options[:original_missing])
50
+ Coaster.logger.debug(caller.join("\n"))
51
+ end
49
52
  throw :exception, result if options[:original_throw]
50
53
  missing = options[:original_missing] || result
51
54
  msg = missing.message
@@ -61,6 +64,7 @@ class Object
61
64
  result = result.dup if result.frozen?
62
65
  result.instance_variable_set(:@translated, true)
63
66
  result.instance_variable_set(:@tkey, options[:tkey])
67
+ result.instance_variable_set(:@missing, options[:original_missing])
64
68
  result
65
69
  end
66
70
  end
@@ -78,16 +82,7 @@ class Object
78
82
  def _translate(*args)
79
83
  options = (args.last.is_a?(Hash) ? args.pop : {}).with_indifferent_access
80
84
  key = args.shift || (respond_to?(:tkey) ? tkey : nil)
81
-
82
- if respond_to?(:description) && description.present? && description != 'false' && description != self.class.name
83
- if !key.is_a?(String) && key != :force
84
- desc = description
85
- return desc unless desc.instance_variable_get(:@raw)
86
- end
87
- options.merge!(description: description)
88
- end
89
-
90
- options.merge!(_translate_params)
85
+ options = _translate_params.merge(options)
91
86
  self.class._translate(key, *args, options)
92
87
  end
93
88
 
@@ -9,10 +9,24 @@ class StandardError
9
9
  def http_status; 500 end
10
10
  def report?; true end
11
11
  def intentional?; false end
12
+ def title; _translate('.title') end
12
13
 
13
- def title
14
- t = _translate('.title')
15
- t.instance_variable_defined?(:@missing) ? nil : t
14
+ def before_logging(name, &block)
15
+ @before_logging_blocks ||= {}
16
+ @before_logging_blocks[name] = block
17
+ end
18
+ def before_logging_blocks
19
+ @before_logging_blocks ||= {}
20
+ superclass <= StandardError ? superclass.before_logging_blocks.merge(@before_logging_blocks) : @before_logging_blocks
21
+ end
22
+
23
+ def after_logging(name, &block)
24
+ @after_logging_blocks ||= {}
25
+ @after_logging_blocks[name] = block
26
+ end
27
+ def after_logging_blocks
28
+ @after_logging_blocks ||= {}
29
+ superclass <= StandardError ? superclass.after_logging_blocks.merge(@after_logging_blocks) : @after_logging_blocks
16
30
  end
17
31
  end
18
32
 
@@ -43,6 +57,7 @@ class StandardError
43
57
  msg = hash.delete(:m)
44
58
  msg = hash.delete(:msg) || msg
45
59
  msg = hash.delete(:message) || msg
60
+ hash[:description] ||= hash.delete(:desc) if hash[:desc].present?
46
61
  @fingerprint = hash.delete(:fingerprint) || hash.delete(:fingerprints)
47
62
  @tags = hash.delete(:tags) || hash.delete(:tag)
48
63
  @level = hash.delete(:level) || hash.delete(:severity) || @level
@@ -65,6 +80,8 @@ class StandardError
65
80
 
66
81
  def safe_message; message || '' end
67
82
  def status; self.class.status end
83
+ def before_logging_blocks; self.class.before_logging_blocks end
84
+ def after_logging_blocks; self.class.after_logging_blocks end
68
85
  def root_cause; cause.respond_to?(:root_cause) ? cause.root_cause : self end
69
86
 
70
87
  def attributes
@@ -82,23 +99,40 @@ class StandardError
82
99
  def code; attributes[:code] || status end
83
100
  def code=(value); attributes[:code] = value end
84
101
  def title; attributes[:title] || self.class.title end
85
- def report?; attributes.key?(:report) ? attributes[:report] : self.class.report? end
86
- def intentional?; attributes.key?(:intentional) ? attributes[:intentional] : self.class.intentional? end
102
+ def it_might_happen?; attributes[:it] == :might_happen end
103
+ def it_should_not_happen?; attributes[:it] == :should_not_happen end
104
+ def report?
105
+ return attributes[:report] if attributes.key?(:report)
106
+ return false if it_might_happen?
107
+ self.class.report?
108
+ end
109
+ def intentional? # not logging in test
110
+ return attributes[:intentional] if attributes.key?(:intentional)
111
+ return true if it_should_not_happen?
112
+ self.class.intentional?
113
+ end
87
114
  def object; attributes[:object] || attributes[:obj] end
88
115
  alias_method :obj, :object
89
116
 
90
- # description is user friendly messages, do not use error's message
117
+ # description is user friendly message as a attribute, do not use error's message
91
118
  # error message is not user friendly in many cases.
92
119
  def description
93
- dsc = attributes[:description] || attributes[:desc]
94
- return dsc if dsc
95
- msg = safe_message.dup
96
- msg.instance_variable_set(:@raw, true)
97
- msg
120
+ attributes[:description] || attributes[:desc]
98
121
  end
99
122
  alias_method :desc, :description
100
123
 
101
- # more user friendly messages
124
+ def _translate(*args)
125
+ return description if description.present?
126
+ super
127
+ end
128
+
129
+ # user friendly message, for overid
130
+ def user_message
131
+ return description if description.present?
132
+ _translate
133
+ end
134
+
135
+ # another user friendly messages
102
136
  def descriptions
103
137
  return attributes[:descriptions] if attributes[:descriptions]
104
138
  attributes[:descriptions] = {}
@@ -120,13 +154,6 @@ class StandardError
120
154
  hash
121
155
  end
122
156
 
123
- def _translate_params
124
- attributes.merge(
125
- type: self.class.name, status: status,
126
- http_status: http_status, message: message
127
- )
128
- end
129
-
130
157
  def to_json
131
158
  Oj.dump(to_hash.with_indifferent_access, mode: :compat)
132
159
  end
@@ -172,13 +199,17 @@ class StandardError
172
199
  end
173
200
 
174
201
  def logging(options = {})
175
- return unless report?
176
- logger = nil
177
- if defined?(Rails)
178
- return if Rails.env.test? && intentional?
179
- logger = Rails.logger
202
+ before_logging_blocks.values.each { |blk| instance_exec &blk }
203
+
204
+ if !report? || intentional?
205
+ if defined?(Rails)
206
+ return if Rails.env.test?
207
+ else
208
+ return
209
+ end
180
210
  end
181
- logger = options[:logger] || Coaster.logger || logger
211
+
212
+ logger = options[:logger] || Coaster.logger
182
213
  return unless logger
183
214
 
184
215
  cl = options[:cleaner] || cleaner
@@ -196,5 +227,8 @@ class StandardError
196
227
  else
197
228
  logger.error(msg)
198
229
  end
230
+ msg
231
+ ensure
232
+ after_logging_blocks.values.each { |blk| instance_exec &blk }
199
233
  end
200
234
  end
@@ -66,4 +66,17 @@ class StandardError
66
66
  capture(options)
67
67
  just_logging(options)
68
68
  end
69
+
70
+ # https://github.com/getsentry/sentry-ruby/blob/fbbc7a51ed10684d0e8b7bd9d2a1b65a7351c9ef/lib/raven/event.rb#L162
71
+ # sentry use `to_s` as a message
72
+ alias to_origin_s to_s
73
+ def message
74
+ to_origin_s
75
+ end
76
+
77
+ def to_s
78
+ str = super # https://ruby-doc.org/core-2.5.1/Exception.html#method-i-to_s
79
+ str = "#{user_message} / #{str}" if user_message.present?
80
+ str
81
+ end
69
82
  end
@@ -1,3 +1,3 @@
1
1
  module Coaster
2
- VERSION = '1.0.5'
2
+ VERSION = '1.2.1'
3
3
  end
@@ -1,5 +1,8 @@
1
1
  en:
2
2
  class:
3
+ StandardError:
4
+ self: 'standard error translation'
5
+ title: 'standard error title'
3
6
  Coaster:
4
7
  self: 'Coaster Translated'
5
8
  SampleObject:
@@ -6,3 +6,12 @@ require 'pry'
6
6
  require 'rubygems'
7
7
  require 'bundler/setup'
8
8
  require 'coaster'
9
+ require 'logger'
10
+
11
+ class Raven
12
+ def self.capture_exception(*args)
13
+ end
14
+ end
15
+
16
+ Coaster.logger = Logger.new(STDOUT)
17
+ Coaster.logger.level = Logger::WARN
@@ -37,6 +37,7 @@ module Coaster
37
37
  def test_translation_sub
38
38
  assert_equal 'Coaster SampleObject Title (class.Coaster.SampleObject.title)', SampleObject._translate('.title')
39
39
  assert_equal 'Coaster SampleObject Title (class.Coaster.SampleObject.title)', SampleObject._translate(:title)
40
+ assert_nil SampleObject._translate(:title).instance_variable_get(:@missing)
40
41
  end
41
42
 
42
43
  def test_translation_with_key
@@ -46,6 +47,7 @@ module Coaster
46
47
  def test_translation_inheritance
47
48
  assert_equal 'Coaster SampleObject Translated', Inherited._translate
48
49
  assert_equal 'Coaster SampleObject Title (class.Coaster.Inherited.title)', Inherited._translate(:title)
50
+ assert Inherited._translate.instance_variable_get(:@missing)
49
51
  end
50
52
 
51
53
  def test_interpolation
@@ -20,6 +20,63 @@ module Coaster
20
20
  I18n.enforce_available_locales = false
21
21
  end
22
22
 
23
+ def test_standard_messages
24
+ e = StandardError.new('asdf')
25
+ assert_equal 'asdf', e.message
26
+ assert_nil e.description
27
+ assert_nil e.desc
28
+ assert_equal 'standard error translation', e._translate
29
+ assert_equal 'standard error translation', e.user_message
30
+ assert_equal 'standard error translation / asdf', e.to_s
31
+ assert_equal 'standard error title', e.title
32
+ e = StandardError.new(m: 'foo', desc: 'bar')
33
+ assert_equal 'foo', e.message
34
+ assert_equal 'bar', e.description
35
+ assert_equal 'bar', e.desc
36
+ assert_equal 'bar', e._translate
37
+ assert_equal 'bar', e.user_message
38
+ assert_equal 'standard error title', e.title
39
+ assert_equal 'bar / foo', e.to_s
40
+ end
41
+
42
+ def test_no_translation_class
43
+ e = UntitledError.new('asdf')
44
+ assert_equal 'asdf', e.message
45
+ assert_nil e.description
46
+ assert_nil e.desc
47
+ assert_equal 'standard error translation', e._translate
48
+ assert_equal 'standard error translation', e.user_message
49
+ assert_equal 'standard error translation / asdf', e.to_s
50
+ assert_equal 'standard error title', e.title
51
+ e = UntitledError.new(m: 'foo', desc: 'bar')
52
+ assert_equal 'foo', e.message
53
+ assert_equal 'bar', e.description
54
+ assert_equal 'bar', e.desc
55
+ assert_equal 'bar', e._translate
56
+ assert_equal 'bar', e.user_message
57
+ assert_equal 'bar / foo', e.to_s
58
+ assert_equal 'standard error title', e.title
59
+ end
60
+
61
+ def test_with_translation_class
62
+ e = SampleError.new('asdf')
63
+ assert_equal 'asdf', e.message
64
+ assert_nil e.description
65
+ assert_nil e.desc
66
+ assert_equal 'Test sample error', e._translate
67
+ assert_equal 'Test sample error', e.user_message
68
+ assert_equal 'Test sample error / asdf', e.to_s
69
+ assert_equal 'Test this title', e.title
70
+ e = SampleError.new(m: 'foo', desc: 'bar')
71
+ assert_equal 'foo', e.message
72
+ assert_equal 'bar', e.description
73
+ assert_equal 'bar', e.desc
74
+ assert_equal 'bar', e._translate
75
+ assert_equal 'bar', e.user_message
76
+ assert_equal 'bar / foo', e.to_s
77
+ assert_equal 'Test this title', e.title
78
+ end
79
+
23
80
  def test_message
24
81
  raise SampleError, {m: 'beer is proof'}
25
82
  rescue => e
@@ -39,16 +96,16 @@ module Coaster
39
96
  raise ExampleError, {wat: 'cha'}
40
97
  end
41
98
  rescue => e
42
- assert_equal e.to_hash['wat'], 'cha'
43
- assert_equal e.to_hash['type'], 'Coaster::TestStandardError::ExampleError'
44
- assert_equal e.to_hash['status'], 20
45
- assert_equal e.to_hash['http_status'], 500
46
- assert_equal e.to_hash['message'], 'Test sample error'
47
- assert_equal e.to_hash['cause']['frog'], 'rams'
48
- assert_equal e.to_hash['cause']['type'], 'Coaster::TestStandardError::SampleError'
49
- assert_equal e.to_hash['cause']['status'], 10
50
- assert_equal e.to_hash['cause']['http_status'], 500
51
- assert_equal e.to_hash['cause']['message'], 'Test sample error'
99
+ assert_equal 'cha', e.to_hash['wat']
100
+ assert_equal 'Coaster::TestStandardError::ExampleError', e.to_hash['type']
101
+ assert_equal 20, e.to_hash['status']
102
+ assert_equal 500, e.to_hash['http_status']
103
+ assert_equal 'Test sample error', e.to_hash['message']
104
+ assert_equal 'rams', e.to_hash['cause']['frog']
105
+ assert_equal 'Coaster::TestStandardError::SampleError', e.to_hash['cause']['type']
106
+ assert_equal 10, e.to_hash['cause']['status']
107
+ assert_equal 500, e.to_hash['cause']['http_status']
108
+ assert_equal 'Test sample error', e.to_hash['cause']['message']
52
109
  end
53
110
 
54
111
  def test_cause_attributes
@@ -58,9 +115,9 @@ module Coaster
58
115
  raise ExampleError, {wat: 'cha'}
59
116
  end
60
117
  rescue => e
61
- assert_equal e.cause.attr['frog'], 'rams'
62
- assert_equal e.attr['frog'], 'rams'
63
- assert_equal e.attr['wat'], 'cha'
118
+ assert_equal 'rams', e.cause.attr['frog']
119
+ assert_equal 'rams', e.attr['frog']
120
+ assert_equal 'cha', e.attr['wat']
64
121
  end
65
122
 
66
123
  def test_to_detail
@@ -94,19 +151,19 @@ LOG
94
151
  def test_translation
95
152
  raise SampleError, {tkey: '.test'}
96
153
  rescue => e
97
- assert_equal e._translate, 'Test this translation'
154
+ assert_equal 'Test this translation', e._translate
98
155
  end
99
156
 
100
157
  def test_title
101
158
  raise SampleError, 'foobar'
102
159
  rescue => e
103
- assert_equal e.title, 'Test this title'
160
+ assert_equal 'Test this title', e.title
104
161
  end
105
162
 
106
163
  def test_title_missing
107
164
  raise UntitledError, 'untitled'
108
165
  rescue => e
109
- assert_nil e.title
166
+ assert_equal 'standard error title', e.title
110
167
  end
111
168
 
112
169
  def root_cause_sample1
@@ -129,31 +186,54 @@ LOG
129
186
  begin
130
187
  root_cause_sample3
131
188
  rescue => e
132
- assert_equal e.root_cause.message, 'a'
189
+ assert_equal 'a', e.root_cause.message
133
190
  end
134
191
  end
135
192
 
136
193
  def test_raven_notes
137
194
  raise SampleError, m: 'foofoo', something: 'other'
138
195
  rescue => e
139
- assert_equal e.notes(the_other: 'something')[:extra][:something], 'other'
140
- assert_equal e.notes(the_other: 'something')[:extra][:the_other], 'something'
196
+ assert_equal 'other', e.notes(the_other: 'something')[:extra][:something]
197
+ assert_equal 'something', e.notes(the_other: 'something')[:extra][:the_other]
141
198
  end
142
199
 
143
200
  def test_to_hash
144
201
  aa # raise NameError
145
202
  rescue => e
146
- assert_equal e.to_hash['type'], 'NameError'
147
- assert_equal e.to_hash['status'], 999999
148
- assert_equal e.to_hash['http_status'], 500
149
- assert e.to_hash['message'] =~ /undefined local variable or method `aa'/
203
+ assert_equal 'NameError', e.to_hash['type']
204
+ assert_equal 999999, e.to_hash['status']
205
+ assert_equal 500, e.to_hash['http_status']
206
+ assert_match /undefined local variable or method `aa'/, e.to_hash['message']
150
207
  end
151
208
 
152
209
  def test_descriptions
153
210
  raise SampleError
154
211
  rescue => e
155
212
  e.descriptions.merge!(a: 1)
156
- assert_equal e.descriptions['a'], 1
213
+ assert_equal 1, e.descriptions['a']
214
+ end
215
+
216
+ class SampleErrorSub < SampleError; end
217
+ class SampleErrorSubSub < SampleErrorSub
218
+ def it_might_happen?; true end
219
+ end
220
+ SampleError.after_logging(:blah) do
221
+ self.attributes[:abc] = 100
222
+ @blah = 101
223
+ end
224
+ def test_before_logging
225
+ e = SampleErrorSubSub.new(m: 'foo')
226
+ assert !e.after_logging_blocks[:blah].nil?
227
+ e.logging
228
+ assert_equal 100, e.attributes[:abc]
229
+ assert_equal 101, e.instance_variable_get(:@blah)
230
+ end
231
+ class SampleErrorMightHappen < SampleErrorSub
232
+ def it_might_happen?; true end
233
+ end
234
+ def test_might_happen
235
+ e = SampleErrorMightHappen.new('fbar')
236
+ assert !e.report?
157
237
  end
158
238
  end
159
239
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: coaster
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.5
4
+ version: 1.2.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - buzz jung
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2020-07-08 00:00:00.000000000 Z
11
+ date: 2020-10-13 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: i18n
@@ -44,14 +44,14 @@ dependencies:
44
44
  requirements:
45
45
  - - ">="
46
46
  - !ruby/object:Gem::Version
47
- version: '3.0'
47
+ version: 6.0.3.1
48
48
  type: :runtime
49
49
  prerelease: false
50
50
  version_requirements: !ruby/object:Gem::Requirement
51
51
  requirements:
52
52
  - - ">="
53
53
  - !ruby/object:Gem::Version
54
- version: '3.0'
54
+ version: 6.0.3.1
55
55
  - !ruby/object:Gem::Dependency
56
56
  name: attr_extras
57
57
  requirement: !ruby/object:Gem::Requirement
@@ -70,114 +70,114 @@ dependencies:
70
70
  name: bundler
71
71
  requirement: !ruby/object:Gem::Requirement
72
72
  requirements:
73
- - - "~>"
73
+ - - ">="
74
74
  - !ruby/object:Gem::Version
75
- version: '1.12'
75
+ version: '0'
76
76
  type: :development
77
77
  prerelease: false
78
78
  version_requirements: !ruby/object:Gem::Requirement
79
79
  requirements:
80
- - - "~>"
80
+ - - ">="
81
81
  - !ruby/object:Gem::Version
82
- version: '1.12'
82
+ version: '0'
83
83
  - !ruby/object:Gem::Dependency
84
84
  name: pry
85
85
  requirement: !ruby/object:Gem::Requirement
86
86
  requirements:
87
- - - "~>"
87
+ - - ">="
88
88
  - !ruby/object:Gem::Version
89
- version: '0.8'
89
+ version: '0'
90
90
  type: :development
91
91
  prerelease: false
92
92
  version_requirements: !ruby/object:Gem::Requirement
93
93
  requirements:
94
- - - "~>"
94
+ - - ">="
95
95
  - !ruby/object:Gem::Version
96
- version: '0.8'
96
+ version: '0'
97
97
  - !ruby/object:Gem::Dependency
98
98
  name: pry-stack_explorer
99
99
  requirement: !ruby/object:Gem::Requirement
100
100
  requirements:
101
- - - "~>"
101
+ - - ">="
102
102
  - !ruby/object:Gem::Version
103
- version: '0.4'
103
+ version: '0'
104
104
  type: :development
105
105
  prerelease: false
106
106
  version_requirements: !ruby/object:Gem::Requirement
107
107
  requirements:
108
- - - "~>"
108
+ - - ">="
109
109
  - !ruby/object:Gem::Version
110
- version: '0.4'
110
+ version: '0'
111
111
  - !ruby/object:Gem::Dependency
112
112
  name: pry-byebug
113
113
  requirement: !ruby/object:Gem::Requirement
114
114
  requirements:
115
- - - "~>"
115
+ - - ">="
116
116
  - !ruby/object:Gem::Version
117
- version: '3.0'
117
+ version: '0'
118
118
  type: :development
119
119
  prerelease: false
120
120
  version_requirements: !ruby/object:Gem::Requirement
121
121
  requirements:
122
- - - "~>"
122
+ - - ">="
123
123
  - !ruby/object:Gem::Version
124
- version: '3.0'
124
+ version: '0'
125
125
  - !ruby/object:Gem::Dependency
126
126
  name: minitest
127
127
  requirement: !ruby/object:Gem::Requirement
128
128
  requirements:
129
- - - "~>"
129
+ - - ">="
130
130
  - !ruby/object:Gem::Version
131
- version: '5.0'
131
+ version: '0'
132
132
  type: :development
133
133
  prerelease: false
134
134
  version_requirements: !ruby/object:Gem::Requirement
135
135
  requirements:
136
- - - "~>"
136
+ - - ">="
137
137
  - !ruby/object:Gem::Version
138
- version: '5.0'
138
+ version: '0'
139
139
  - !ruby/object:Gem::Dependency
140
140
  name: mocha
141
141
  requirement: !ruby/object:Gem::Requirement
142
142
  requirements:
143
- - - "~>"
143
+ - - ">="
144
144
  - !ruby/object:Gem::Version
145
- version: '1.0'
145
+ version: '0'
146
146
  type: :development
147
147
  prerelease: false
148
148
  version_requirements: !ruby/object:Gem::Requirement
149
149
  requirements:
150
- - - "~>"
150
+ - - ">="
151
151
  - !ruby/object:Gem::Version
152
- version: '1.0'
152
+ version: '0'
153
153
  - !ruby/object:Gem::Dependency
154
154
  name: shoulda
155
155
  requirement: !ruby/object:Gem::Requirement
156
156
  requirements:
157
- - - "~>"
157
+ - - ">="
158
158
  - !ruby/object:Gem::Version
159
- version: '3.0'
159
+ version: '0'
160
160
  type: :development
161
161
  prerelease: false
162
162
  version_requirements: !ruby/object:Gem::Requirement
163
163
  requirements:
164
- - - "~>"
164
+ - - ">="
165
165
  - !ruby/object:Gem::Version
166
- version: '3.0'
166
+ version: '0'
167
167
  - !ruby/object:Gem::Dependency
168
168
  name: shoulda-context
169
169
  requirement: !ruby/object:Gem::Requirement
170
170
  requirements:
171
- - - "~>"
171
+ - - ">="
172
172
  - !ruby/object:Gem::Version
173
- version: '1.0'
173
+ version: '0'
174
174
  type: :development
175
175
  prerelease: false
176
176
  version_requirements: !ruby/object:Gem::Requirement
177
177
  requirements:
178
- - - "~>"
178
+ - - ">="
179
179
  - !ruby/object:Gem::Version
180
- version: '1.0'
180
+ version: '0'
181
181
  description: Ruby Core Extensions
182
182
  email: buzz@frograms.com
183
183
  executables: []
@@ -221,12 +221,12 @@ required_rubygems_version: !ruby/object:Gem::Requirement
221
221
  - !ruby/object:Gem::Version
222
222
  version: '0'
223
223
  requirements: []
224
- rubygems_version: 3.0.3
224
+ rubygems_version: 3.1.2
225
225
  signing_key:
226
226
  specification_version: 4
227
227
  summary: A little convenient feature for standard library
228
228
  test_files:
229
+ - test/test_object_translation.rb
229
230
  - test/test_helper.rb
230
231
  - test/test_standard_error.rb
231
232
  - test/locales/en.yml
232
- - test/test_object_translation.rb