coercible 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (99) hide show
  1. data/.gitignore +18 -0
  2. data/.rspec +2 -0
  3. data/.travis.yml +19 -0
  4. data/Changelog.md +4 -0
  5. data/Gemfile +6 -0
  6. data/Gemfile.devtools +44 -0
  7. data/Guardfile +58 -0
  8. data/LICENSE.txt +22 -0
  9. data/README.md +64 -0
  10. data/Rakefile +2 -0
  11. data/coercible.gemspec +22 -0
  12. data/config/flay.yml +3 -0
  13. data/config/flog.yml +2 -0
  14. data/config/mutant.yml +3 -0
  15. data/config/roodi.yml +17 -0
  16. data/config/site.reek +91 -0
  17. data/config/yardstick.yml +2 -0
  18. data/lib/coercible.rb +42 -0
  19. data/lib/coercible/coercer.rb +155 -0
  20. data/lib/coercible/coercer/array.rb +24 -0
  21. data/lib/coercible/coercer/configurable.rb +54 -0
  22. data/lib/coercible/coercer/date.rb +27 -0
  23. data/lib/coercible/coercer/date_time.rb +27 -0
  24. data/lib/coercible/coercer/decimal.rb +41 -0
  25. data/lib/coercible/coercer/false_class.rb +25 -0
  26. data/lib/coercible/coercer/float.rb +40 -0
  27. data/lib/coercible/coercer/hash.rb +72 -0
  28. data/lib/coercible/coercer/integer.rb +130 -0
  29. data/lib/coercible/coercer/numeric.rb +67 -0
  30. data/lib/coercible/coercer/object.rb +160 -0
  31. data/lib/coercible/coercer/string.rb +251 -0
  32. data/lib/coercible/coercer/symbol.rb +25 -0
  33. data/lib/coercible/coercer/time.rb +41 -0
  34. data/lib/coercible/coercer/time_coercions.rb +87 -0
  35. data/lib/coercible/coercer/true_class.rb +25 -0
  36. data/lib/coercible/configuration.rb +33 -0
  37. data/lib/coercible/version.rb +3 -0
  38. data/lib/support/options.rb +113 -0
  39. data/lib/support/type_lookup.rb +113 -0
  40. data/spec/integration/configuring_coercers_spec.rb +14 -0
  41. data/spec/shared/unit/configurable.rb +27 -0
  42. data/spec/spec_helper.rb +30 -0
  43. data/spec/unit/coercible/coercer/array/to_set_spec.rb +12 -0
  44. data/spec/unit/coercible/coercer/class_methods/new_spec.rb +13 -0
  45. data/spec/unit/coercible/coercer/date/to_date_spec.rb +10 -0
  46. data/spec/unit/coercible/coercer/date/to_datetime_spec.rb +30 -0
  47. data/spec/unit/coercible/coercer/date/to_string_spec.rb +12 -0
  48. data/spec/unit/coercible/coercer/date/to_time_spec.rb +12 -0
  49. data/spec/unit/coercible/coercer/date_time/to_date_spec.rb +30 -0
  50. data/spec/unit/coercible/coercer/date_time/to_datetime_spec.rb +10 -0
  51. data/spec/unit/coercible/coercer/date_time/to_string_spec.rb +12 -0
  52. data/spec/unit/coercible/coercer/date_time/to_time_spec.rb +30 -0
  53. data/spec/unit/coercible/coercer/decimal/to_decimal_spec.rb +9 -0
  54. data/spec/unit/coercible/coercer/decimal/to_float_spec.rb +12 -0
  55. data/spec/unit/coercible/coercer/decimal/to_integer_spec.rb +12 -0
  56. data/spec/unit/coercible/coercer/decimal/to_string_spec.rb +12 -0
  57. data/spec/unit/coercible/coercer/element_reference_spec.rb +19 -0
  58. data/spec/unit/coercible/coercer/false_class/to_string_spec.rb +12 -0
  59. data/spec/unit/coercible/coercer/float/to_decimal_spec.rb +12 -0
  60. data/spec/unit/coercible/coercer/float/to_float_spec.rb +9 -0
  61. data/spec/unit/coercible/coercer/float/to_integer_spec.rb +12 -0
  62. data/spec/unit/coercible/coercer/float/to_string_spec.rb +12 -0
  63. data/spec/unit/coercible/coercer/hash/to_date_spec.rb +38 -0
  64. data/spec/unit/coercible/coercer/hash/to_datetime_spec.rb +38 -0
  65. data/spec/unit/coercible/coercer/hash/to_time_spec.rb +38 -0
  66. data/spec/unit/coercible/coercer/integer/to_boolean_spec.rb +27 -0
  67. data/spec/unit/coercible/coercer/integer/to_decimal_spec.rb +12 -0
  68. data/spec/unit/coercible/coercer/integer/to_float_spec.rb +12 -0
  69. data/spec/unit/coercible/coercer/integer/to_integer_spec.rb +9 -0
  70. data/spec/unit/coercible/coercer/integer/to_string_spec.rb +12 -0
  71. data/spec/unit/coercible/coercer/integer_spec.rb +11 -0
  72. data/spec/unit/coercible/coercer/numeric/to_decimal_spec.rb +10 -0
  73. data/spec/unit/coercible/coercer/numeric/to_float_spec.rb +10 -0
  74. data/spec/unit/coercible/coercer/numeric/to_integer_spec.rb +10 -0
  75. data/spec/unit/coercible/coercer/numeric/to_string_spec.rb +12 -0
  76. data/spec/unit/coercible/coercer/object/to_array_spec.rb +51 -0
  77. data/spec/unit/coercible/coercer/object/to_hash_spec.rb +22 -0
  78. data/spec/unit/coercible/coercer/object/to_integer_spec.rb +22 -0
  79. data/spec/unit/coercible/coercer/object/to_string_spec.rb +22 -0
  80. data/spec/unit/coercible/coercer/string/to_boolean_spec.rb +31 -0
  81. data/spec/unit/coercible/coercer/string/to_constant_spec.rb +49 -0
  82. data/spec/unit/coercible/coercer/string/to_date_spec.rb +25 -0
  83. data/spec/unit/coercible/coercer/string/to_datetime_spec.rb +52 -0
  84. data/spec/unit/coercible/coercer/string/to_decimal_spec.rb +47 -0
  85. data/spec/unit/coercible/coercer/string/to_float_spec.rb +57 -0
  86. data/spec/unit/coercible/coercer/string/to_integer_spec.rb +68 -0
  87. data/spec/unit/coercible/coercer/string/to_symbol_spec.rb +9 -0
  88. data/spec/unit/coercible/coercer/string/to_time_spec.rb +52 -0
  89. data/spec/unit/coercible/coercer/string_spec.rb +11 -0
  90. data/spec/unit/coercible/coercer/symbol/to_string_spec.rb +12 -0
  91. data/spec/unit/coercible/coercer/time/to_integer_spec.rb +10 -0
  92. data/spec/unit/coercible/coercer/time/to_time_spec.rb +10 -0
  93. data/spec/unit/coercible/coercer/time_coercions/to_date_spec.rb +30 -0
  94. data/spec/unit/coercible/coercer/time_coercions/to_datetime_spec.rb +34 -0
  95. data/spec/unit/coercible/coercer/time_coercions/to_string_spec.rb +19 -0
  96. data/spec/unit/coercible/coercer/time_coercions/to_time_spec.rb +34 -0
  97. data/spec/unit/coercible/coercer/true_class/to_string_spec.rb +12 -0
  98. data/spec/unit/coercible/configuration/class_methods/build_spec.rb +15 -0
  99. 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
@@ -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,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coercer::Date, '.to_date' do
4
+ subject { object.to_date(date) }
5
+
6
+ let(:object) { described_class.new }
7
+ let(:date) { Date.new(2012, 1, 1) }
8
+
9
+ it { should equal(date) }
10
+ 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,10 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coercer::DateTime, '.to_datetime' do
4
+ subject { object.to_datetime(date_time) }
5
+
6
+ let(:object) { described_class.new }
7
+ let(:date_time) { DateTime.new(2012, 1, 1) }
8
+
9
+ it { should equal(date_time) }
10
+ 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,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coercer::Decimal, '.to_decimal' do
4
+ subject { described_class.new.to_decimal(value) }
5
+
6
+ let(:value) { BigDecimal('1.0') }
7
+
8
+ it { should be(value) }
9
+ 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,9 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coercer::Float, '.to_float' do
4
+ subject { described_class.new.to_float(value) }
5
+
6
+ let(:value) { 1.0 }
7
+
8
+ it { should be(value) }
9
+ end
@@ -0,0 +1,12 @@
1
+ require 'spec_helper'
2
+
3
+ describe Coercer::Float, '.to_integer' do
4
+ subject { object.to_integer(float) }
5
+
6
+ let(:object) { described_class.new }
7
+ let(:float) { 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::Float, '.to_string' do
4
+ subject { object.to_string(float) }
5
+
6
+ let(:object) { described_class.new }
7
+ let(:float) { 1.0 }
8
+
9
+ it { should be_instance_of(String) }
10
+
11
+ it { should eql('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