ensure_it 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (41) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +17 -0
  3. data/.rspec +2 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +7 -0
  6. data/Gemfile +6 -0
  7. data/LICENSE.txt +22 -0
  8. data/README.md +332 -0
  9. data/Rakefile +11 -0
  10. data/ensure_it.gemspec +39 -0
  11. data/lib/ensure_it/config.rb +23 -0
  12. data/lib/ensure_it/ensure_array.rb +67 -0
  13. data/lib/ensure_it/ensure_class.rb +30 -0
  14. data/lib/ensure_it/ensure_float.rb +48 -0
  15. data/lib/ensure_it/ensure_hash.rb +22 -0
  16. data/lib/ensure_it/ensure_instance_of.rb +27 -0
  17. data/lib/ensure_it/ensure_integer.rb +89 -0
  18. data/lib/ensure_it/ensure_string.rb +43 -0
  19. data/lib/ensure_it/ensure_symbol.rb +26 -0
  20. data/lib/ensure_it/errors.rb +173 -0
  21. data/lib/ensure_it/patch.rb +17 -0
  22. data/lib/ensure_it/version.rb +3 -0
  23. data/lib/ensure_it.rb +18 -0
  24. data/lib/ensure_it_refines.rb +8 -0
  25. data/spec/integration/refines_spec.rb +37 -0
  26. data/spec/lib/config_spec.rb +50 -0
  27. data/spec/lib/ensure_array_spec.rb +75 -0
  28. data/spec/lib/ensure_class_spec.rb +54 -0
  29. data/spec/lib/ensure_float_spec.rb +65 -0
  30. data/spec/lib/ensure_hash_spec.rb +45 -0
  31. data/spec/lib/ensure_instance_of_spec.rb +49 -0
  32. data/spec/lib/ensure_integer_spec.rb +89 -0
  33. data/spec/lib/ensure_string_spec.rb +53 -0
  34. data/spec/lib/ensure_symbol_spec.rb +39 -0
  35. data/spec/lib/errors_spec.rb +124 -0
  36. data/spec/lib/patch_spec.rb +31 -0
  37. data/spec/spec_helper.rb +19 -0
  38. data/spec/support/example_groups/ensure_it_example_group.rb +66 -0
  39. data/spec/support/matchers/warn_matcher.rb +30 -0
  40. data/spec/support/shared_examples/unmet_objects.rb +60 -0
  41. metadata +177 -0
@@ -0,0 +1,89 @@
1
+ module EnsureIt
2
+ OCT_REGEXP = /\A0\d+\z/
3
+ INT_REGEXP = /\A[+\-]?\d[\d_]*\z/
4
+ HEX_REGEXP = /\A0x[0-9a-zA-Z]+\z/
5
+ BIN_REGEXP = /\A0b[01]+\z/
6
+
7
+ patch Object do
8
+ def ensure_integer(**opts)
9
+ opts.key?(:wrong) ? opts[:wrong] : nil
10
+ end
11
+
12
+ def ensure_integer!(**opts)
13
+ opts[:message] ||= '#{subject} should be an integer or be able' \
14
+ ' to convert to it'
15
+ EnsureIt.raise_error(:ensure_integer!, **opts)
16
+ end
17
+ end
18
+
19
+ patch String do
20
+ using EnsureIt if ENSURE_IT_REFINES
21
+
22
+ def ensure_integer(**opts)
23
+ case self
24
+ when OCT_REGEXP then opts[:octal] == true ? self.to_i(8) : self.to_i
25
+ when INT_REGEXP then self.to_i
26
+ when HEX_REGEXP then self[2..-1].to_i(16)
27
+ when BIN_REGEXP then self[2..-1].to_i(2)
28
+ else nil
29
+ end
30
+ end
31
+
32
+ def ensure_integer!(**opts)
33
+ ensure_integer(**opts) || super(**opts)
34
+ end
35
+ end
36
+
37
+ patch Integer do
38
+ def ensure_integer(**opts)
39
+ self
40
+ end
41
+ alias_method :ensure_integer!, :ensure_integer
42
+ end
43
+
44
+ patch Float do
45
+ def ensure_integer(**opts)
46
+ round
47
+ end
48
+ alias_method :ensure_integer!, :ensure_integer
49
+ end
50
+
51
+ patch Rational do
52
+ def ensure_integer(**opts)
53
+ round
54
+ end
55
+ alias_method :ensure_integer!, :ensure_integer
56
+ end
57
+
58
+ patch TrueClass do
59
+ using EnsureIt if ENSURE_IT_REFINES
60
+
61
+ def ensure_integer(**opts)
62
+ if opts[:boolean] == true || opts[:boolean].is_a?(Integer)
63
+ opts[:boolean] == true ? 1 : opts[:boolean]
64
+ else
65
+ nil
66
+ end
67
+ end
68
+
69
+ def ensure_integer!(**opts)
70
+ if opts[:boolean] == true || opts[:boolean].is_a?(Integer)
71
+ opts[:boolean] == true ? 1 : opts[:boolean]
72
+ else
73
+ super(**opts)
74
+ end
75
+ end
76
+ end
77
+
78
+ patch FalseClass do
79
+ using EnsureIt if ENSURE_IT_REFINES
80
+
81
+ def ensure_integer(**opts)
82
+ opts[:boolean] == true || opts[:boolean].is_a?(Integer) ? 0 : nil
83
+ end
84
+
85
+ def ensure_integer!(**opts)
86
+ opts[:boolean] == true || opts[:boolean].is_a?(Integer) ? 0 : super(**opts)
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,43 @@
1
+ module EnsureIt
2
+ patch Object do
3
+ def ensure_string(**opts)
4
+ opts.key?(:wrong) ? opts[:wrong] : nil
5
+ end
6
+
7
+ def ensure_string!(**opts)
8
+ opts[:message] ||=
9
+ if opts[:numbers] == true
10
+ '#{subject} should be a String, Symbol, Numeric or Rational'
11
+ else
12
+ '#{subject} should be a String or a Symbol'
13
+ end
14
+ EnsureIt.raise_error(:ensure_string!, **opts)
15
+ end
16
+ end
17
+
18
+ patch String do
19
+ def ensure_string(**opts)
20
+ self
21
+ end
22
+ alias_method :ensure_string!, :ensure_string
23
+ end
24
+
25
+ patch Symbol do
26
+ def ensure_string(**opts)
27
+ to_s
28
+ end
29
+ alias_method :ensure_string!, :ensure_string
30
+ end
31
+
32
+ patch Numeric do
33
+ using EnsureIt if ENSURE_IT_REFINES
34
+
35
+ def ensure_string(**opts)
36
+ opts[:numbers] == true ? to_s : nil
37
+ end
38
+
39
+ def ensure_string!(**opts)
40
+ opts[:numbers] == true ? to_s : super(**opts)
41
+ end
42
+ end
43
+ end
@@ -0,0 +1,26 @@
1
+ module EnsureIt
2
+ patch Object do
3
+ def ensure_symbol(**opts)
4
+ opts.key?(:wrong) ? opts[:wrong] : nil
5
+ end
6
+
7
+ def ensure_symbol!(**opts)
8
+ opts[:message] ||= '#{subject} should be a Symbol or a String'
9
+ EnsureIt.raise_error(:ensure_symbol!, **opts)
10
+ end
11
+ end
12
+
13
+ patch String do
14
+ def ensure_symbol(**opts)
15
+ to_sym
16
+ end
17
+ alias_method :ensure_symbol!, :ensure_symbol
18
+ end
19
+
20
+ patch Symbol do
21
+ def ensure_symbol(**opts)
22
+ self
23
+ end
24
+ alias_method :ensure_symbol!, :ensure_symbol
25
+ end
26
+ end
@@ -0,0 +1,173 @@
1
+ module EnsureIt
2
+ class Error < StandardError; end
3
+
4
+ class ErrorMessage
5
+ attr_accessor :method_name, :subject, :subject_type, :inside, :backtrace
6
+ attr_writer :message
7
+
8
+ def initialize(method_name, message, backtrace)
9
+ method_name = method_name.to_sym if method_name.is_a?(String)
10
+ unless method_name.is_a?(Symbol)
11
+ raise ArgumentError, 'EnsureIt: Wrong method_name argument for Error'
12
+ end
13
+ @method_name, @message, @backtrace = method_name, message, backtrace
14
+ end
15
+
16
+ def subject_display_name
17
+ display_name =
18
+ if @subject.nil? && @subject_type != :unknown_method_result
19
+ "subject of '#{method_name}' method"
20
+ else
21
+ case @subject_type
22
+ when :local_variable then "local variable '#{@subject}'"
23
+ when :instance_variable then "instance variable '@#{@subject}'"
24
+ when :class_variable then "class variable '@@#{@subject}'"
25
+ when :method_result then "return value of '#{subject}' method"
26
+ when :unknown_method_result then 'return value of method'
27
+ when :req_argument then "argument '#{subject}'"
28
+ when :rest_argument then "argument '*#{subject}'"
29
+ when :opt_argument then "optional argument '#{subject}'"
30
+ when :key_argument then "key argument '#{subject}'"
31
+ when :keyrest_argument then "key argument '**#{subject}'"
32
+ when :block_argument then "block argument '&#{subject}'"
33
+ else "subject of '#{method_name}' method"
34
+ end
35
+ end
36
+ unless @inside.nil?
37
+ display_name +=
38
+ if !@subject_type.nil? && @subject_type.to_s =~ /_argument\z/
39
+ " of '#{@inside}' method"
40
+ else
41
+ " inside '#{@inside}' method"
42
+ end
43
+ end
44
+ display_name
45
+ end
46
+
47
+ def message
48
+ unless @message.is_a?(String)
49
+ @message =
50
+ if @subject.nil? && @subject_type != :unknown_method_result
51
+ '#{subject}'
52
+ else
53
+ '#{subject} of #{method_name}'
54
+ end
55
+ end
56
+ @message.gsub(/\#\{subject\}/, subject_display_name)
57
+ .gsub(/\#\{name\}/, @subject.to_s)
58
+ .gsub(/\#\{method_name\}/, @method_name.to_s)
59
+ end
60
+ end
61
+
62
+ def self.raise_error(method_name, message: nil, error: Error, **opts)
63
+ error = Error unless error <= Exception
64
+ error_msg = ErrorMessage.new(method_name, message, caller[1..-1])
65
+ if opts.key?(:smart) && opts[:smart] != true ||
66
+ EnsureIt.config.errors != :smart
67
+ raise error_class, error.message, error.backtrace
68
+ end
69
+ raise_smart_error(error_msg, error, **opts)
70
+ end
71
+
72
+ def self.raise_smart_error(error, error_class, **opts)
73
+ inspect_source(error, **opts)
74
+ tp_count = 0
75
+ error_obj = nil
76
+ error_message = error.message
77
+ error_backtrace = error.backtrace
78
+ #
79
+ # first trace point is to capture raise object before exitting
80
+ # from :ensure_* method
81
+ #
82
+ # after that with second trace point we try to return from :ensure_* method
83
+ # to caller and inspect code there for method name and arguments
84
+ TracePoint.trace(:return, :raise) do |first_tp|
85
+ if first_tp.event == :raise
86
+ # save error object for patching
87
+ error_obj = first_tp.raised_exception
88
+ else
89
+ # skip returns from :raise_smart_error and :raise_error
90
+ tp_count += 1
91
+ if tp_count > 1
92
+ # at this moment we are at end of 'ensure_' method
93
+ first_tp.disable
94
+ TracePoint.trace(:return) do |second_tp|
95
+ # skip return from :ensure_* method
96
+ tp_count += 1
97
+ if tp_count > 3
98
+ # now we are in caller context
99
+ second_tp.disable
100
+ unless error_obj.nil?
101
+ # inspect caller code
102
+ inspect_code(second_tp, error, **opts)
103
+ # patch error message
104
+ error_obj.extend(Module.new do
105
+ @@ensure_it_message = error.message
106
+ def message; @@ensure_it_message; end
107
+ end)
108
+ end
109
+ end
110
+ end
111
+ end
112
+ end
113
+ end
114
+ raise error_class, error_message, error_backtrace
115
+ end
116
+
117
+ def self.inspect_source(error, **opts)
118
+ file_name, line_no = error.backtrace.first.split(':', 2)
119
+ return unless File.exist?(file_name)
120
+ line_no = line_no.to_i
121
+ line = read_line_number(file_name, line_no)
122
+ return if line.nil?
123
+ m_name = error.method_name
124
+ m = /
125
+ (?:(?<method_access>\.)|(?<class_access>@{1,2}))?
126
+ (?<name>(?:[a-z_][a-zA-Z_0-9]*(?<modifier>[?!])?)|\))
127
+ (?:
128
+ (?<send>\.send\(\s*(?::#{m_name}|'#{m_name}'|"#{m_name}")\s*\))|
129
+ (?:\.#{m_name}(?:[^a-zA-Z_0-9]|\z))
130
+ )
131
+ /x.match(line)
132
+ return if m.nil? || m[:method_access].nil? && !m[:modifier].nil?
133
+ error.subject = m[:name]
134
+ error.subject_type = case
135
+ when m[:class_access] then
136
+ m[:class_access] == '@' ? :instance_variable : :class_variable
137
+ when m[:name] == ')' then
138
+ error.subject = nil
139
+ :unknown_method_result
140
+ when m[:method_access] then :method_result
141
+ else :local_variable
142
+ end
143
+ end
144
+
145
+ def self.inspect_code(tp, error, **opts)
146
+ return if tp.method_id.nil?
147
+ error.inside = tp.method_id
148
+ begin
149
+ method = eval("method(:#{tp.method_id})", tp.binding)
150
+ rescue NameError
151
+ return
152
+ end
153
+ param = method.parameters.find { |_, name| name.to_s == error.subject }
154
+ unless param.nil?
155
+ error.subject_type = "#{param[0]}_argument".to_sym
156
+ end
157
+ end
158
+
159
+ def self.read_line_number(file_name, number)
160
+ counter, line = 0, nil
161
+ File.foreach(file_name) do |l|
162
+ counter += 1
163
+ if counter == number
164
+ line = l.chomp!
165
+ break
166
+ end
167
+ end
168
+ line
169
+ end
170
+
171
+ private_class_method :raise_smart_error, :inspect_source, :inspect_code,
172
+ :read_line_number
173
+ end
@@ -0,0 +1,17 @@
1
+ module EnsureIt
2
+ if ENSURE_IT_REFINES
3
+ def self.patch(target, &block)
4
+ module_eval do
5
+ refine target do
6
+ class_eval(&block)
7
+ end
8
+ end
9
+ end
10
+ else
11
+ def self.patch(target, &block)
12
+ target.class_eval(&block)
13
+ end
14
+ end
15
+
16
+ private_class_method :patch
17
+ end
@@ -0,0 +1,3 @@
1
+ module EnsureIt
2
+ VERSION = '0.1.0'
3
+ end
data/lib/ensure_it.rb ADDED
@@ -0,0 +1,18 @@
1
+ if RUBY_VERSION < '2.0.0'
2
+ fail %q{EnsureIt: library doesn't support ruby < 2.0.0}
3
+ end
4
+
5
+ defined?(ENSURE_IT_REFINES) || ENSURE_IT_REFINES = false
6
+
7
+ require File.join %w(ensure_it version)
8
+ require File.join %w(ensure_it config)
9
+ require File.join %w(ensure_it errors)
10
+ require File.join %w(ensure_it patch)
11
+ require File.join %w(ensure_it ensure_symbol)
12
+ require File.join %w(ensure_it ensure_string)
13
+ require File.join %w(ensure_it ensure_integer)
14
+ require File.join %w(ensure_it ensure_float)
15
+ require File.join %w(ensure_it ensure_array)
16
+ require File.join %w(ensure_it ensure_hash)
17
+ require File.join %w(ensure_it ensure_instance_of)
18
+ require File.join %w(ensure_it ensure_class)
@@ -0,0 +1,8 @@
1
+ if RUBY_VERSION >= '2.1'
2
+ ENSURE_IT_REFINES = true
3
+ else
4
+ ENSURE_IT_REFINES = false
5
+ warn 'EsureIt: refines supported only for ruby >= 2.1'
6
+ end
7
+
8
+ require 'ensure_it'
@@ -0,0 +1,37 @@
1
+ require 'spec_helper'
2
+
3
+ describe EnsureIt do
4
+ describe 'refines requirement' do
5
+ before { @backup = ENSURE_IT_REFINES }
6
+
7
+ after do
8
+ if defined? ENSURE_IT_REFINES
9
+ Object.instance_eval { remove_const(:ENSURE_IT_REFINES) }
10
+ end
11
+ ENSURE_IT_REFINES = @backup
12
+ end
13
+
14
+ def load_refines
15
+ if defined? ENSURE_IT_REFINES
16
+ Object.instance_eval { remove_const(:ENSURE_IT_REFINES) }
17
+ end
18
+ load(File.expand_path(
19
+ File.join(%w(.. .. .. lib ensure_it_refines.rb)), __FILE__
20
+ ))
21
+ end
22
+
23
+ if RUBY_VERSION >= '2.1'
24
+ it 'defines ENSURE_IT_REFINES' do
25
+ load_refines
26
+ expect(ENSURE_IT_REFINES).to be_true
27
+ end
28
+ else
29
+ it %q{warns with ruby < 2.1 and doesn't defines ENSURE_IT_REFINES} do
30
+ expect {
31
+ load_refines
32
+ }.to warn('EsureIt: refines supported only for ruby >= 2.1')
33
+ expect(ENSURE_IT_REFINES).to be_false
34
+ end
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,50 @@
1
+ require 'spec_helper'
2
+
3
+ describe EnsureIt::Config do
4
+ describe '::errors' do
5
+ after { described_class.instance_variable_set(:@errors, nil) }
6
+
7
+ it 'gives :smart by default' do
8
+ expect(described_class.errors).to eq :smart
9
+ end
10
+
11
+ it 'calls setter if value given' do
12
+ expect(described_class).to receive(:errors=).with(:standard)
13
+ described_class.errors :standard
14
+ end
15
+ end
16
+
17
+ describe '::errors=' do
18
+ after { described_class.instance_variable_set(:@errors, nil) }
19
+
20
+ it 'allows to change value' do
21
+ described_class.errors = :standard
22
+ expect(described_class.errors).to eq :standard
23
+ end
24
+
25
+ it 'sets to default for wrong values' do
26
+ described_class.errors = :bad_value
27
+ expect(described_class.errors).to eq :smart
28
+ end
29
+ end
30
+ end
31
+
32
+ describe EnsureIt do
33
+ describe '::config' do
34
+ it 'returns Config module' do
35
+ expect(described_class.config).to eq EnsureIt::Config
36
+ end
37
+ end
38
+
39
+ describe '::configure' do
40
+ it 'returns Config module' do
41
+ expect(described_class.config).to eq EnsureIt::Config
42
+ end
43
+
44
+ it 'yields block with Config module' do
45
+ expect { |b|
46
+ described_class.configure(&b)
47
+ }.to yield_with_args(EnsureIt::Config)
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,75 @@
1
+ require 'spec_helper'
2
+
3
+ class Tester
4
+ using EnsureIt if ENSURE_IT_REFINES
5
+
6
+ def ensure_array(*args)
7
+ obj.ensure_array(*args)
8
+ end
9
+
10
+ def ensure_array!(*args)
11
+ obj.ensure_array!(*args)
12
+ end
13
+ end
14
+
15
+ describe EnsureIt do
16
+ shared_examples 'array parser' do
17
+ it 'and returns self for array' do
18
+ obj = [1, nil, 2]
19
+ expect(call_for(obj)).to eq obj
20
+ end
21
+
22
+ it 'compacts array with compact option' do
23
+ expect(call_for([1, nil, 2], compact: true)).to eq [1, 2]
24
+ end
25
+
26
+ it 'flattens array with flatten option' do
27
+ expect(call_for([1, [2, 3], 4], flatten: true)).to eq [1, 2, 3, 4]
28
+ end
29
+
30
+ [:sorted, :ordered].each do |o|
31
+ it "flattens and then sorts array with flatten and #{o} options" do
32
+ expect(
33
+ call_for([1, [5, 6], 4], flatten: true, o => true)
34
+ ).to eq [1, 4, 5, 6]
35
+ end
36
+
37
+ it "sorts descending with #{o}: :desc option" do
38
+ expect(call_for([1, 5, 6, 4], o => :desc)).to eq [6, 5, 4, 1]
39
+ end
40
+ end
41
+
42
+ it 'calls :ensure_* for each element' do
43
+ arr = ['s', nil, :v]
44
+ expect(call_for(arr, :ensure_symbol, compact: true)).to eq [:s, :v]
45
+ end
46
+
47
+ it 'calls standard method for each element' do
48
+ arr = ['s', :v]
49
+ expect(call_for(arr, :to_s)).to eq ['s', 'v']
50
+ end
51
+
52
+ it 'chains methods for each element' do
53
+ arr = ['s', :v]
54
+ expect(call_for(arr, :ensure_string, :to_sym)).to eq [:s, :v]
55
+ end
56
+ end
57
+
58
+ describe '#ensure_array' do
59
+ it_behaves_like 'array parser'
60
+ it_behaves_like 'empty array creator for unmet objects', except: Array
61
+
62
+ it 'and returns nil with wrong: nil option' do
63
+ expect(call_for(true, wrong: nil)).to be_nil
64
+ expect(call_for(true, wrong: 1)).to eq 1
65
+ end
66
+ end
67
+
68
+ describe '#ensure_array!' do
69
+ it_behaves_like 'array parser'
70
+ it_behaves_like(
71
+ 'banger for unmet objects', except: Array,
72
+ message: /should be an Array/
73
+ )
74
+ end
75
+ end
@@ -0,0 +1,54 @@
1
+ require 'spec_helper'
2
+
3
+ class Tester
4
+ using EnsureIt if ENSURE_IT_REFINES
5
+
6
+ def ensure_class(*args)
7
+ obj.ensure_class(*args)
8
+ end
9
+
10
+ def ensure_class!(*args)
11
+ obj.ensure_class!(*args)
12
+ end
13
+ end
14
+
15
+ describe EnsureIt do
16
+ shared_examples 'class selector' do
17
+ it 'and returns self for right classes' do
18
+ expect(call_for(String)).to eq String
19
+ end
20
+
21
+ it 'and checks for ancestors' do
22
+ expect(call_for(Array, Enumerable, Array)).to eq Array
23
+ end
24
+ end
25
+
26
+ describe '#ensure_class' do
27
+ it_behaves_like 'class selector'
28
+
29
+ it 'returns nil for wrong classes' do
30
+ expect(call_for(10)).to be_nil
31
+ expect(call_for(Float, Integer)).to be_nil
32
+ end
33
+
34
+ it 'returns wrong option for wrong classs' do
35
+ expect(call_for(10, wrong: true)).to be_true
36
+ end
37
+ end
38
+
39
+ describe '#ensure_class!' do
40
+ it_behaves_like 'class selector'
41
+
42
+ it 'raises for non-classes' do
43
+ expect {
44
+ call_for(10)
45
+ }.to raise_error EnsureIt::Error, /should be a class\z/
46
+ end
47
+
48
+ it 'raises on wrong classes' do
49
+ expect {
50
+ call_for(Float, Integer)
51
+ }.to raise_error EnsureIt::Error, /should subclass or extend all of/
52
+ end
53
+ end
54
+ end
@@ -0,0 +1,65 @@
1
+ require 'spec_helper'
2
+
3
+ class Tester
4
+ using EnsureIt if ENSURE_IT_REFINES
5
+
6
+ def ensure_float(*args)
7
+ obj.ensure_float(*args)
8
+ end
9
+
10
+ def ensure_float!(*args)
11
+ obj.ensure_float!(*args)
12
+ end
13
+ end
14
+
15
+ describe EnsureIt do
16
+ shared_examples 'float numerizer' do
17
+ it 'and returns self for Float' do
18
+ obj = 0.1
19
+ expect(call_for(obj)).to eq obj
20
+ end
21
+
22
+ it 'and converts Rational' do
23
+ expect(call_for(Rational(1, 2))).to eq 0.5
24
+ end
25
+
26
+ it 'and converts Integers' do
27
+ expect(call_for(100)).to eq 100.0
28
+ expect(call_for(100)).to be_kind_of(Float)
29
+ end
30
+
31
+ it 'and converts decimal strings' do
32
+ expect(call_for('100')).to eq(100.0)
33
+ expect(call_for('100')).to be_kind_of(Float)
34
+ end
35
+
36
+ it 'and converts strings with dot' do
37
+ expect(call_for('0.1')).to eq(0.1)
38
+ end
39
+
40
+ it 'and converts scientific strings' do
41
+ expect(call_for('1e3')).to eq(1000.0)
42
+ expect(call_for('1e-3')).to eq(0.001)
43
+ expect(call_for('-1.5e+3')).to eq(-1500.0)
44
+ end
45
+ end
46
+
47
+ describe '#ensure_float' do
48
+ it_behaves_like 'float numerizer'
49
+ it_behaves_like(
50
+ 'niller for unmet objects',
51
+ '123test', :test123, :'0.1',
52
+ except: [String, Integer, Float, Rational]
53
+ )
54
+ end
55
+
56
+ describe '#ensure_float!' do
57
+ it_behaves_like 'float numerizer'
58
+ it_behaves_like(
59
+ 'banger for unmet objects',
60
+ '123test', :test123, :'0.1',
61
+ except: [String, Integer, Float, Rational],
62
+ message: /should be a float or be able to convert to it/
63
+ )
64
+ end
65
+ end