smooth_operator 1.10.6 → 1.10.9

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 CHANGED
@@ -1,15 +1,15 @@
1
1
  ---
2
2
  !binary "U0hBMQ==":
3
3
  metadata.gz: !binary |-
4
- MjFkNjcxMjZmMWFkYzYzY2E1NWE3ZDA5ODdkYzJmYTkwMWZhZTExOA==
4
+ NTYxNDdmNGJiNTIzZWU5YTc2MzlmYTkzYTJjOTZjOTcyZWU5YjMwMg==
5
5
  data.tar.gz: !binary |-
6
- ODBjZTE5NzQwNDU0MmQwY2M0MGQ1ZWZmM2VhNmM0YThmNDQ4Y2U3MA==
6
+ YjlhYzNiNWUwNDdiYjUyOTMyNDY2YjhmYmM3YmE0YzNlM2I2MTBjZQ==
7
7
  SHA512:
8
8
  metadata.gz: !binary |-
9
- NDc2OTA2NWFkZTBkN2I5Y2FiNGEwNDQ2YTAyNTg0NDc4ZDYxYWMwYTk2Y2Y3
10
- YzY3ZTVlZDUwNjNlNDEzMjc3NGM4YThjODZkYjNiYTZmY2EzYTA4MzMxYjg0
11
- MDQxM2Y4ZDA0NGRmNTUwNjRhOTExZWQ4YjY5NDhiZDhkYzllNzk=
9
+ NTQwNzAxYTExZDA0ZjE3YWMwNDJhMDljZjRkMWU3OTFlNzgzNWU4ODliN2Ez
10
+ MzI2NjUyZDMyYjdlYjJmYThkOGUzN2NlYjkxMTc1ODNiMGUyNmJiNzdkMjdl
11
+ OTVhYjAwNDlhZTliNDA4ODE1ODM1NWY5NzIwYTExN2MyOWZjNTQ=
12
12
  data.tar.gz: !binary |-
13
- MzMyODcyNTZhZDY1MzE3MWUzNDg1NjI0NzRmODEyN2NiMWViMmNhZTdkZmQ3
14
- M2EzOTlhZmZkMjQ5ZDkyYjAzODIyYmQ5MzM3NTQ2ZGM2YmRiMzlmZGJhZTll
15
- ZWNhMDBmMGNlYjA3NTFlNGU2ZjAyYmE3YjQ4NWY1ZmM1YzgxZGM=
13
+ YTc1ODM3MmZlNmFjOGM0ZjYzNjc3ZTA0MmE1NGRlNzkyOWQzM2NiNmM5MTc2
14
+ YjE0ZDg5YjcxNWY1ODk4ODE5ZjNkZWMyOWVmNWZlNzE5MTRiMTdmOTY1MmYz
15
+ MTVlMDBhZGQyNjg1ZDNjMGJjM2I1YmE4MmY5OWFkZGNiNDg2Zjk=
@@ -10,10 +10,11 @@ module SmoothOperator
10
10
 
11
11
  def_delegators :internal_array, :length, :<<, :[]
12
12
 
13
- def initialize(attributes, table_name, object_class)
13
+ def initialize(attributes, object_class)
14
14
  _attributes = attributes.dup
15
15
 
16
- @table_name, @object_class = table_name, object_class
16
+ @object_class = object_class
17
+ @table_name = object_class.table_name
17
18
 
18
19
  @internal_array = [*_attributes[table_name]].map { |array_entry| object_class.new(array_entry).tap { |object| object.reloaded = true } }
19
20
  _attributes.delete(table_name)
@@ -1,5 +1,6 @@
1
1
  require 'smooth_operator/attributes/base'
2
2
  require 'smooth_operator/attributes/dirty'
3
+ require 'smooth_operator/attributes/normal'
3
4
 
4
5
  module SmoothOperator
5
6
 
@@ -44,20 +45,44 @@ module SmoothOperator
44
45
  end
45
46
 
46
47
 
47
- def initialize(attributes = {})
48
- before_initialize(attributes)
48
+ def initialize(attributes = {}, options = {})
49
+ @_options = {}
49
50
 
50
- assign_attributes attributes
51
+ before_initialize(attributes, options)
51
52
 
52
- after_initialize(attributes)
53
+ assign_attributes attributes, options
54
+
55
+ after_initialize(attributes, options)
53
56
  end
54
57
 
55
- def assign_attributes(attributes = {})
56
- return nil unless attributes.is_a?(Hash)
58
+ attr_reader :_options, :_meta_data
59
+
60
+
61
+ def assign_attributes(_attributes = {}, options = {})
62
+ return nil unless _attributes.is_a?(Hash)
63
+
64
+ attributes = _attributes = Helpers.stringify_keys(_attributes)
65
+
66
+ if _attributes.include?(model_name)
67
+ attributes = _attributes.delete(model_name)
68
+ @_meta_data = _attributes
69
+ end
57
70
 
71
+ options.each { |key, value| @_options[key] = value } if options.is_a?(Hash)
72
+
58
73
  attributes.each { |name, value| push_to_internal_data(name, value) }
59
74
  end
60
75
 
76
+ def parent_object
77
+ _options[:parent_object]
78
+ end
79
+
80
+ def has_data_from_server
81
+ _options[:from_server] == true
82
+ end
83
+
84
+ alias :from_server :has_data_from_server
85
+
61
86
  def internal_data
62
87
  @internal_data ||= {}
63
88
  end
@@ -91,9 +116,9 @@ module SmoothOperator
91
116
 
92
117
  protected #################### PROTECTED METHODS DOWN BELOW ######################
93
118
 
94
- def before_initialize(attributes); end
119
+ def before_initialize(attributes, options); end
95
120
 
96
- def after_initialize(attributes); end
121
+ def after_initialize(attributes, options); end
97
122
 
98
123
  def allowed_attribute(attribute)
99
124
  if !self.class.attributes_white_list.empty?
@@ -116,16 +141,16 @@ module SmoothOperator
116
141
 
117
142
  def update_internal_data(attribute_name, attribute_value)
118
143
  if self.class.dirty_attributes?
119
- internal_data[attribute_name].set_value(attribute_value)
144
+ internal_data[attribute_name].set_value(attribute_value, self.class.unknown_hash_class, self)
120
145
  else
121
146
  internal_data[attribute_name] = new_attribute_object(attribute_name, attribute_value).value
122
147
  end
123
148
  end
124
149
 
125
150
  def new_attribute_object(attribute_name, attribute_value)
126
- attribute_class = self.class.dirty_attributes? ? Attributes::Dirty : Attributes::Base
151
+ attribute_class = self.class.dirty_attributes? ? Attributes::Dirty : Attributes::Normal
127
152
 
128
- attribute_class.new(attribute_name, attribute_value, internal_structure[attribute_name], self.class.unknown_hash_class)
153
+ attribute_class.new(attribute_name, attribute_value, internal_structure[attribute_name], self.class.unknown_hash_class, self)
129
154
  end
130
155
 
131
156
  end
@@ -1,14 +1,100 @@
1
- require 'smooth_operator/type_converter'
2
-
3
1
  module SmoothOperator
4
2
  module Attributes
5
3
 
6
4
  class Base
7
5
 
8
- attr_reader :value
6
+ protected ##################### PROTECTED ########################
7
+
8
+ def cast_to_type(name, value, type, unknown_hash_class, parent_object)
9
+ case value
10
+ when Array
11
+ value.map { |array_entry| self.class.new(name, array_entry, type, unknown_hash_class, parent_object).value }
12
+ when Hash
13
+ type.nil? ? new_unknown_hash(value, unknown_hash_class, parent_object) : type.new(value, parent_object: parent_object)
14
+ else
15
+ convert(value, type)
16
+ end
17
+ end
18
+
19
+ def convert(value, type)
20
+ case type
21
+
22
+ when :string, :text, String
23
+ value.to_s
24
+
25
+ when :int, :integer, Integer, Fixnum
26
+ to_int(value)
27
+
28
+ when :date, Date
29
+ to_date(value)
30
+
31
+ when :float, Float
32
+ to_float(value)
33
+
34
+ when :bool, :boolean
35
+ to_boolean(value)
36
+
37
+ when :datetime, :date_time, DateTime
38
+ to_datetime(value)
39
+
40
+ else
41
+ Helpers.duplicate(value)
42
+ end
43
+ end
44
+
45
+ def to_int(string)
46
+ return string if string.is_a?(Fixnum)
47
+
48
+ to_float(string).to_i
49
+ end
50
+
51
+ def to_date(string)
52
+ return string if string.is_a?(Date)
53
+
54
+ Date.parse(string) rescue nil
55
+ end
56
+
57
+ def to_datetime(string)
58
+ return string if string.is_a?(DateTime)
59
+
60
+ DateTime.parse(string) rescue nil
61
+ end
62
+
63
+ def to_boolean(string)
64
+ value = string.to_s.downcase
65
+
66
+ ['1', 'true'].include?(value) ? true : ['0', 'false'].include?(value) ? false : nil
67
+ end
68
+
69
+ def to_float(string)
70
+ return string if string.is_a?(Float)
71
+
72
+ return 0 if string.nil? || !string.is_a?(String)
73
+
74
+ value = string.scan(/-*\d+[,.]*\d*/).flatten.map(&:to_f).first
75
+
76
+ value.nil? ? 0 : value
77
+ end
78
+
79
+ def new_unknown_hash(hash, unknown_hash_class, parent_object)
80
+ if unknown_hash_class == :none
81
+ hash
82
+ else
83
+ unknown_hash_class.new(cast_params(hash, unknown_hash_class, parent_object))
84
+ end
85
+ end
86
+
87
+
88
+ private ################### PRIVATE #####################
89
+
90
+ def cast_params(attributes, unknown_hash_class, parent_object)
91
+ hash = {}
92
+
93
+ attributes.each do |key, value|
94
+ hash[key] = cast_to_type(key, value, nil, unknown_hash_class, parent_object)
95
+ end
9
96
 
10
- def initialize(name, value, type, unknown_hash_class)
11
- @value = TypeConverter.cast_to_type(name, value, type, self.class, unknown_hash_class)
97
+ hash
12
98
  end
13
99
 
14
100
  end
@@ -1,20 +1,18 @@
1
- require 'smooth_operator/type_converter'
2
-
3
1
  module SmoothOperator
4
2
  module Attributes
5
3
 
6
- class Dirty
4
+ class Dirty < Base
7
5
 
8
- attr_reader :original_name, :original_value, :first_value, :value, :type, :unknown_hash_class
6
+ attr_reader :original_name, :original_value, :first_value, :value, :type
9
7
 
10
- def initialize(name, value, type, unknown_hash_class)
11
- @original_name, @original_value, @type, @unknown_hash_class = name, value, type, unknown_hash_class
8
+ def initialize(name, value, type, unknown_hash_class, parent_object)
9
+ @original_name, @original_value, @type = name, value, type
12
10
 
13
- @first_value = set_value(value)
11
+ @first_value = set_value(value, unknown_hash_class, parent_object)
14
12
  end
15
13
 
16
- def set_value(new_value)
17
- @value = TypeConverter.cast_to_type(original_name, new_value, type, self.class, unknown_hash_class)
14
+ def set_value(new_value, unknown_hash_class, parent_object)
15
+ @value = cast_to_type(original_name, new_value, type, unknown_hash_class, parent_object)
18
16
  end
19
17
 
20
18
  def changed?
@@ -0,0 +1,15 @@
1
+ module SmoothOperator
2
+ module Attributes
3
+
4
+ class Normal < Base
5
+
6
+ attr_reader :value
7
+
8
+ def initialize(name, value, type, unknown_hash_class, parent_object)
9
+ @value = cast_to_type(name, value, type, unknown_hash_class, parent_object)
10
+ end
11
+
12
+ end
13
+
14
+ end
15
+ end
@@ -27,13 +27,15 @@ module SmoothOperator
27
27
 
28
28
  def build_object(parsed_response, options)
29
29
  options ||={}
30
-
31
- table_name = (options[:table_name] || self.table_name).to_s
32
30
 
33
31
  if parsed_response.is_a?(Array)
34
32
  parsed_response.map { |array_entry| build_object(array_entry, options) }
35
33
  elsif parsed_response.is_a?(Hash)
36
- parsed_response.include?(table_name) ? ArrayWithMetaData.new(parsed_response, table_name, self) : new(parsed_response).tap { |object| object.reloaded = true }
34
+ if parsed_response.include?(table_name)
35
+ ArrayWithMetaData.new(parsed_response, self)
36
+ else
37
+ new(parsed_response, from_server: true)
38
+ end
37
39
  else
38
40
  parsed_response
39
41
  end
@@ -12,14 +12,7 @@ module SmoothOperator
12
12
  remote_call = begin
13
13
  set_basic_authentication
14
14
 
15
- response = connection.send(http_verb) do |request|
16
- operator_options.each { |key, value| request.options.send("#{key}=", value) }
17
- options[:headers].each { |key, value| request.headers[key] = value }
18
- params.each { |key, value| request.params[key] = value }
19
-
20
- request.url relative_path
21
- request.body = body
22
- end
15
+ response = connection.send(http_verb, relative_path) { |request| request_configuration(request) }
23
16
 
24
17
  RemoteCall::Faraday.new(response)
25
18
  rescue ::Faraday::Error::ConnectionFailed
@@ -40,6 +33,16 @@ module SmoothOperator
40
33
  connection.basic_auth(endpoint_user, endpoint_pass) if Helpers.present?(endpoint_user)
41
34
  end
42
35
 
36
+ def request_configuration(request)
37
+ operator_options.each { |key, value| request.options.send("#{key}=", value) }
38
+
39
+ options[:headers].each { |key, value| request.headers[key] = value }
40
+
41
+ params.each { |key, value| request.params[key] = value }
42
+
43
+ request.body = body
44
+ end
45
+
43
46
  end
44
47
 
45
48
  end
@@ -27,10 +27,13 @@ module SmoothOperator
27
27
  end
28
28
 
29
29
 
30
- attr_accessor :extra_params, :reloaded, :meta_data
30
+ attr_accessor :extra_params
31
31
 
32
32
  def reload(relative_path = nil, data = {}, options = {})
33
- relative_path = id.to_s if Helpers.blank?(relative_path)
33
+ raise 'UnknownPath' if !respond_to?(:id) || Helpers.blank?(id)
34
+
35
+ relative_path, options = build_relative_path(relative_path, options)
36
+
34
37
  success = {}
35
38
 
36
39
  make_remote_call(:get, relative_path, data, options) do |remote_call|
@@ -52,12 +55,6 @@ module SmoothOperator
52
55
  @destroyed = false
53
56
  end
54
57
 
55
- def reloaded?
56
- return @reloaded if defined?(@reloaded)
57
-
58
- @reloaded = false
59
- end
60
-
61
58
  def persisted?
62
59
  !(new_record? || destroyed?)
63
60
  end
@@ -73,7 +70,7 @@ module SmoothOperator
73
70
  def destroy(relative_path = nil, data = {}, options = {})
74
71
  return false unless persisted?
75
72
 
76
- relative_path = id.to_s if Helpers.blank?(relative_path)
73
+ relative_path, options = build_relative_path(relative_path, options)
77
74
 
78
75
  success = {}
79
76
 
@@ -106,7 +103,7 @@ module SmoothOperator
106
103
  end
107
104
 
108
105
  def update(relative_path, data, options)
109
- relative_path = id.to_s if Helpers.blank?(relative_path)
106
+ relative_path, options = build_relative_path(relative_path, options)
110
107
 
111
108
  success = {}
112
109
 
@@ -120,6 +117,24 @@ module SmoothOperator
120
117
 
121
118
  private ##################### PRIVATE ####################
122
119
 
120
+ def build_relative_path(relative_path, options)
121
+ if Helpers.blank?(relative_path)
122
+ if parent_object.nil?
123
+ relative_path = id.to_s
124
+ else
125
+ options ||= {}
126
+ options[:table_name] = ''
127
+ relative_path = "#{parent_object.send(:rest_relative_path)}/#{table_name}/#{id}"
128
+ end
129
+ end
130
+
131
+ [relative_path, options]
132
+ end
133
+
134
+ def rest_relative_path
135
+ "#{table_name}/#{id}"
136
+ end
137
+
123
138
  def make_remote_call(http_verb, relative_path, data, options)
124
139
  data ||= {}
125
140
  data.merge!(extra_params || {})
@@ -132,16 +147,7 @@ module SmoothOperator
132
147
  returning_data = @last_remote_call.parsed_response
133
148
 
134
149
  if !@last_remote_call.error? && returning_data.is_a?(Hash)
135
- @reloaded = true
136
-
137
- attributes = returning_data
138
-
139
- if returning_data.include?(model_name)
140
- attributes = returning_data.delete(model_name)
141
- @meta_data = returning_data
142
- end
143
-
144
- assign_attributes attributes
150
+ assign_attributes returning_data, from_server: true
145
151
  end
146
152
 
147
153
  yield(remote_call)
@@ -1,3 +1,3 @@
1
1
  module SmoothOperator
2
- VERSION = "1.10.6"
2
+ VERSION = "1.10.9"
3
3
  end
@@ -4,6 +4,36 @@ require "spec_helper"
4
4
  describe SmoothOperator::AttributeAssignment do
5
5
 
6
6
  describe "#assign_attributes" do
7
+
8
+ describe "receiving data from server" do
9
+ subject { User::Base.new }
10
+
11
+ context "when receiving the option 'from_server = true'" do
12
+ before { subject.assign_attributes({}, from_server: true) }
13
+
14
+ it "#has_data_from_server and #from_server should return true" do
15
+ expect(subject.has_data_from_server).to be true
16
+ expect(subject.from_server).to be true
17
+ end
18
+ end
19
+
20
+ context "when receiving a Hash with meta_data on it" do
21
+ before { subject.assign_attributes({ user: attributes_for(:user), status: 1 }) }
22
+
23
+ it "#meta_data should reflect the receiving meta_data" do
24
+ expect(subject._meta_data).to eq({ "status" => 1 })
25
+ end
26
+
27
+ it "subject should NOT contain meta_data" do
28
+ expect{ subject.status }.to raise_error NoMethodError
29
+ end
30
+
31
+ it "subject should contain all other data" do
32
+ expect(subject.attributes).to eq(attributes_for(:user))
33
+ end
34
+ end
35
+
36
+ end
7
37
 
8
38
  describe "white and black list" do
9
39
  subject { UserWithAddressAndPosts::Son.new(attributes_for(:user_with_address_and_posts)) }
@@ -1,5 +1,20 @@
1
1
  require "spec_helper"
2
2
 
3
+ shared_examples_for "finder method" do
4
+ it "it should return a RemoteCall instance with a subject's class instance" do
5
+ expect(user).to be_instance_of(subject)
6
+ end
7
+
8
+ it "the instance class should be populated with the returned hash" do
9
+ expect(user.attributes).to eq(attributes_for(:user_with_address_and_posts))
10
+ end
11
+
12
+ it "#has_data_from_server and #from_server should return true" do
13
+ expect(user.has_data_from_server).to be true
14
+ expect(user.from_server).to be true
15
+ end
16
+ end
17
+
3
18
  describe SmoothOperator::FinderMethods do
4
19
  subject { UserWithAddressAndPosts::Son }
5
20
 
@@ -11,12 +26,22 @@ describe SmoothOperator::FinderMethods do
11
26
 
12
27
  describe ".find" do
13
28
  context "when the server returns a single hash" do
14
- it "it should return a RemoteCall instance with a subject's class instance populated with the returned hash" do
15
- remote_call = subject.find(5)
16
- user = remote_call.object
29
+ let(:user) { subject.find(5).object }
30
+
31
+ it_behaves_like "finder method"
32
+ end
33
+
34
+ context "when the server returns a hash with meta_data" do
35
+ let(:user) { subject.find("5/with_metadata").object }
36
+
37
+ it_behaves_like "finder method"
38
+
39
+ it "#meta_data should reflect the receiving meta_data" do
40
+ expect(user._meta_data).to eq({ "status" => 1 })
41
+ end
17
42
 
18
- expect(user).to be_instance_of(subject)
19
- expect(user.attributes).to eq(attributes_for(:user_with_address_and_posts))
43
+ it "user should NOT contain meta_data" do
44
+ expect{ user.status }.to raise_error NoMethodError
20
45
  end
21
46
  end
22
47
 
@@ -90,6 +90,52 @@ end
90
90
 
91
91
  describe SmoothOperator::Persistence, helpers: :persistence do
92
92
 
93
+ describe "#reload", current: true do
94
+ subject { new_user }
95
+
96
+ context "before calling #reload" do
97
+ it "#has_data_from_server and #from_server should return false" do
98
+ expect(subject.from_server).to be_falsey
99
+ expect(subject.has_data_from_server).to be_falsey
100
+ end
101
+ end
102
+
103
+ context "when subject doesn't has an id" do
104
+ it "it should raise 'UnknownPath'" do
105
+ expect{ subject.reload }.to raise_error 'UnknownPath'
106
+ end
107
+ end
108
+
109
+ context "when subject has an id" do
110
+ before do
111
+ subject.id = 1
112
+ subject.reload
113
+ end
114
+
115
+ it "it should fetch server data" do
116
+ expect(subject.attributes).to eq(attributes_for(:user_with_address_and_posts))
117
+ end
118
+
119
+ it "#has_data_from_server and #from_server should return true" do
120
+ expect(subject.from_server).to be true
121
+ expect(subject.has_data_from_server).to be true
122
+ end
123
+ end
124
+
125
+ context "when calling #reload on a nested object" do
126
+ before do
127
+ subject.id = 1
128
+ subject.reload
129
+ subject.posts.first.reload
130
+ end
131
+
132
+ it "it should fetch server data, with the correct nested REST url" do
133
+ # binding.pry
134
+ expect(subject.posts.first.attributes).to eq({ id: 1, body: 'from_server' })
135
+ end
136
+ end
137
+ end
138
+
93
139
  describe ".create" do
94
140
 
95
141
  subject { created_subject }
@@ -9,8 +9,8 @@ class TestServer < Sinatra::Base
9
9
  end
10
10
 
11
11
 
12
- get '/posts/:id' do
13
- post_data = { id: 1, body: 'test' }
12
+ get '/users/:id/posts/:id' do
13
+ post_data = { id: 1, body: 'from_server' }
14
14
  json post_data
15
15
  end
16
16
 
@@ -54,8 +54,14 @@ class TestServer < Sinatra::Base
54
54
  json FactoryGirl.attributes_for(:user_with_address_and_posts)
55
55
  end
56
56
 
57
+ get '/users/:id/with_metadata' do
58
+ user_data = { user: FactoryGirl.attributes_for(:user_with_address_and_posts), status: 1 }
59
+ json user_data
60
+ end
61
+
62
+
57
63
  put '/users/send_error' do
58
- data_with_error = { id: 1, errors: { first_name: ["can't be blank"] } }
64
+ data_with_error = { id: 1, errors: [{ first_name: ["can't be blank"] }] }
59
65
  json data_with_error
60
66
  end
61
67
 
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: smooth_operator
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.10.6
4
+ version: 1.10.9
5
5
  platform: ruby
6
6
  authors:
7
7
  - João Gonçalves
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-05-07 00:00:00.000000000 Z
11
+ date: 2014-05-08 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -85,6 +85,7 @@ files:
85
85
  - lib/smooth_operator/attribute_assignment.rb
86
86
  - lib/smooth_operator/attributes/base.rb
87
87
  - lib/smooth_operator/attributes/dirty.rb
88
+ - lib/smooth_operator/attributes/normal.rb
88
89
  - lib/smooth_operator/delegation.rb
89
90
  - lib/smooth_operator/finder_methods.rb
90
91
  - lib/smooth_operator/helpers.rb
@@ -102,7 +103,6 @@ files:
102
103
  - lib/smooth_operator/remote_call/typhoeus.rb
103
104
  - lib/smooth_operator/serialization.rb
104
105
  - lib/smooth_operator/translation.rb
105
- - lib/smooth_operator/type_converter.rb
106
106
  - lib/smooth_operator/validations.rb
107
107
  - lib/smooth_operator/version.rb
108
108
  - smooth_operator.gemspec
@@ -1,104 +0,0 @@
1
- module SmoothOperator
2
-
3
- module TypeConverter
4
-
5
- extend self
6
-
7
- def cast_to_type(name, value, type, array_class, unknown_hash_class)
8
- case value
9
- when Array
10
- value.map { |array_entry| array_class.new(name, array_entry, type, unknown_hash_class).value }
11
- when Hash
12
- type.nil? ? new_unknown_hash(value, array_class, unknown_hash_class) : type.new(value)
13
- else
14
- TypeConverter.convert(value, type)
15
- end
16
- end
17
-
18
- def convert(value, type)
19
- case type
20
-
21
- when :string, :text, String
22
- value.to_s
23
-
24
- when :int, :integer, Integer, Fixnum
25
- to_int(value)
26
-
27
- when :date, Date
28
- to_date(value)
29
-
30
- when :float, Float
31
- to_float(value)
32
-
33
- when :bool, :boolean
34
- to_boolean(value)
35
-
36
- when :datetime, :date_time, DateTime
37
- to_datetime(value)
38
-
39
- else
40
- Helpers.duplicate(value)
41
- end
42
- end
43
-
44
- def to_int(string)
45
- return string if string.is_a?(Fixnum)
46
-
47
- to_float(string).to_i
48
- end
49
-
50
- def to_date(string)
51
- return string if string.is_a?(Date)
52
-
53
- Date.parse(string) rescue nil
54
- end
55
-
56
- def to_datetime(string)
57
- return string if string.is_a?(DateTime)
58
-
59
- DateTime.parse(string) rescue nil
60
- end
61
-
62
- def to_boolean(string)
63
- value = string.to_s.downcase
64
-
65
- ['1', 'true'].include?(value) ? true : ['0', 'false'].include?(value) ? false : nil
66
- end
67
-
68
- def to_float(string)
69
- return string if string.is_a?(Float)
70
-
71
- return 0 if string.nil? || !string.is_a?(String)
72
-
73
- value = string.scan(/-*\d+[,.]*\d*/).flatten.map(&:to_f).first
74
-
75
- value.nil? ? 0 : value
76
- end
77
-
78
-
79
- protected ################### PROTECTED #####################
80
-
81
- def new_unknown_hash(hash, array_class, unknown_hash_class)
82
- if unknown_hash_class == :none
83
- hash
84
- else
85
- unknown_hash_class.new(cast_params(hash, array_class, unknown_hash_class))
86
- end
87
- end
88
-
89
-
90
- private ################### PRIVATE #####################
91
-
92
- def cast_params(attributes, array_class, unknown_hash_class)
93
- hash = {}
94
-
95
- attributes.each do |key, value|
96
- hash[key] = cast_to_type(key, value, nil, array_class, unknown_hash_class)
97
- end
98
-
99
- hash
100
- end
101
-
102
- end
103
-
104
- end