sunstone 7.0.0 → 7.1.0.1

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 02df1d75e40c2ef207e6e1f329068c95098f5b99758d1bcea603e157ed2c1f40
4
- data.tar.gz: 4807c8a530f9c7f09448a08bea1dbe015724f2afb53d81b86cf5cef6d6b49dcf
3
+ metadata.gz: 3956ea045dce2994b10bcac8535462bdf08597b85d7e15fc325110149a576aa6
4
+ data.tar.gz: 02be730df372f32557112e9fb618befb5aafd7a8ef15ce1e12a866f8c18c2ed7
5
5
  SHA512:
6
- metadata.gz: e884525eda7c249da0f4decbadff3d27ff97859eac4874e1c20b4b0e10c80d6d96ee49419d27bd2f6d429c55c93485bfe1961451ff8396d101e37752ec39ac6d
7
- data.tar.gz: 4323252706192a940b6f730a6c46324d4c40729df5864a5d1aafc4283764ef159284ddefe9b1335a7d9174b6716d11a2d0da4aa59dbdfbc3ac7cdccc537b06f8
6
+ metadata.gz: c978ff5919d301007ccd326a632ed915cce129584e0ff9c25c199bddb9a65e517361f95a7d3a8af4ea70546acd1bb16fbc1118ff050a0c209f4168f9ec71feb9
7
+ data.tar.gz: 3a24f347b5ca8ccf2816e8d50a28ca3effedea79a897ab3692801b5cd8095d9fc324f37f792ffba621a9669eb7ea92f58be762b62d2a1e9096a9306fc1d46be9
@@ -1,3 +1,5 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
1
3
  module ActiveRecord
2
4
  module Associations
3
5
  class CollectionAssociation
@@ -8,7 +10,7 @@ module ActiveRecord
8
10
 
9
11
  if owner.new_record?
10
12
  replace_records(other_array, original_target)
11
- elsif owner.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@updating) && owner.instance_variable_get(:@updating)
13
+ elsif owner.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@sunstone_updating) && owner.instance_variable_get(:@sunstone_updating)
12
14
  replace_common_records_in_memory(other_array, original_target)
13
15
 
14
16
  # Remove from target
@@ -41,7 +43,7 @@ module ActiveRecord
41
43
  end
42
44
 
43
45
  def insert_record(record, validate = true, raise = false, &block)
44
- if record.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@updating) && owner.instance_variable_get(:@updating)
46
+ if record.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && owner.instance_variable_defined?(:@sunstone_updating) && owner.instance_variable_get(:@sunstone_updating)
45
47
  true
46
48
  elsif raise
47
49
  record.save!(validate: validate, &block)
@@ -70,27 +72,3 @@ module ActiveRecord
70
72
 
71
73
  end
72
74
  end
73
-
74
- module ActiveRecord
75
- module Persistence
76
-
77
- # Updates the attributes of the model from the passed-in hash and saves the
78
- # record, all wrapped in a transaction. If the object is invalid, the saving
79
- # will fail and false will be returned.
80
- def update(attributes)
81
- @updating = :updating
82
- Thread.current[:sunstone_updating_model] = self
83
-
84
- # The following transaction covers any possible database side-effects of the
85
- # attributes assignment. For example, setting the IDs of a child collection.
86
- with_transaction_returning_status do
87
- assign_attributes(attributes)
88
- save
89
- end
90
- ensure
91
- @updating = false
92
- Thread.current[:sunstone_updating_model] = nil
93
- end
94
-
95
- end
96
- end
@@ -1,5 +1,9 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  require 'active_record'
2
5
  require 'active_record/associations'
6
+
3
7
  module ActiveRecord
4
8
  module Associations
5
9
  module ClassMethods
@@ -44,4 +48,4 @@ module ActiveRecord
44
48
  end
45
49
  end
46
50
  end
47
- end
51
+ end
@@ -1,14 +1,15 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  module ActiveRecord
2
5
  module AttributeMethods
3
-
6
+
4
7
  protected
5
-
8
+
6
9
  # Returns a Hash of the Arel::Attributes and attribute values that have been
7
10
  # typecasted for use in an Arel insert/update method.
8
11
  def attributes_with_values(attribute_names)
9
- attrs = attribute_names.index_with do |name|
10
- _read_attribute(name)
11
- end
12
+ attrs = attribute_names.index_with { |name| @attributes[name] }
12
13
 
13
14
  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
14
15
  self.class.reflect_on_all_associations.each do |reflection|
@@ -25,17 +26,17 @@ module ActiveRecord
25
26
  end
26
27
  end
27
28
  end
28
-
29
+
29
30
  attrs
30
31
  end
31
-
32
+
32
33
  def add_attributes_for_belongs_to_association(reflection, attrs)
33
34
  key = :"add_attributes_for_belongs_to_association_#{reflection.name}"
34
35
  @_already_called ||= {}
35
36
  return if @_already_called[key]
36
37
  @_already_called[key]=true
37
38
  @_already_called[:"autosave_associated_records_for_#{reflection.name}"] = true
38
-
39
+
39
40
  association = association_instance_get(reflection.name)
40
41
  record = association && association.load_target
41
42
  if record && !record.destroyed?
@@ -51,14 +52,14 @@ module ActiveRecord
51
52
  end
52
53
  end
53
54
  end
54
-
55
+
55
56
  def add_attributes_for_has_one_association(reflection, attrs)
56
57
  key = :"add_attributes_for_has_one_association#{reflection.name}"
57
58
  @_already_called ||= {}
58
59
  return if @_already_called[key]
59
60
  @_already_called[key]=true
60
61
  @_already_called[:"autosave_associated_records_for_#{reflection.name}"] = true
61
-
62
+
62
63
  association = association_instance_get(reflection.name)
63
64
  record = association && association.load_target
64
65
 
@@ -80,7 +81,7 @@ module ActiveRecord
80
81
  end
81
82
  end
82
83
  end
83
-
84
+
84
85
  def add_attributes_for_collection_association(reflection, attrs, arel_table=nil)
85
86
  key = :"add_attributes_for_collection_association#{reflection.name}"
86
87
  @_already_called ||= {}
@@ -106,7 +107,7 @@ module ActiveRecord
106
107
  )
107
108
  end
108
109
  end
109
-
110
+
110
111
  association.instance_variable_set(:@sunstone_changed, false)
111
112
  end
112
113
 
@@ -114,6 +115,6 @@ module ActiveRecord
114
115
  association.reset_scope if association.respond_to?(:reset_scope)
115
116
  end
116
117
  end
117
-
118
+
118
119
  end
119
120
  end
@@ -1,3 +1,6 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  module ActiveRecord
2
5
  module Callbacks
3
6
  private
@@ -14,4 +17,4 @@ module ActiveRecord
14
17
  end
15
18
 
16
19
  end
17
- end
20
+ end
@@ -1,14 +1,24 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  module ActiveRecord
2
5
  class PredicateBuilder # :nodoc:
3
6
 
4
7
  def expand_from_hash(attributes, &block)
5
8
  return ["1=0"] if attributes.empty?
6
-
9
+
7
10
  attributes.flat_map do |key, value|
8
- if value.is_a?(Hash) && !table.has_column?(key)
11
+ if key.is_a?(Array)
12
+ queries = Array(value).map do |ids_set|
13
+ raise ArgumentError, "Expected corresponding value for #{key} to be an Array" unless ids_set.is_a?(Array)
14
+ expand_from_hash(key.zip(ids_set).to_h)
15
+ end
16
+ grouping_queries(queries)
17
+ elsif value.is_a?(Hash) && !table.has_column?(key)
9
18
  ka = table.associated_table(key, &block)
10
- .predicate_builder.expand_from_hash(value.stringify_keys)
11
- if self.send(:table).instance_variable_get(:@klass).connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
19
+ .predicate_builder.expand_from_hash(value.stringify_keys)
20
+
21
+ if self.table.instance_variable_get(:@klass).connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
12
22
  ka.each { |k|
13
23
  if k.left.is_a?(Arel::Attributes::Attribute) || k.left.is_a?(Arel::Attributes::Relation)
14
24
  k.left = Arel::Attributes::Relation.new(k.left, key)
@@ -6,10 +6,12 @@ module ActiveRecord
6
6
  def rpc(name)
7
7
  define_method("#{name}!") do
8
8
  req = Net::HTTP::Post.new("/#{self.class.table_name}/#{CGI.escape(id.to_s)}/#{CGI.escape(name.to_s)}")
9
- self.class.connection.instance_variable_get(:@connection).send_request(req) do |response|
10
- JSON.parse(response.body).each do |k,v|
11
- if self.class.column_names.include?(k)
12
- @attributes.write_from_database(k, v)
9
+ self.class.connection.send(:with_raw_connection) do |conn|
10
+ conn.send_request(req) do |response|
11
+ JSON.parse(response.body).each do |k,v|
12
+ if self.class.column_names.include?(k)
13
+ @attributes.write_from_database(k, v)
14
+ end
13
15
  end
14
16
  end
15
17
  end
@@ -17,7 +19,25 @@ module ActiveRecord
17
19
  end
18
20
  end
19
21
  end
20
-
22
+
23
+ # Updates the attributes of the model from the passed-in hash and saves the
24
+ # record, all wrapped in a transaction. If the object is invalid, the saving
25
+ # will fail and false will be returned.
26
+ def update(attributes)
27
+ @sunstone_updating = :updating
28
+ Thread.current[:sunstone_updating_model] = self
29
+
30
+ # The following transaction covers any possible database side-effects of the
31
+ # attributes assignment. For example, setting the IDs of a child collection.
32
+ with_transaction_returning_status do
33
+ assign_attributes(attributes)
34
+ save
35
+ end
36
+ ensure
37
+ @sunstone_updating = false
38
+ Thread.current[:sunstone_updating_model] = nil
39
+ end
40
+
21
41
  def update!(attributes)
22
42
  @no_save_transaction = true
23
43
  with_transaction_returning_status do
@@ -33,14 +53,14 @@ module ActiveRecord
33
53
  def create_or_update(**, &block)
34
54
  _raise_readonly_record_error if readonly?
35
55
  return false if destroyed?
36
-
37
- @updating = new_record? ? :creating : :updating
56
+
57
+ @sunstone_updating = new_record? ? :creating : :updating
38
58
  Thread.current[:sunstone_updating_model] = self
39
59
 
40
60
  result = new_record? ? _create_record(&block) : _update_record(&block)
41
61
 
42
62
  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && result != 0
43
- row_hash = result.rows.first
63
+ row_hash = result[0]
44
64
 
45
65
  seen = Hash.new { |h, parent_klass|
46
66
  h[parent_klass] = Hash.new { |i, parent_id|
@@ -51,10 +71,13 @@ module ActiveRecord
51
71
  model_cache = Hash.new { |h,klass| h[klass] = {} }
52
72
  parents = model_cache[self.class.base_class]
53
73
 
54
- self.assign_attributes(row_hash.select{|k,v| self.class.column_names.include?(k.to_s) })
55
- row_hash.select{|k,v| !self.class.column_names.include?(k.to_s) }.each do |relation_name, value|
56
- assc = association(relation_name.to_sym)
57
- assc.reset if assc.reflection.collection?
74
+ row_hash.each do |key, value|
75
+ if self.class.column_names.include?(key.to_s)
76
+ _write_attribute(key, value)
77
+ else
78
+ assc = association(key.to_sym)
79
+ assc.reset if assc.reflection.collection? # TODO: can load here if included
80
+ end
58
81
  end
59
82
 
60
83
  construct(self, row_hash.select{|k,v| !self.class.column_names.include?(k.to_s) }, seen, model_cache)
@@ -72,39 +95,50 @@ module ActiveRecord
72
95
  end
73
96
  raise ActiveRecord::RecordInvalid
74
97
  ensure
75
- @updating = false
98
+ @sunstone_updating = false
76
99
  Thread.current[:sunstone_updating_model] = nil
77
100
  end
78
-
101
+
79
102
  # Creates a record with values matching those of the instance attributes
80
103
  # and returns its id.
81
104
  def _create_record(attribute_names = self.attribute_names)
82
105
  attribute_names = attributes_for_create(attribute_names)
83
- attributes_values = attributes_with_values(attribute_names)
84
-
85
- new_id = self.class._insert_record(attributes_values)
106
+ attribute_values = attributes_with_values(attribute_names)
107
+
108
+ returning_columns = self.class._returning_columns_for_insert
109
+
110
+ returning_values = self.class._insert_record(
111
+ attribute_values,
112
+ returning_columns
113
+ )
114
+
115
+ if !self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
116
+ returning_columns.zip(returning_values).each do |column, value|
117
+ _write_attribute(column, value) if !_read_attribute(column)
118
+ end if returning_values
119
+ end
86
120
 
87
- self.id ||= new_id if @primary_key
88
121
  @new_record = false
89
122
  @previously_new_record = true
90
123
 
91
124
  yield(self) if block_given?
92
125
 
93
126
  if self.class.connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
94
- new_id
127
+ returning_values
95
128
  else
96
129
  id
97
130
  end
98
131
  end
99
-
132
+
100
133
  def _update_record(attribute_names = self.attribute_names)
134
+ attribute_names = attributes_for_update(attribute_names)
101
135
  attribute_values = attributes_with_values(attribute_names)
102
136
 
103
137
  if attribute_values.empty?
104
138
  affected_rows = 0
105
139
  @_trigger_update_callback = true
106
140
  else
107
- affected_rows = self.class._update_record( attribute_values, self.class.primary_key => id_in_database )
141
+ affected_rows = self.class._update_record(attribute_values, _query_constraints_hash)
108
142
  @_trigger_update_callback = affected_rows == 1
109
143
  end
110
144
 
@@ -1,6 +1,9 @@
1
+ # The last ref that this code was synced with Rails
2
+ # ref: 9269f634d471ad6ca46752421eabd3e1c26220b5
3
+
1
4
  module ActiveRecord
2
5
  module Calculations
3
-
6
+
4
7
  def pluck(*column_names)
5
8
  if loaded? && all_attributes?(column_names)
6
9
  return records.pluck(*column_names)
@@ -36,8 +36,8 @@ module ActiveRecord
36
36
  def with_transaction_returning_status
37
37
  status = nil
38
38
  connection = self.class.connection
39
-
40
- if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && instance_variable_defined?(:@updating) && @updating
39
+
40
+ if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter) && instance_variable_defined?(:@sunstone_updating) && @sunstone_updating
41
41
  status = yield
42
42
  else
43
43
  ensure_finalize = !connection.transaction_open?
@@ -2,6 +2,8 @@ module ActiveRecord
2
2
  module ConnectionAdapters
3
3
  # Sunstone-specific extensions to column definitions in a table.
4
4
  class SunstoneColumn < Column #:nodoc:
5
+ NONE = Object.new
6
+
5
7
  attr_reader :array
6
8
 
7
9
  def initialize(name, sql_type_metadata, options={})
@@ -14,12 +16,20 @@ module ActiveRecord
14
16
  @table_name = nil
15
17
  @primary_key = (options['primary_key'] == true)
16
18
  @array = options['array']
19
+ @auto_populated = options.has_key?('auto_populated') ? options['auto_populated'] : NONE
17
20
  end
18
21
 
19
22
  def primary_key?
20
23
  @primary_key
21
24
  end
22
25
 
26
+ def auto_populated?
27
+ # TODO: when retuning is working we can do the following to only
28
+ # return autopulated fields from StandardAPI
29
+ # @auto_populated == NONE ? @primary_key : @auto_populated
30
+ true
31
+ end
32
+
23
33
  end
24
34
  end
25
35
  end
@@ -25,22 +25,35 @@ module ActiveRecord
25
25
  else
26
26
  sar = arel_or_sar_string
27
27
  end
28
+
28
29
  sar.compile(binds)
29
30
  end
30
31
 
31
32
  def to_sar_and_binds(arel_or_sar_string, binds = [], preparable = nil) # :nodoc:
33
+ # Arel::TreeManager -> Arel::Node
32
34
  if arel_or_sar_string.respond_to?(:ast)
35
+ arel_or_sar_string = arel_or_sar_string.ast
36
+ end
37
+
38
+ if Arel.arel_node?(arel_or_sar_string) && !(String === arel_or_sar_string)
33
39
  unless binds.empty?
34
40
  raise "Passing bind parameters with an arel AST is forbidden. " \
35
41
  "The values must be stored on the AST directly"
36
42
  end
37
- sar = visitor.accept(arel_or_sar_string.ast, collector)
43
+
44
+ sar = visitor.accept(arel_or_sar_string, collector)
38
45
  [sar.freeze, sar.binds, false]
39
46
  else
40
47
  [arel_or_sar_string.dup.freeze, binds, false]
41
48
  end
42
49
  end
43
50
 
51
+ def sar_for_insert(sql, pk, binds, returning)
52
+ # TODO: when StandardAPI supports returning we can do this; it might
53
+ # already need to investigate
54
+ to_sar_and_binds(sql, binds)
55
+ end
56
+
44
57
  # This is used in the StatementCache object. It returns an object that
45
58
  # can be used to query the database repeatedly.
46
59
  def cacheable_query(klass, arel) # :nodoc:
@@ -80,11 +93,26 @@ module ActiveRecord
80
93
  def select_all(arel, name = nil, binds = [], preparable: nil, async: false)
81
94
  arel = arel_from_relation(arel)
82
95
  sar, binds, preparable = to_sar_and_binds(arel, binds, preparable)
83
-
96
+
84
97
  select(sar, name, binds, prepare: prepared_statements && preparable, async: async && FutureResult::SelectAll)
98
+ rescue ::RangeError
99
+ ActiveRecord::Result.empty(async: async)
100
+ end
101
+
102
+ # Executes insert +sql+ statement in the context of this connection using
103
+ # +binds+ as the bind substitutes. +name+ is logged along with
104
+ # the executed +sql+ statement.
105
+ # Some adapters support the `returning` keyword argument which allows to control the result of the query:
106
+ # `nil` is the default value and maintains default behavior. If an array of column names is passed -
107
+ # the result will contain values of the specified columns from the inserted row.
108
+ #
109
+ # TODO: Add support for returning
110
+ def exec_insert(arel, name = nil, binds = [], pk = nil, sequence_name = nil, returning: nil)
111
+ sar, binds = sar_for_insert(arel, pk, binds, returning)
112
+ internal_exec_query(sar, name, binds)
85
113
  end
86
114
 
87
- def exec_query(arel, name = 'SAR', binds = [], prepare: false)
115
+ def internal_exec_query(arel, name = 'SAR', binds = [], prepare: false, async: false, allow_retry: false, materialize_transactions: true)
88
116
  sars = []
89
117
  multiple_requests = arel.is_a?(Arel::Collectors::Sunstone)
90
118
  type_casted_binds = binds#type_casted_binds(binds)
@@ -112,11 +140,13 @@ module ActiveRecord
112
140
  sars.push(sar)
113
141
  log_mess = sar.path.split('?', 2)
114
142
  log("#{sar.method} #{log_mess[0]} #{(log_mess[1] && !log_mess[1].empty?) ? MessagePack.unpack(CGI.unescape(log_mess[1])) : '' }", name) do
115
- response = @connection.send_request(sar)
116
- if response.is_a?(Net::HTTPNoContent)
117
- nil
118
- else
119
- JSON.parse(response.body)
143
+ with_raw_connection do |conn|
144
+ response = conn.send_request(sar)
145
+ if response.is_a?(Net::HTTPNoContent)
146
+ nil
147
+ else
148
+ JSON.parse(response.body)
149
+ end
120
150
  end
121
151
  end
122
152
  }
@@ -141,21 +171,21 @@ module ActiveRecord
141
171
 
142
172
  if sars[0].instance_variable_defined?(:@sunstone_calculation) && sars[0].instance_variable_get(:@sunstone_calculation)
143
173
  # this is a count, min, max.... yea i know..
144
- ActiveRecord::Result.new(['all'], [result], {:all => type_map.lookup('integer', {})})
174
+ ActiveRecord::Result.new(['all'], [result], {:all => @type_map.lookup('integer', {})})
145
175
  elsif result.is_a?(Array)
146
176
  ActiveRecord::Result.new(result[0] ? result[0].keys : [], result.map{|r| r.values})
147
177
  else
148
- ActiveRecord::Result.new(result.keys, [result])
178
+ ActiveRecord::Result.new(result.keys, [result.values])
149
179
  end
150
180
  end
151
181
 
152
182
  def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
153
183
  sar, binds = to_sar_and_binds(arel, binds)
154
184
  value = exec_insert(sar, name, binds, pk, sequence_name)
185
+
186
+ return returning_column_values(value) unless returning.nil?
187
+
155
188
  id_value || last_inserted_id(value)
156
-
157
- # value = exec_insert(arel, name, binds, pk, sequence_name)
158
- # id_value || last_inserted_id(value)
159
189
  end
160
190
 
161
191
  def update(arel, name = nil, binds = [])
@@ -171,6 +201,10 @@ module ActiveRecord
171
201
  row && row['id']
172
202
  end
173
203
 
204
+ def returning_column_values(result)
205
+ result.rows.first
206
+ end
207
+
174
208
  end
175
209
  end
176
210
  end
@@ -27,8 +27,7 @@ module ActiveRecord
27
27
  return @definitions[table_name]
28
28
  end
29
29
 
30
- response = @connection.get("/#{table_name}/schema")
31
-
30
+ response = with_raw_connection { |conn| conn.get("/#{table_name}/schema") }
32
31
  @definitions[table_name] = JSON.parse(response.body)
33
32
  rescue ::Sunstone::Exception::NotFound
34
33
  raise ActiveRecord::StatementInvalid, "Table \"#{table_name}\" does not exist"
@@ -40,7 +39,9 @@ module ActiveRecord
40
39
  # - format_type includes the column size constraint, e.g. varchar(50)
41
40
  # - ::regclass is a function that gives the id for a table name
42
41
  def column_definitions(table_name) # :nodoc:
43
- definition(table_name)['columns']
42
+ # TODO: settle on schema, I think we've switched to attributes, so
43
+ # columns can be removed soon?
44
+ definition(table_name)['attributes'] || definition(table_name)['columns']
44
45
  end
45
46
 
46
47
  # Returns the limit definition of the table (the maximum limit that can
@@ -50,7 +51,7 @@ module ActiveRecord
50
51
  end
51
52
 
52
53
  def tables
53
- JSON.parse(@connection.get('/tables').body)
54
+ JSON.parse(with_raw_connection { |conn| conn.get('/tables').body })
54
55
  end
55
56
 
56
57
  def views
@@ -63,7 +64,7 @@ module ActiveRecord
63
64
  end
64
65
 
65
66
  def lookup_cast_type(options)
66
- type_map.lookup(options['type'], options.symbolize_keys)
67
+ @type_map.lookup(options['type'], options.symbolize_keys)
67
68
  end
68
69
 
69
70
  def fetch_type_metadata(options)
@@ -13,11 +13,11 @@ module ActiveRecord
13
13
  #
14
14
  # +value+ The raw input, as provided from the database.
15
15
  def deserialize(value)
16
- value.nil? ? nil : Base64.strict_decode64(value)
16
+ value.nil? ? nil : Base64.strict_decode64(value)
17
17
  end
18
18
 
19
- # Casts a value from the ruby type to a type that the database knows how
20
- # to understand. The returned value from this method should be a
19
+ # Casts a value from the ruby type to a type that the database knows
20
+ # how to understand. The returned value from this method should be a
21
21
  # +String+, +Numeric+, +Date+, +Time+, +Symbol+, +true+, +false+, or
22
22
  # +nil+.
23
23
  def serialize(value)
@@ -17,27 +17,14 @@ require 'active_record/connection_adapters/sunstone/type/json'
17
17
  module ActiveRecord
18
18
  module ConnectionHandling # :nodoc:
19
19
 
20
- VALID_SUNSTONE_CONN_PARAMS = [:url, :host, :port, :api_key, :use_ssl, :user_agent, :ca_cert]
21
-
20
+ def sunstone_adapter_class
21
+ ConnectionAdapters::SunstoneAPIAdapter
22
+ end
23
+
22
24
  # Establishes a connection to the database that's used by all Active Record
23
25
  # objects
24
26
  def sunstone_connection(config)
25
- conn_params = config.symbolize_keys
26
- conn_params.delete_if { |_, v| v.nil? }
27
-
28
- if conn_params[:url]
29
- uri = URI.parse(conn_params.delete(:url))
30
- conn_params[:api_key] ||= (uri.user ? CGI.unescape(uri.user) : nil)
31
- conn_params[:host] ||= uri.host
32
- conn_params[:port] ||= uri.port
33
- conn_params[:use_ssl] ||= (uri.scheme == 'https')
34
- end
35
-
36
- # Forward only valid config params to Sunstone::Connection
37
- conn_params.slice!(*VALID_SUNSTONE_CONN_PARAMS)
38
-
39
- client = ::Sunstone::Connection.new(conn_params)
40
- ConnectionAdapters::SunstoneAPIAdapter.new(client, logger, conn_params, config)
27
+ sunstone_adapter_class.new(config)
41
28
  end
42
29
  end
43
30
 
@@ -54,6 +41,7 @@ module ActiveRecord
54
41
  # <encoding></tt> call on the connection.
55
42
  class SunstoneAPIAdapter < AbstractAdapter
56
43
  ADAPTER_NAME = 'Sunstone'.freeze
44
+ VALID_SUNSTONE_CONN_PARAMS = [:url, :host, :port, :api_key, :use_ssl, :user_agent, :ca_cert]
57
45
 
58
46
  NATIVE_DATABASE_TYPES = {
59
47
  string: { name: "string" },
@@ -61,6 +49,12 @@ module ActiveRecord
61
49
  json: { name: "json" },
62
50
  boolean: { name: "boolean" }
63
51
  }
52
+
53
+ class << self
54
+ def new_client(conn_params)
55
+ ::Sunstone::Connection.new(conn_params)
56
+ end
57
+ end
64
58
 
65
59
  # include PostgreSQL::Quoting
66
60
  # include PostgreSQL::ReferentialIntegrity
@@ -72,35 +66,66 @@ module ActiveRecord
72
66
  def supports_statement_cache?
73
67
  false
74
68
  end
69
+
70
+ def default_prepared_statements
71
+ false
72
+ end
75
73
 
76
- def clear_cache!
74
+ def clear_cache!(new_connection: false)
77
75
  # TODO move @definitions to using @schema_cache
78
76
  @definitions = {}
79
77
  end
80
78
 
81
79
  # Initializes and connects a SunstoneAPI adapter.
82
- def initialize(connection, logger, connection_parameters, config)
83
- super(connection, logger, config.reverse_merge(prepared_statements: false))
80
+ def initialize(...)
81
+ super
84
82
 
85
- @prepared_statement_status = Concurrent::ThreadLocalVar.new(false)
86
- @connection_parameters = connection_parameters
83
+ conn_params = @config.compact
84
+ if conn_params[:url]
85
+ uri = URI.parse(conn_params.delete(:url))
86
+ conn_params[:api_key] ||= (uri.user ? CGI.unescape(uri.user) : nil)
87
+ conn_params[:host] ||= uri.host
88
+ conn_params[:port] ||= uri.port
89
+ conn_params[:use_ssl] ||= (uri.scheme == 'https')
90
+ end
87
91
 
88
- @type_map = Type::HashLookupTypeMap.new
89
- initialize_type_map(@type_map)
92
+ # Forward only valid config params to Sunstone::Connection
93
+ conn_params.slice!(*VALID_SUNSTONE_CONN_PARAMS)
94
+
95
+ @connection_parameters = conn_params
96
+
97
+ @max_identifier_length = nil
98
+ @type_map = nil
99
+ @raw_connection = nil
100
+ end
101
+
102
+ def url(path=nil)
103
+ "http#{@connection_parameters[:use_ssl] ? 's' : ''}://#{@connection_parameters[:host]}#{@connection_parameters[:port] != 80 ? (@connection_parameters[:port] == 443 && @connection_parameters[:use_ssl] ? '' : ":#{@connection_parameters[:port]}") : ''}#{path}"
90
104
  end
91
105
 
92
106
  def active?
93
- @connection.active?
107
+ @raw_connection&.active?
94
108
  end
95
109
 
96
- def reconnect!
110
+ def load_type_map
111
+ @type_map = Type::HashLookupTypeMap.new
112
+ initialize_type_map(@type_map)
113
+ end
114
+
115
+ def reconnect
97
116
  super
98
- @connection.reconnect!
117
+ @raw_connection&.reconnect!
99
118
  end
100
119
 
101
120
  def disconnect!
102
121
  super
103
- @connection.disconnect!
122
+ @raw_connection&.disconnect!
123
+ @raw_connection = nil
124
+ end
125
+
126
+ def discard! # :nodoc:
127
+ super
128
+ @raw_connection = nil
104
129
  end
105
130
 
106
131
  # Executes the delete statement and returns the number of rows affected.
@@ -134,11 +159,17 @@ module ActiveRecord
134
159
  end
135
160
 
136
161
  def server_config
137
- JSON.parse(@connection.get("/configuration").body)
162
+ with_raw_connection do |conn|
163
+ JSON.parse(conn.get("/configuration").body)
164
+ end
165
+ end
166
+
167
+ def return_value_after_insert?(column) # :nodoc:
168
+ column.auto_populated?
138
169
  end
139
170
 
140
171
  def lookup_cast_type_from_column(column) # :nodoc:
141
- cast_type = type_map.lookup(column.sql_type, {
172
+ cast_type = @type_map.lookup(column.sql_type, {
142
173
  limit: column.limit,
143
174
  precision: column.precision,
144
175
  scale: column.scale
@@ -167,55 +198,63 @@ module ActiveRecord
167
198
  true
168
199
  end
169
200
 
170
- # Executes an INSERT query and returns the new record's ID
171
- #
172
- # +id_value+ will be returned unless the value is nil, in
173
- # which case the database will attempt to calculate the last inserted
174
- # id and return that value.
175
- #
176
- # If the next id was calculated in advance (as in Oracle), it should be
177
- # passed in as +id_value+.
178
- def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [])
179
- exec_insert(arel, name, binds, pk, sequence_name)
201
+ # Executes an INSERT query and returns a hash of the object and
202
+ # any updated relations. This is different from AR which returns an ID
203
+ def insert(arel, name = nil, pk = nil, id_value = nil, sequence_name = nil, binds = [], returning: nil)
204
+ exec_insert(arel, name, binds, pk, sequence_name, returning: returning)
180
205
  end
181
206
  alias create insert
182
207
 
183
- def reload_type_map
184
- type_map.clear
185
- initialize_type_map
208
+ # Connects to a StandardAPI server and sets up the adapter depending
209
+ # on the connected server's characteristics.
210
+ def connect
211
+ @raw_connection = self.class.new_client(@connection_parameters)
186
212
  end
187
213
 
188
- private
214
+ def reconnect
215
+ @raw_connection&.reconnect!
216
+ connect unless @raw_connection
217
+ end
218
+
219
+ # Configures the encoding, verbosity, schema search path, and time zone of the connection.
220
+ # This is called by #connect and should not be called manually.
221
+ def configure_connection
222
+ reload_type_map
223
+ end
189
224
 
190
- def type_map
191
- @type_map ||= Type::HashLookupTypeMap.new.tap do |mapping|
192
- initialize_type_map(mapping)
225
+ def reload_type_map
226
+ if @type_map
227
+ type_map.clear
228
+ else
229
+ @type_map = Type::HashLookupTypeMap.new
193
230
  end
231
+
232
+ initialize_type_map
194
233
  end
234
+
235
+ private
195
236
 
196
- def initialize_type_map(m = type_map)
197
- self.class.initialize_type_map(m)
198
- load_additional_types
237
+ def initialize_type_map(m = nil)
238
+ self.class.initialize_type_map(m || @type_map)
199
239
  end
200
240
 
201
- def initialize_type_map(m) # :nodoc:
202
- m.register_type 'boolean', Type::Boolean.new
203
- m.register_type 'string' do |_, options|
204
- Type::String.new(**options.slice(:limit))
205
- end
206
- m.register_type 'integer' do |_, options|
207
- Type::Integer.new(**options.slice(:limit))
241
+ def self.initialize_type_map(m) # :nodoc:
242
+ m.register_type 'boolean', Type::Boolean.new
243
+ m.register_type 'binary' do |_, options|
244
+ Sunstone::Type::Binary.new(**options.slice(:limit))
208
245
  end
209
- m.register_type 'decimal' do |_, options|
246
+ m.register_type 'datetime', Sunstone::Type::DateTime.new
247
+ m.register_type 'decimal' do |_, options|
210
248
  Type::Decimal.new(**options.slice(:precision, :scale))
211
249
  end
212
- m.register_type 'binary' do |_, options|
213
- Sunstone::Type::Binary.new(**options.slice(:limit))
250
+ m.register_type 'integer' do |_, options|
251
+ Type::Integer.new(**options.slice(:limit))
214
252
  end
215
-
216
- m.register_type 'datetime', Sunstone::Type::DateTime.new
217
- m.register_type 'json', Sunstone::Type::Json.new
218
- m.register_type 'uuid', Sunstone::Type::Uuid.new
253
+ m.register_type 'json', Sunstone::Type::Json.new
254
+ m.register_type 'string' do |_, options|
255
+ Type::String.new(**options.slice(:limit))
256
+ end
257
+ m.register_type 'uuid', Sunstone::Type::Uuid.new
219
258
 
220
259
  if defined?(Sunstone::Type::EWKB)
221
260
  m.register_type 'ewkb', Sunstone::Type::EWKB.new
@@ -3,24 +3,24 @@ require 'arel/visitors/visitor'
3
3
  module Arel
4
4
  module Visitors
5
5
  class Sunstone < Arel::Visitors::Visitor
6
-
6
+
7
7
  def compile(node, collector = Arel::Collectors::Sunstone.new)
8
8
  accept(node, collector).value
9
9
  end
10
-
10
+
11
11
  private
12
-
12
+
13
13
  def visit_Arel_Nodes_SelectStatement o, collector
14
14
  collector.table = o.cores.first.source.left.name
15
15
 
16
16
  collector = o.cores.inject(collector) { |c,x|
17
17
  visit_Arel_Nodes_SelectCore(x, c)
18
18
  }
19
-
19
+
20
20
  if !o.orders.empty?
21
21
  collector.order = o.orders.map { |x| visit(x, collector) }
22
22
  end
23
-
23
+
24
24
  collector = maybe_visit o.limit, collector
25
25
  collector = maybe_visit o.offset, collector
26
26
  collector = maybe_visit o.eager_load, collector
@@ -61,27 +61,36 @@ module Arel
61
61
  collector.request_type = Net::HTTP::Post
62
62
  collector.table = o.relation.name
63
63
  collector.operation = :insert
64
-
64
+
65
65
  if o.values
66
66
  if o.values.is_a?(Arel::Nodes::SqlLiteral) && o.values == 'DEFAULT VALUES'
67
67
  collector.updates = {}
68
68
  else
69
- collector.updates = {}
70
-
71
- o.columns.map(&:name).zip(o.values.expr.first).to_h.each do |k, v|
72
- collector.updates[k] = case v
73
- when Nodes::SqlLiteral, Nodes::BindParam, ActiveModel::Attribute
74
- visit(v, collector)
75
- else
76
- v
77
- end
78
- end
69
+ values = visit(o.values, collector)
70
+ collector.updates = o.columns.map(&:name).zip(values).to_h
79
71
  end
80
72
  end
81
-
73
+
82
74
  collector
83
75
  end
84
-
76
+
77
+ def visit_Arel_Nodes_ValuesList o, collector
78
+ o.rows[0].map do |v|
79
+ visit_subrelation v, collector
80
+ end
81
+ end
82
+
83
+ def visit_subrelation v, collector
84
+ case v
85
+ when Array
86
+ v.map { |v2| visit_subrelation v2, collector }
87
+ when Hash
88
+ v.transform_values { |v2| visit_subrelation v2, collector }
89
+ else
90
+ visit(v, collector)
91
+ end
92
+ end
93
+
85
94
  def find_bottom(hash)
86
95
  if hash.is_a?(Hash)
87
96
  if hash.values.first.is_a?(Array) || hash.values.first.is_a?(Hash)
@@ -98,10 +107,10 @@ module Arel
98
107
  end
99
108
  end
100
109
  end
101
-
110
+
102
111
  def add_to_bottom_of_hash_or_array(hash, value)
103
112
  hash = find_bottom(hash)
104
-
113
+
105
114
  if hash.is_a?(Hash)
106
115
  nkey = hash.keys.first
107
116
  nvalue = hash.values.first
@@ -147,26 +156,26 @@ module Arel
147
156
  #
148
157
  def visit_Arel_Nodes_UpdateStatement o, collector
149
158
  collector.request_type = Net::HTTP::Patch
150
-
159
+
151
160
  collector.table = o.relation.name
152
161
  collector.operation = :update
153
-
162
+
154
163
  # collector.id = o.wheres.first.children.first.right
155
164
  if !o.wheres.empty?
156
165
  collector.where = o.wheres.map { |x| visit(x, collector) }.inject([]) { |c, w|
157
166
  w.is_a?(Array) ? c += w : c << w
158
167
  }
159
168
  end
160
-
169
+
161
170
  if collector.where.size != 1 && collector.where.first.size != 1 && !collector.where.first['id']
162
171
  raise 'Upsupported'
163
172
  end
164
-
173
+
165
174
  collector.where = collector.where.first
166
-
175
+
167
176
  if o.values
168
177
  collector.updates = {}
169
-
178
+
170
179
  o.values.map { |x| visit(x, collector) }.each do |value|
171
180
  value.each do |key, v|
172
181
  if key.is_a?(Hash)
@@ -191,7 +200,7 @@ module Arel
191
200
  end
192
201
  end
193
202
  end
194
-
203
+
195
204
  collector
196
205
  end
197
206
  #
@@ -426,7 +435,7 @@ module Arel
426
435
  def visit_Arel_Nodes_Descending o, collector
427
436
  { visit(o.expr, collector) => :desc }
428
437
  end
429
-
438
+
430
439
  def visit_Arel_Nodes_RandomOrdering o, collector
431
440
  :random
432
441
  end
@@ -468,7 +477,7 @@ module Arel
468
477
  #
469
478
  def visit_Arel_Nodes_Count o, collector
470
479
  collector.operation = :calculate
471
-
480
+
472
481
  collector.columns ||= []
473
482
  collector.columns << {:count => (o.expressions.first.is_a?(Arel::Attributes::Attribute) ? o.expressions.first.name : o.expressions.first) }
474
483
  # collector.columns = visit o.expressions.first, collector
@@ -476,7 +485,7 @@ module Arel
476
485
 
477
486
  def visit_Arel_Nodes_Sum o, collector
478
487
  collector.operation = :calculate
479
-
488
+
480
489
  collector.columns ||= []
481
490
  collector.columns << {:sum => (o.expressions.first.is_a?(Arel::Attributes::Attribute) ? o.expressions.first.name : o.expressions.first) }
482
491
  # collector.columns = visit o.expressions.first, collector
@@ -484,7 +493,7 @@ module Arel
484
493
 
485
494
  def visit_Arel_Nodes_Max o, collector
486
495
  collector.operation = :calculate
487
-
496
+
488
497
  collector.columns ||= []
489
498
  if o.expressions.first.is_a?(Arel::Attributes::Attribute)
490
499
  relation = o.expressions.first.relation
@@ -686,11 +695,11 @@ module Arel
686
695
  end
687
696
  end
688
697
  alias_method :visit_Arel_Nodes_HomogeneousIn, :visit_Arel_Nodes_In
689
-
698
+
690
699
  def visit_Arel_Nodes_NotIn o, collector
691
700
  key = visit(o.left, collector)
692
701
  value = {not_in: visit(o.right, collector)}
693
-
702
+
694
703
  if hash.is_a?(Hash)
695
704
  add_to_bottom_of_hash_or_array(key, value)
696
705
  key
@@ -698,10 +707,10 @@ module Arel
698
707
  {key => value}
699
708
  end
700
709
  end
701
-
710
+
702
711
  # You merge a into b if a keys do not colid with b keys
703
712
  def mergeable?(hash_a, hash_b)
704
-
713
+
705
714
  hash_a.each do |key, value_a|
706
715
  #TODO: one day maybe just use symbols for all keys?
707
716
  if hash_b.has_key?(key.to_sym) || hash_b.has_key?(key.to_s)
@@ -715,7 +724,7 @@ module Arel
715
724
  end
716
725
  true
717
726
  end
718
-
727
+
719
728
  def visit_Arel_Nodes_And o, collector
720
729
  ors = []
721
730
 
@@ -730,16 +739,16 @@ module Arel
730
739
  ors << value
731
740
  end
732
741
  end
733
-
742
+
734
743
  result = []
735
744
  ors.each_with_index do |c, i|
736
745
  result << c
737
746
  result << 'AND' if ors.size != i + 1
738
747
  end
739
-
748
+
740
749
  result.size == 1 ? result.first : result
741
750
  end
742
-
751
+
743
752
  def visit_Arel_Nodes_Or o, collector
744
753
  [visit(o.left, collector), 'OR', visit(o.right, collector)]
745
754
  end
@@ -748,10 +757,12 @@ module Arel
748
757
  case o.left
749
758
  when Arel::Nodes::UnqualifiedColumn
750
759
  case o.right
751
- when Arel::Attributes::Attribute, Arel::Nodes::BindParam, ActiveModel::Attribute
752
- { visit(o.left.expr, collector) => visit(o.right, collector) }
760
+ when Array
761
+ { visit(o.left.expr, collector) => o.right.map { |i| i.transform_values { |v| visit(v, collector) } } }
762
+ when Hash
763
+ { visit(o.left.expr, collector) => o.right.transform_values { |v| visit(v, collector) } }
753
764
  else
754
- { visit(o.left.expr, collector) => o.right }
765
+ { visit(o.left.expr, collector) => visit(o.right, collector) }
755
766
  end
756
767
  when Arel::Attributes::Attribute, Arel::Nodes::BindParam, ActiveModel::Attribute
757
768
  { visit(o.left, collector) => visit(o.right, collector) }
@@ -770,7 +781,7 @@ module Arel
770
781
  okey.merge!(value)
771
782
  hash
772
783
  end
773
-
784
+
774
785
  def add_to_bottom_of_hash(hash, value)
775
786
  okey = hash
776
787
  while okey.is_a?(Hash) && (okey.values.first.is_a?(Hash) || okey.values.first.is_a?(Array))
@@ -785,11 +796,11 @@ module Arel
785
796
  okey[nkey] = { nvalue => value }
786
797
  hash
787
798
  end
788
-
799
+
789
800
  def visit_Arel_Nodes_Equality o, collector
790
801
  key = visit(o.left, collector)
791
802
  value = (o.right.nil? ? nil : visit(o.right, collector))
792
-
803
+
793
804
  if key.is_a?(Hash)
794
805
  add_to_bottom_of_hash(key, {eq: value})
795
806
  elsif o.left.class.name == 'Arel::Attributes::Key'
@@ -798,7 +809,7 @@ module Arel
798
809
  { key => value }
799
810
  end
800
811
  end
801
-
812
+
802
813
  def visit_Arel_Nodes_TSMatch(o, collector)
803
814
  key = visit(o.left, collector)
804
815
  value = { ts_match: (o.right.nil? ? nil : visit(o.right, collector)) }
@@ -814,11 +825,11 @@ module Arel
814
825
  hash
815
826
  end
816
827
  end
817
-
828
+
818
829
  def visit_Arel_Nodes_TSVector(o, collector)
819
830
  visit(o.attribute, collector)
820
831
  end
821
-
832
+
822
833
  def visit_Arel_Nodes_TSQuery(o, collector)
823
834
  if o.language
824
835
  [visit(o.expression, collector), visit(o.language, collector)]
@@ -826,11 +837,11 @@ module Arel
826
837
  visit(o.expression, collector)
827
838
  end
828
839
  end
829
-
840
+
830
841
  def visit_Arel_Nodes_HasKey o, collector
831
842
  key = visit(o.left, collector)
832
843
  value = {has_key: (o.right.nil? ? nil : o.right.to_s)}
833
-
844
+
834
845
  if key.is_a?(Hash)
835
846
  okey = key
836
847
  while okey.values.first.is_a?(Hash)
@@ -847,7 +858,7 @@ module Arel
847
858
  def visit_Arel_Nodes_HasKeys o, collector
848
859
  key = visit(o.left, collector)
849
860
  value = { has_keys: visit(o.right, collector) }
850
-
861
+
851
862
  if key.is_a?(Hash)
852
863
  okey = key
853
864
  while okey.values.first.is_a?(Hash)
@@ -864,7 +875,7 @@ module Arel
864
875
  def visit_Arel_Nodes_HasAnyKey o, collector
865
876
  key = visit(o.left, collector)
866
877
  value = { has_any_key: visit(o.right, collector) }
867
-
878
+
868
879
  if key.is_a?(Hash)
869
880
  okey = key
870
881
  while okey.values.first.is_a?(Hash)
@@ -894,11 +905,11 @@ module Arel
894
905
  def visit_Arel_Nodes_UnqualifiedColumn o, collector
895
906
  o.name
896
907
  end
897
-
908
+
898
909
  def visit_Arel_Attributes_Cast(o, collector)
899
910
  visit(o.relation, collector) # No casting yet
900
911
  end
901
-
912
+
902
913
  def visit_Arel_Attributes_Key o, collector
903
914
  "#{visit(o.relation, collector)}.#{o.name}"
904
915
  end
@@ -938,7 +949,7 @@ module Arel
938
949
  # def visit_Arel_Attributes_EmptyRelation o, collector, top=true
939
950
  # o.for_write ? "#{o.name}_attributes" : o.name
940
951
  # end
941
-
952
+
942
953
  def visit_Arel_Attributes_Attribute o, collector
943
954
  join_name = o.relation.table_alias || o.relation.name
944
955
 
@@ -963,7 +974,7 @@ module Arel
963
974
  o.value_for_database
964
975
  end
965
976
  end
966
-
977
+
967
978
  def visit_Arel_Nodes_BindParam o, collector
968
979
  a = collector.add_bind(o.value)
969
980
  o.is_a?(Arel::Nodes::BindParam) ? o : a
@@ -1060,11 +1071,11 @@ module Arel
1060
1071
  collector
1061
1072
  end
1062
1073
  end
1063
-
1074
+
1064
1075
  def maybe_visit thing, collector
1065
1076
  return collector unless thing
1066
1077
  visit thing, collector
1067
1078
  end
1068
1079
  end
1069
1080
  end
1070
- end
1081
+ end
@@ -4,7 +4,7 @@
4
4
  module Sunstone
5
5
  class Connection
6
6
 
7
- attr_reader :api_key, :host, :port, :use_ssl
7
+ attr_reader :api_key, :host, :port, :use_ssl, :prefix
8
8
 
9
9
  # Initialize a connection a Sunstone API server.
10
10
  #
@@ -31,7 +31,7 @@ module Sunstone
31
31
  self.instance_variable_set(:"@#{key}", config[key])
32
32
  end
33
33
 
34
- @connection = Net::HTTP.new(host, port)
34
+ @connection = Net::HTTP.new(host, port || (use_ssl ? 443 : 80))
35
35
  @connection.max_retries = 0
36
36
  @connection.open_timeout = 5
37
37
  @connection.read_timeout = 30
@@ -142,7 +142,7 @@ module Sunstone
142
142
  message << " #{request.method} #{path_and_query[0]}"
143
143
  if path_and_query[1]
144
144
  if request['Query-Encoding'] == 'application/msgpack'
145
- message << " " << MessagePack.unpack(CGI.unescape(path_and_query[1]))
145
+ message << " " << MessagePack.unpack(CGI.unescape(path_and_query[1])).inspect
146
146
  else
147
147
  message << " " << CGI.unescape(path_and_query[1])
148
148
  end
@@ -1,3 +1,3 @@
1
1
  module Sunstone
2
- VERSION = '7.0.0'
2
+ VERSION = '7.1.0.1'
3
3
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: sunstone
3
3
  version: !ruby/object:Gem::Version
4
- version: 7.0.0
4
+ version: 7.1.0.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Jon Bracy
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2022-12-07 00:00:00.000000000 Z
11
+ date: 2023-12-20 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: rake
@@ -184,14 +184,14 @@ dependencies:
184
184
  requirements:
185
185
  - - ">="
186
186
  - !ruby/object:Gem::Version
187
- version: 7.0.0
187
+ version: 7.1.0
188
188
  type: :development
189
189
  prerelease: false
190
190
  version_requirements: !ruby/object:Gem::Requirement
191
191
  requirements:
192
192
  - - ">="
193
193
  - !ruby/object:Gem::Version
194
- version: 7.0.0
194
+ version: 7.1.0
195
195
  - !ruby/object:Gem::Dependency
196
196
  name: msgpack
197
197
  requirement: !ruby/object:Gem::Requirement
@@ -226,42 +226,42 @@ dependencies:
226
226
  requirements:
227
227
  - - ">="
228
228
  - !ruby/object:Gem::Version
229
- version: 7.0.0
229
+ version: 7.1.0
230
230
  type: :runtime
231
231
  prerelease: false
232
232
  version_requirements: !ruby/object:Gem::Requirement
233
233
  requirements:
234
234
  - - ">="
235
235
  - !ruby/object:Gem::Version
236
- version: 7.0.0
236
+ version: 7.1.0
237
237
  - !ruby/object:Gem::Dependency
238
238
  name: arel-extensions
239
239
  requirement: !ruby/object:Gem::Requirement
240
240
  requirements:
241
241
  - - ">="
242
242
  - !ruby/object:Gem::Version
243
- version: 6.1.0
243
+ version: 7.0.1
244
244
  type: :runtime
245
245
  prerelease: false
246
246
  version_requirements: !ruby/object:Gem::Requirement
247
247
  requirements:
248
248
  - - ">="
249
249
  - !ruby/object:Gem::Version
250
- version: 6.1.0
250
+ version: 7.0.1
251
251
  - !ruby/object:Gem::Dependency
252
252
  name: activerecord-filter
253
253
  requirement: !ruby/object:Gem::Requirement
254
254
  requirements:
255
255
  - - ">="
256
256
  - !ruby/object:Gem::Version
257
- version: 6.1.0
257
+ version: 7.0.0
258
258
  type: :runtime
259
259
  prerelease: false
260
260
  version_requirements: !ruby/object:Gem::Requirement
261
261
  requirements:
262
262
  - - ">="
263
263
  - !ruby/object:Gem::Version
264
- version: 6.1.0
264
+ version: 7.0.0
265
265
  description: A library for interacting with REST APIs. Similar to ActiveResource
266
266
  email:
267
267
  - jonbracy@gmail.com
@@ -323,7 +323,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
323
323
  - !ruby/object:Gem::Version
324
324
  version: '0'
325
325
  requirements: []
326
- rubygems_version: 3.2.22
326
+ rubygems_version: 3.4.13
327
327
  signing_key:
328
328
  specification_version: 4
329
329
  summary: A library for interacting with REST APIs