sunstone 7.0.0 → 7.1.0.1

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,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