ensure_it 0.1.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.
- checksums.yaml +7 -0
- data/.gitignore +17 -0
- data/.rspec +2 -0
- data/.ruby-version +1 -0
- data/.travis.yml +7 -0
- data/Gemfile +6 -0
- data/LICENSE.txt +22 -0
- data/README.md +332 -0
- data/Rakefile +11 -0
- data/ensure_it.gemspec +39 -0
- data/lib/ensure_it/config.rb +23 -0
- data/lib/ensure_it/ensure_array.rb +67 -0
- data/lib/ensure_it/ensure_class.rb +30 -0
- data/lib/ensure_it/ensure_float.rb +48 -0
- data/lib/ensure_it/ensure_hash.rb +22 -0
- data/lib/ensure_it/ensure_instance_of.rb +27 -0
- data/lib/ensure_it/ensure_integer.rb +89 -0
- data/lib/ensure_it/ensure_string.rb +43 -0
- data/lib/ensure_it/ensure_symbol.rb +26 -0
- data/lib/ensure_it/errors.rb +173 -0
- data/lib/ensure_it/patch.rb +17 -0
- data/lib/ensure_it/version.rb +3 -0
- data/lib/ensure_it.rb +18 -0
- data/lib/ensure_it_refines.rb +8 -0
- data/spec/integration/refines_spec.rb +37 -0
- data/spec/lib/config_spec.rb +50 -0
- data/spec/lib/ensure_array_spec.rb +75 -0
- data/spec/lib/ensure_class_spec.rb +54 -0
- data/spec/lib/ensure_float_spec.rb +65 -0
- data/spec/lib/ensure_hash_spec.rb +45 -0
- data/spec/lib/ensure_instance_of_spec.rb +49 -0
- data/spec/lib/ensure_integer_spec.rb +89 -0
- data/spec/lib/ensure_string_spec.rb +53 -0
- data/spec/lib/ensure_symbol_spec.rb +39 -0
- data/spec/lib/errors_spec.rb +124 -0
- data/spec/lib/patch_spec.rb +31 -0
- data/spec/spec_helper.rb +19 -0
- data/spec/support/example_groups/ensure_it_example_group.rb +66 -0
- data/spec/support/matchers/warn_matcher.rb +30 -0
- data/spec/support/shared_examples/unmet_objects.rb +60 -0
- 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
|
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,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
|