coercible 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +18 -0
- data/.rspec +2 -0
- data/.travis.yml +19 -0
- data/Changelog.md +4 -0
- data/Gemfile +6 -0
- data/Gemfile.devtools +44 -0
- data/Guardfile +58 -0
- data/LICENSE.txt +22 -0
- data/README.md +64 -0
- data/Rakefile +2 -0
- data/coercible.gemspec +22 -0
- data/config/flay.yml +3 -0
- data/config/flog.yml +2 -0
- data/config/mutant.yml +3 -0
- data/config/roodi.yml +17 -0
- data/config/site.reek +91 -0
- data/config/yardstick.yml +2 -0
- data/lib/coercible.rb +42 -0
- data/lib/coercible/coercer.rb +155 -0
- data/lib/coercible/coercer/array.rb +24 -0
- data/lib/coercible/coercer/configurable.rb +54 -0
- data/lib/coercible/coercer/date.rb +27 -0
- data/lib/coercible/coercer/date_time.rb +27 -0
- data/lib/coercible/coercer/decimal.rb +41 -0
- data/lib/coercible/coercer/false_class.rb +25 -0
- data/lib/coercible/coercer/float.rb +40 -0
- data/lib/coercible/coercer/hash.rb +72 -0
- data/lib/coercible/coercer/integer.rb +130 -0
- data/lib/coercible/coercer/numeric.rb +67 -0
- data/lib/coercible/coercer/object.rb +160 -0
- data/lib/coercible/coercer/string.rb +251 -0
- data/lib/coercible/coercer/symbol.rb +25 -0
- data/lib/coercible/coercer/time.rb +41 -0
- data/lib/coercible/coercer/time_coercions.rb +87 -0
- data/lib/coercible/coercer/true_class.rb +25 -0
- data/lib/coercible/configuration.rb +33 -0
- data/lib/coercible/version.rb +3 -0
- data/lib/support/options.rb +113 -0
- data/lib/support/type_lookup.rb +113 -0
- data/spec/integration/configuring_coercers_spec.rb +14 -0
- data/spec/shared/unit/configurable.rb +27 -0
- data/spec/spec_helper.rb +30 -0
- data/spec/unit/coercible/coercer/array/to_set_spec.rb +12 -0
- data/spec/unit/coercible/coercer/class_methods/new_spec.rb +13 -0
- data/spec/unit/coercible/coercer/date/to_date_spec.rb +10 -0
- data/spec/unit/coercible/coercer/date/to_datetime_spec.rb +30 -0
- data/spec/unit/coercible/coercer/date/to_string_spec.rb +12 -0
- data/spec/unit/coercible/coercer/date/to_time_spec.rb +12 -0
- data/spec/unit/coercible/coercer/date_time/to_date_spec.rb +30 -0
- data/spec/unit/coercible/coercer/date_time/to_datetime_spec.rb +10 -0
- data/spec/unit/coercible/coercer/date_time/to_string_spec.rb +12 -0
- data/spec/unit/coercible/coercer/date_time/to_time_spec.rb +30 -0
- data/spec/unit/coercible/coercer/decimal/to_decimal_spec.rb +9 -0
- data/spec/unit/coercible/coercer/decimal/to_float_spec.rb +12 -0
- data/spec/unit/coercible/coercer/decimal/to_integer_spec.rb +12 -0
- data/spec/unit/coercible/coercer/decimal/to_string_spec.rb +12 -0
- data/spec/unit/coercible/coercer/element_reference_spec.rb +19 -0
- data/spec/unit/coercible/coercer/false_class/to_string_spec.rb +12 -0
- data/spec/unit/coercible/coercer/float/to_decimal_spec.rb +12 -0
- data/spec/unit/coercible/coercer/float/to_float_spec.rb +9 -0
- data/spec/unit/coercible/coercer/float/to_integer_spec.rb +12 -0
- data/spec/unit/coercible/coercer/float/to_string_spec.rb +12 -0
- data/spec/unit/coercible/coercer/hash/to_date_spec.rb +38 -0
- data/spec/unit/coercible/coercer/hash/to_datetime_spec.rb +38 -0
- data/spec/unit/coercible/coercer/hash/to_time_spec.rb +38 -0
- data/spec/unit/coercible/coercer/integer/to_boolean_spec.rb +27 -0
- data/spec/unit/coercible/coercer/integer/to_decimal_spec.rb +12 -0
- data/spec/unit/coercible/coercer/integer/to_float_spec.rb +12 -0
- data/spec/unit/coercible/coercer/integer/to_integer_spec.rb +9 -0
- data/spec/unit/coercible/coercer/integer/to_string_spec.rb +12 -0
- data/spec/unit/coercible/coercer/integer_spec.rb +11 -0
- data/spec/unit/coercible/coercer/numeric/to_decimal_spec.rb +10 -0
- data/spec/unit/coercible/coercer/numeric/to_float_spec.rb +10 -0
- data/spec/unit/coercible/coercer/numeric/to_integer_spec.rb +10 -0
- data/spec/unit/coercible/coercer/numeric/to_string_spec.rb +12 -0
- data/spec/unit/coercible/coercer/object/to_array_spec.rb +51 -0
- data/spec/unit/coercible/coercer/object/to_hash_spec.rb +22 -0
- data/spec/unit/coercible/coercer/object/to_integer_spec.rb +22 -0
- data/spec/unit/coercible/coercer/object/to_string_spec.rb +22 -0
- data/spec/unit/coercible/coercer/string/to_boolean_spec.rb +31 -0
- data/spec/unit/coercible/coercer/string/to_constant_spec.rb +49 -0
- data/spec/unit/coercible/coercer/string/to_date_spec.rb +25 -0
- data/spec/unit/coercible/coercer/string/to_datetime_spec.rb +52 -0
- data/spec/unit/coercible/coercer/string/to_decimal_spec.rb +47 -0
- data/spec/unit/coercible/coercer/string/to_float_spec.rb +57 -0
- data/spec/unit/coercible/coercer/string/to_integer_spec.rb +68 -0
- data/spec/unit/coercible/coercer/string/to_symbol_spec.rb +9 -0
- data/spec/unit/coercible/coercer/string/to_time_spec.rb +52 -0
- data/spec/unit/coercible/coercer/string_spec.rb +11 -0
- data/spec/unit/coercible/coercer/symbol/to_string_spec.rb +12 -0
- data/spec/unit/coercible/coercer/time/to_integer_spec.rb +10 -0
- data/spec/unit/coercible/coercer/time/to_time_spec.rb +10 -0
- data/spec/unit/coercible/coercer/time_coercions/to_date_spec.rb +30 -0
- data/spec/unit/coercible/coercer/time_coercions/to_datetime_spec.rb +34 -0
- data/spec/unit/coercible/coercer/time_coercions/to_string_spec.rb +19 -0
- data/spec/unit/coercible/coercer/time_coercions/to_time_spec.rb +34 -0
- data/spec/unit/coercible/coercer/true_class/to_string_spec.rb +12 -0
- data/spec/unit/coercible/configuration/class_methods/build_spec.rb +15 -0
- metadata +235 -0
@@ -0,0 +1,14 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe "Configuring coercers" do
|
4
|
+
it "allows to configure coercers" do
|
5
|
+
coercer = Coercer.new do |config|
|
6
|
+
config.string.boolean_map = { 'yup' => true, 'nope' => false }
|
7
|
+
end
|
8
|
+
|
9
|
+
expect(coercer[String].to_boolean('yup')).to be(true)
|
10
|
+
expect(coercer[String].to_boolean('nope')).to be(false)
|
11
|
+
|
12
|
+
expect { coercer[String].to_boolean('1') }.to raise_error
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,27 @@
|
|
1
|
+
shared_examples_for 'Configurable' do
|
2
|
+
describe '.config_name' do
|
3
|
+
subject { described_class.config_name }
|
4
|
+
|
5
|
+
it { should be_instance_of(Symbol) }
|
6
|
+
end
|
7
|
+
|
8
|
+
describe '.config_keys' do
|
9
|
+
subject { described_class.config_keys }
|
10
|
+
|
11
|
+
it { should be_instance_of(Array) }
|
12
|
+
it { should_not be_empty }
|
13
|
+
end
|
14
|
+
|
15
|
+
describe '.config' do
|
16
|
+
subject { described_class.config }
|
17
|
+
|
18
|
+
it { should be_instance_of(Coercible::Configuration) }
|
19
|
+
|
20
|
+
it 'responds to configuration keys' do
|
21
|
+
described_class.config_keys.each do |key|
|
22
|
+
expect(subject).to respond_to(key)
|
23
|
+
expect(subject).to respond_to("#{key}=")
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
data/spec/spec_helper.rb
ADDED
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'coercible'
|
2
|
+
|
3
|
+
include Coercible
|
4
|
+
|
5
|
+
ENV['TZ'] = 'UTC'
|
6
|
+
|
7
|
+
if ENV['COVERAGE']
|
8
|
+
require 'simplecov'
|
9
|
+
SimpleCov.start
|
10
|
+
end
|
11
|
+
|
12
|
+
Dir[File.expand_path('../shared/**/*.rb', __FILE__)].each { |file| require file }
|
13
|
+
|
14
|
+
# This file was generated by the `rspec --init` command. Conventionally, all
|
15
|
+
# specs live under a `spec` directory, which RSpec adds to the `$LOAD_PATH`.
|
16
|
+
# Require this file using `require "spec_helper"` to ensure that it is only
|
17
|
+
# loaded once.
|
18
|
+
#
|
19
|
+
# See http://rubydoc.info/gems/rspec-core/RSpec/Core/Configuration
|
20
|
+
RSpec.configure do |config|
|
21
|
+
config.treat_symbols_as_metadata_keys_with_true_values = true
|
22
|
+
config.run_all_when_everything_filtered = true
|
23
|
+
config.filter_run :focus
|
24
|
+
|
25
|
+
# Run specs in random order to surface order dependencies. If you find an
|
26
|
+
# order dependency and want to debug it, you can fix the order by providing
|
27
|
+
# the seed, which is printed after each run.
|
28
|
+
# --seed 1234
|
29
|
+
config.order = 'random'
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Array, '#to_set' do
|
4
|
+
subject { object.to_set(array) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:array) { [ 'a', 1, 'b', 2, 'b', 1, 'a', 2 ] }
|
8
|
+
|
9
|
+
it { should be_instance_of(Set) }
|
10
|
+
|
11
|
+
it { should eql(Set[ 'a', 1, 'b', 2 ]) }
|
12
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer, '.new' do
|
4
|
+
subject { described_class.new(&block) }
|
5
|
+
|
6
|
+
let(:block) { Proc.new {} }
|
7
|
+
|
8
|
+
it { should be_instance_of(Coercer) }
|
9
|
+
|
10
|
+
its(:config) { should be_instance_of(Coercible::Configuration) }
|
11
|
+
its(:config) { should respond_to(:string) }
|
12
|
+
its(:config) { should respond_to(:string=) }
|
13
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Date, '.to_datetime' do
|
4
|
+
subject { object.to_datetime(date) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:date) { Date.new(2011, 1, 1) }
|
8
|
+
|
9
|
+
context 'when Date does not support #to_datetime' do
|
10
|
+
if RUBY_VERSION < '1.9'
|
11
|
+
before do
|
12
|
+
date.should_not respond_to(:to_datetime)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it { should be_instance_of(DateTime) }
|
17
|
+
|
18
|
+
it { should eql(DateTime.new(2011, 1, 1)) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when Date supports #to_datetime' do
|
22
|
+
let(:datetime) { DateTime.new(2011, 1, 1) }
|
23
|
+
|
24
|
+
before do
|
25
|
+
date.stub!(:to_datetime).and_return(datetime)
|
26
|
+
end
|
27
|
+
|
28
|
+
it { should equal(datetime) }
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Date, '.to_string' do
|
4
|
+
subject { object.to_string(date) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:date) { Date.new(2011, 1, 1) }
|
8
|
+
|
9
|
+
it { should be_instance_of(String) }
|
10
|
+
|
11
|
+
it { should eql('2011-01-01') }
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Date, '.to_time' do
|
4
|
+
subject { object.to_time(date) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:date) { Date.new(2011, 1, 1) }
|
8
|
+
|
9
|
+
it { should be_instance_of(Time) }
|
10
|
+
|
11
|
+
it { should eql(Time.local(2011, 1, 1)) }
|
12
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::DateTime, '.to_date' do
|
4
|
+
subject { object.to_date(date_time) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:date_time) { DateTime.new(2011, 1, 1) }
|
8
|
+
|
9
|
+
context 'when DateTime does not support #to_date' do
|
10
|
+
if RUBY_VERSION < '1.9'
|
11
|
+
before do
|
12
|
+
date_time.should_not respond_to(:to_date)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it { should be_instance_of(Date) }
|
17
|
+
|
18
|
+
it { should eql(Date.new(2011, 1, 1)) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when DateTime supports #to_date' do
|
22
|
+
let(:date) { Date.new(2011, 1, 1) }
|
23
|
+
|
24
|
+
before do
|
25
|
+
date_time.stub!(:to_date).and_return(date)
|
26
|
+
end
|
27
|
+
|
28
|
+
it { should equal(date) }
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::DateTime, '.to_string' do
|
4
|
+
subject { object.to_string(date_time) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:date_time) { DateTime.new(2011, 1, 1, 0, 0, 0, 0) }
|
8
|
+
|
9
|
+
it { should be_instance_of(String) }
|
10
|
+
|
11
|
+
it { should eql('2011-01-01T00:00:00+00:00') }
|
12
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::DateTime, '.to_time' do
|
4
|
+
subject { object.to_time(date_time) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:date_time) { DateTime.new(2011, 1, 1) }
|
8
|
+
|
9
|
+
context 'when DateTime does not support #to_time' do
|
10
|
+
if RUBY_VERSION < '1.9'
|
11
|
+
before do
|
12
|
+
date_time.should_not respond_to(:to_time)
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
it { should be_instance_of(Time) }
|
17
|
+
|
18
|
+
it { should eql(Time.local(2011, 1, 1)) }
|
19
|
+
end
|
20
|
+
|
21
|
+
context 'when DateTime supports #to_time' do
|
22
|
+
let(:time) { Time.local(2011, 1, 1) }
|
23
|
+
|
24
|
+
before do
|
25
|
+
date_time.stub!(:to_time).and_return(time)
|
26
|
+
end
|
27
|
+
|
28
|
+
it { should equal(time) }
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Decimal, '.to_float' do
|
4
|
+
subject { object.to_float(big_decimal) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:big_decimal) { BigDecimal('1.0') }
|
8
|
+
|
9
|
+
it { should be_instance_of(Float) }
|
10
|
+
|
11
|
+
it { should eql(1.0) }
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Decimal, '.to_integer' do
|
4
|
+
subject { object.to_integer(big_decimal) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:big_decimal) { BigDecimal('1.0') }
|
8
|
+
|
9
|
+
it { should be_kind_of(Integer) }
|
10
|
+
|
11
|
+
it { should eql(1) }
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Decimal, '.to_string' do
|
4
|
+
subject { object.to_string(big_decimal) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:big_decimal) { BigDecimal('1.0') }
|
8
|
+
|
9
|
+
it { should be_instance_of(String) }
|
10
|
+
|
11
|
+
it { should eql('1.0') }
|
12
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer, '#[]' do
|
4
|
+
subject { object[type] }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
|
8
|
+
context "with a known type" do
|
9
|
+
let(:type) { ::String }
|
10
|
+
|
11
|
+
it { should be_instance_of(Coercer::String) }
|
12
|
+
end
|
13
|
+
|
14
|
+
context "with an unknown type" do
|
15
|
+
let(:type) { Object }
|
16
|
+
|
17
|
+
it { should be_instance_of(Coercer::Object) }
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::FalseClass, '.to_string' do
|
4
|
+
subject { object.to_string(false_class) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:false_class) { false }
|
8
|
+
|
9
|
+
it { should be_instance_of(String) }
|
10
|
+
|
11
|
+
it { should eql('false') }
|
12
|
+
end
|
@@ -0,0 +1,12 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Float, '.to_decimal' do
|
4
|
+
subject { object.to_decimal(float) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
let(:float) { 1.0 }
|
8
|
+
|
9
|
+
it { should be_instance_of(BigDecimal) }
|
10
|
+
|
11
|
+
it { should eql(BigDecimal('1.0')) }
|
12
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Hash, '.to_date' do
|
4
|
+
subject { object.to_date(hash) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
|
8
|
+
context 'when time segments are missing' do
|
9
|
+
let(:time_now) { Time.local(2011, 1, 1) }
|
10
|
+
let(:hash) { {} }
|
11
|
+
|
12
|
+
before do
|
13
|
+
Time.stub!(:now).and_return(time_now) # freeze time
|
14
|
+
end
|
15
|
+
|
16
|
+
it { should be_instance_of(Date) }
|
17
|
+
|
18
|
+
it 'uses the Time now to populate the segments' do
|
19
|
+
should eql(Date.new(2011, 1, 1))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when time segments are integers' do
|
24
|
+
let(:hash) { { :year => 2011, :month => 1, :day => 1 } }
|
25
|
+
|
26
|
+
it { should be_instance_of(Date) }
|
27
|
+
|
28
|
+
it { should eql(Date.new(2011, 1, 1)) }
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when time segments are strings' do
|
32
|
+
let(:hash) { { :year => '2011', :month => '1', :day => '1' } }
|
33
|
+
|
34
|
+
it { should be_instance_of(Date) }
|
35
|
+
|
36
|
+
it { should eql(Date.new(2011, 1, 1)) }
|
37
|
+
end
|
38
|
+
end
|
@@ -0,0 +1,38 @@
|
|
1
|
+
require 'spec_helper'
|
2
|
+
|
3
|
+
describe Coercer::Hash, '.to_datetime' do
|
4
|
+
subject { object.to_datetime(hash) }
|
5
|
+
|
6
|
+
let(:object) { described_class.new }
|
7
|
+
|
8
|
+
context 'when time segments are missing' do
|
9
|
+
let(:time_now) { Time.local(2011, 1, 1) }
|
10
|
+
let(:hash) { {} }
|
11
|
+
|
12
|
+
before do
|
13
|
+
Time.stub!(:now).and_return(time_now) # freeze time
|
14
|
+
end
|
15
|
+
|
16
|
+
it { should be_instance_of(DateTime) }
|
17
|
+
|
18
|
+
it 'uses the Time now to populate the segments' do
|
19
|
+
should eql(DateTime.new(2011, 1, 1))
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
context 'when time segments are integers' do
|
24
|
+
let(:hash) { { :year => 2011, :month => 1, :day => 1, :hour => 1, :min => 1, :sec => 1 } }
|
25
|
+
|
26
|
+
it { should be_instance_of(DateTime) }
|
27
|
+
|
28
|
+
it { should eql(DateTime.new(2011, 1, 1, 1, 1, 1)) }
|
29
|
+
end
|
30
|
+
|
31
|
+
context 'when time segments are strings' do
|
32
|
+
let(:hash) { { :year => '2011', :month => '1', :day => '1', :hour => '1', :min => '1', :sec => '1' } }
|
33
|
+
|
34
|
+
it { should be_instance_of(DateTime) }
|
35
|
+
|
36
|
+
it { should eql(DateTime.new(2011, 1, 1, 1, 1, 1)) }
|
37
|
+
end
|
38
|
+
end
|