sunstone 2.0.4 → 5.0.0.beta3

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.
@@ -3,28 +3,70 @@ module ActiveRecord
3
3
  module Sunstone
4
4
  module Type
5
5
  class Array < ActiveRecord::Type::Value
6
- include ActiveRecord::Type::Mutable
6
+ include ActiveRecord::Type::Helpers::Mutable
7
7
 
8
8
  attr_reader :subtype
9
- delegate :type, to: :subtype
9
+ delegate :type, :user_input_in_time_zone, :limit, to: :subtype
10
10
 
11
11
  def initialize(subtype)
12
12
  @subtype = subtype
13
13
  end
14
14
 
15
- def type_cast_for_database(value)
16
- super(value).to_json if value
15
+ def deserialize(value)
16
+ if value.is_a?(String)
17
+ type_cast_array(JSON.parse(value), :deserialize)
18
+ else
19
+ super
20
+ end
17
21
  end
18
22
 
19
- def cast_value(string)
20
- return string unless string.is_a?(::String)
21
- return if string.empty?
22
-
23
- JSON.parse(string)
23
+ def cast(value)
24
+ if value.is_a?(::String)
25
+ value = JSON.parse(value)
26
+ end
27
+ type_cast_array(value, :cast)
28
+ end
29
+
30
+ def serialize(value)
31
+ if value.is_a?(::Array)
32
+ type_cast_array(value, :serialize)
33
+ else
34
+ super
35
+ end
36
+ end
37
+
38
+ def ==(other)
39
+ other.is_a?(Array) && subtype == other.subtype
40
+ end
41
+
42
+ # def type_cast_for_schema(value)
43
+ # return super unless value.is_a?(::Array)
44
+ # "[" + value.map { |v| subtype.type_cast_for_schema(v) }.join(", ") + "]"
45
+ # end
46
+
47
+ def map(value, &block)
48
+ value.map(&block)
49
+ end
50
+
51
+ # def cast_value(string)
52
+ # return string unless string.is_a?(::String)
53
+ # return if string.empty?
54
+ #
55
+ # JSON.parse(string)
56
+ # end
57
+
58
+ private
59
+
60
+ def type_cast_array(value, method)
61
+ if value.is_a?(::Array)
62
+ value.map { |item| type_cast_array(item, method) }
63
+ else
64
+ @subtype.public_send(method, value)
65
+ end
24
66
  end
25
67
 
26
68
  end
27
69
  end
28
70
  end
29
71
  end
30
- end
72
+ end
@@ -4,7 +4,7 @@ module ActiveRecord
4
4
  module Type
5
5
  class DateTime < ActiveRecord::Type::DateTime
6
6
 
7
- def type_cast_for_database(value)
7
+ def serialize(value)
8
8
  super(value).iso8601(3) if value
9
9
  end
10
10
 
@@ -10,7 +10,7 @@ module ActiveRecord
10
10
  :ewkb
11
11
  end
12
12
 
13
- def type_cast_for_database(value)
13
+ def serialize(value)
14
14
  if value
15
15
  ::RGeo::WKRep::WKBGenerator.new(hex_format: true, type_format: :ewkb, emit_ewkb_srid: true).generate(value)
16
16
  end
@@ -0,0 +1,15 @@
1
+ module ActiveRecord
2
+ module ConnectionAdapters
3
+ class SunstoneSQLTypeMetadata < DelegateClass(SqlTypeMetadata)
4
+ attr_reader :array
5
+
6
+ def initialize(type_metadata, options = {})
7
+ super(type_metadata)
8
+ @type_metadata = type_metadata
9
+ @primary_key = (options['primary_key'] == true)
10
+ @array = !!options['array']
11
+ end
12
+
13
+ end
14
+ end
15
+ end
@@ -34,7 +34,7 @@ module ActiveRecord
34
34
  end
35
35
 
36
36
  # Forward only valid config params to PGconn.connect.
37
- conn_params.keep_if { |k, _| VALID_SUNSTONE_CONN_PARAMS.include?(k) }
37
+ conn_params.slice!(*VALID_SUNSTONE_CONN_PARAMS)
38
38
 
39
39
  # The postgres drivers don't allow the creation of an unconnected PGconn object,
40
40
  # so just pass a nil connection object for the time being.
@@ -54,7 +54,7 @@ module ActiveRecord
54
54
  # * <tt>:encoding</tt> - An optional client encoding that is used in a <tt>SET client_encoding TO
55
55
  # <encoding></tt> call on the connection.
56
56
  class SunstoneAPIAdapter < AbstractAdapter
57
- ADAPTER_NAME = 'Sunstone'
57
+ ADAPTER_NAME = 'Sunstone'.freeze
58
58
 
59
59
  NATIVE_DATABASE_TYPES = {
60
60
  string: { name: "string" },
@@ -63,8 +63,12 @@ module ActiveRecord
63
63
  boolean: { name: "boolean" }
64
64
  }
65
65
 
66
- include Sunstone::DatabaseStatements
66
+ # include PostgreSQL::Quoting
67
+ # include PostgreSQL::ReferentialIntegrity
67
68
  include Sunstone::SchemaStatements
69
+ include Sunstone::DatabaseStatements
70
+ # include PostgreSQL::ColumnDumper
71
+ # include Savepoints
68
72
 
69
73
  # Returns 'SunstoneAPI' as adapter name for identification purposes.
70
74
  def adapter_name
@@ -80,7 +84,7 @@ module ActiveRecord
80
84
 
81
85
  # Initializes and connects a SunstoneAPI adapter.
82
86
  def initialize(connection, logger, connection_parameters, config)
83
- super(connection, logger)
87
+ super(connection, logger, config)
84
88
 
85
89
  @visitor = Arel::Visitors::Sunstone.new
86
90
  @connection_parameters, @config = connection_parameters, config
@@ -149,6 +153,15 @@ module ActiveRecord
149
153
  def server_config
150
154
  Wankel.parse(@connection.get("/configuration").body)
151
155
  end
156
+
157
+ def lookup_cast_type_from_column(column) # :nodoc:
158
+ if column.array
159
+ Sunstone::Type::Array.new(type_map.lookup(column.sql_type))
160
+ else
161
+ type_map.lookup(column.sql_type)
162
+ end
163
+ end
164
+
152
165
 
153
166
  private
154
167
 
@@ -158,7 +171,7 @@ module ActiveRecord
158
171
  m.register_type 'integer', Type::Integer.new
159
172
  m.register_type 'decimal', Type::Decimal.new
160
173
  m.register_type 'datetime', Sunstone::Type::DateTime.new
161
- m.register_type 'hash', Type::Value.new
174
+ m.register_type 'json', Type::Internal::AbstractJson.new
162
175
  m.register_type 'ewkb', Sunstone::Type::EWKB.new
163
176
  end
164
177
 
@@ -186,6 +199,9 @@ module ActiveRecord
186
199
  def create_table_definition(name, temporary, options, as = nil) # :nodoc:
187
200
  SunstoneAPI::TableDefinition.new native_database_types, name, temporary, options, as
188
201
  end
202
+
203
+ ActiveRecord::Type.add_modifier({ array: true }, Sunstone::Type::Array, adapter: :sunstone)
204
+ # ActiveRecord::Type.add_modifier({ range: true }, OID::Range, adapter: :postgresql)
189
205
  end
190
206
  end
191
207
  end
@@ -4,21 +4,41 @@ module Arel
4
4
 
5
5
  attr_accessor :request_type, :table, :where, :limit, :offset, :order, :operation, :columns, :updates, :eager_loads, :id
6
6
 
7
+ def cast_attribute(v)
8
+ if (v.is_a?(ActiveRecord::Attribute))
9
+ v.value_for_database
10
+ else
11
+ v
12
+ end
13
+ end
14
+
7
15
  def substitute_binds hash, bvs
8
16
  if hash.is_a?(Array)
9
- hash.map { |w| substitute_binds(w, bvs) }
10
- else
17
+ hash.map do |v|
18
+ if v.is_a?(Arel::Nodes::BindParam)
19
+ cast_attribute(bvs.last.is_a?(Array) ? bvs.shift.last : bvs.shift)
20
+ elsif v.is_a?(Hash) || v.is_a?(Array)
21
+ substitute_binds(v, bvs)
22
+ else
23
+ v
24
+ end
25
+ end
26
+ elsif hash.is_a?(Hash)
11
27
  newhash = {}
12
28
  hash.each do |k, v|
13
- if Arel::Nodes::BindParam === v
14
- newhash[k] = (bvs.last.is_a?(Array) ? bvs.shift.last : bvs.shift)
29
+ if v.is_a?(Arel::Nodes::BindParam)
30
+ newhash[k] = cast_attribute(bvs.last.is_a?(Array) ? bvs.shift.last : bvs.shift)
15
31
  elsif v.is_a?(Hash)
16
32
  newhash[k] = substitute_binds(v, bvs)
33
+ elsif v.is_a?(Array)
34
+ newhash[k] = substitute_binds(v, bvs)
17
35
  else
18
36
  newhash[k] = v
19
37
  end
20
38
  end
21
39
  newhash
40
+ else
41
+ cast_attribute(bvs.last.is_a?(Array) ? bvs.shift.last : bvs.shift)
22
42
  end
23
43
  end
24
44
 
@@ -55,9 +75,9 @@ module Arel
55
75
  get_params[:include] = eager_loads.clone
56
76
  end
57
77
 
58
- get_params[:limit] = limit if limit
59
- get_params[:offset] = offset if offset
60
- get_params[:order] = order if order
78
+ get_params[:limit] = substitute_binds(limit, bvs) if limit
79
+ get_params[:offset] = substitute_binds(offset, bvs) if offset
80
+ get_params[:order] = substitute_binds(order, bvs) if order
61
81
 
62
82
  case operation
63
83
  when :count
@@ -69,9 +89,9 @@ module Arel
69
89
  path += "/#{get_params[:where]['id']}"
70
90
  get_params.delete(:where)
71
91
  end
72
-
92
+
73
93
  if get_params.size > 0
74
- path += '?' + get_params.to_param
94
+ path += '?m=' + URI.escape(CGI.escape(MessagePack.pack(get_params)))
75
95
  end
76
96
 
77
97
  request = request_type.new(path)
@@ -18,8 +18,12 @@ module Arel
18
18
  accept(node, Arel::Collectors::SQLString.new, &block).value
19
19
  end
20
20
 
21
+ def preparable
22
+ false
23
+ end
24
+
21
25
  private
22
-
26
+
23
27
  def visit_Arel_Nodes_SelectStatement o, collector
24
28
  collector = o.cores.inject(collector) { |c,x|
25
29
  visit_Arel_Nodes_SelectCore(x, c)
@@ -64,17 +68,76 @@ module Arel
64
68
  collector
65
69
  end
66
70
 
71
+ def visit_Arel_Nodes_Overlaps o, collector
72
+ { visit(o.left, collector) => {overlaps: o.left.type_cast_for_database(o.right) }}
73
+ end
74
+
67
75
  def visit_Arel_Nodes_InsertStatement o, collector
68
76
  collector.request_type = Net::HTTP::Post
69
77
  collector.table = o.relation.name
70
78
  collector.operation = :insert
71
79
 
72
80
  if o.values
73
- collector.updates = o.values.right.map { |x| visit(x, collector) }.zip(o.values.left).to_h
81
+ keys = o.values.right.map { |x| visit(x, collector) }
82
+ values = o.values.left
83
+ collector.updates = {}
84
+
85
+
86
+ keys.each_with_index do |k, i|
87
+ if k.is_a?(Hash)
88
+ add_to_bottom_of_hash_or_array(k, values[i])
89
+ collector.updates.deep_merge!(k) { |key, v1, v2|
90
+ if (v1.is_a?(Array) && v2.is_a?(Array))
91
+ v2.each_with_index do |v, i|
92
+ if v1[i].nil?
93
+ v1[i] = v2[i]
94
+ else
95
+ v1[i].deep_merge!(v2[i]) unless v2[i].nil?
96
+ end
97
+ end
98
+ v1
99
+ else
100
+ v2
101
+ end
102
+ }
103
+ else
104
+ collector.updates[k] = values[i]
105
+ end
106
+ end
74
107
  end
75
108
 
76
109
  collector
77
110
  end
111
+
112
+ def find_bottom(hash)
113
+ if hash.is_a?(Hash)
114
+ if hash.values.first.is_a?(Array) || hash.values.first.is_a?(Hash)
115
+ find_bottom(hash.values.first)
116
+ else
117
+ hash
118
+ end
119
+ elsif hash.is_a?(Array)
120
+ fnn = hash.find { |i| !i.nil? }
121
+ if fnn.is_a?(Array) || fnn.is_a?(Hash)
122
+ fnn
123
+ else
124
+ hash
125
+ end
126
+ end
127
+ end
128
+
129
+ def add_to_bottom_of_hash_or_array(hash, value)
130
+ hash = find_bottom(hash)
131
+ if hash.is_a?(Hash)
132
+ nkey = hash.keys.first
133
+ nvalue = hash.values.first
134
+ hash[nkey] = { nvalue => value }
135
+ elsif hash.is_a?(Array)
136
+ fnni = hash.find_index { |i| !i.nil? }
137
+ nvalue = hash[fnni]
138
+ hash[fnni] = { nvalue => value }
139
+ end
140
+ end
78
141
 
79
142
 
80
143
  private
@@ -112,22 +175,50 @@ module Arel
112
175
  collector.request_type = Net::HTTP::Patch
113
176
  collector.table = o.relation.name
114
177
  collector.operation = :update
115
-
116
- wheres = o.wheres.map { |x| visit(x, collector) }.inject([]) { |c, w|
117
- w.is_a?(Array) ? c += w : c << w
118
- }
119
- if wheres.size != 1 && wheres.first.size != 1 && !wheres['id']
120
- raise 'Upsupported'
121
- else
122
- collector.where = wheres
178
+
179
+ # collector.id = o.wheres.first.children.first.right
180
+ if !o.wheres.empty?
181
+ collector.where = o.wheres.map { |x| visit(x, collector) }.inject([]) { |c, w|
182
+ w.is_a?(Array) ? c += w : c << w
183
+ }
123
184
  end
124
185
 
125
- collector.id = wheres.first['id']
186
+ if collector.where.size != 1 && collector.where.first.size != 1 && !collector.where.first['id']
187
+ raise 'Upsupported'
188
+ end
189
+ if !collector.where.first['id']
190
+ collector.table = collector.where.first.keys.first
191
+ collector.where[0] = {'id' => collector.where.first.values.first.values.first}
192
+ end
126
193
 
127
194
  if o.values
128
- collector.updates = o.values.map { |x| visit(x, collector) }.inject({}){|c,v| c.merge(v) }#.zip(o.values).to_h
195
+ collector.updates = {}
196
+
197
+ o.values.map { |x| visit(x, collector) }.each do |value|
198
+ value.each do |key, v|
199
+ if key.is_a?(Hash)
200
+ add_to_bottom_of_hash_or_array(key, v)
201
+ collector.updates.deep_merge!(key) { |key, v1, v2|
202
+ if (v1.is_a?(Array) && v2.is_a?(Array))
203
+ v2.each_with_index do |v, i|
204
+ if v1[i].nil?
205
+ v1[i] = v2[i]
206
+ else
207
+ v1[i].deep_merge!(v2[i]) unless v2[i].nil?
208
+ end
209
+ end
210
+ v1
211
+ else
212
+ v2
213
+ end
214
+ }
215
+ else
216
+ collector.updates[key] = v
217
+ end
218
+ end
219
+ end
129
220
  end
130
-
221
+
131
222
  collector
132
223
  end
133
224
  #
@@ -457,31 +548,63 @@ module Arel
457
548
  # collector << " BETWEEN "
458
549
  # visit o.right, collector
459
550
  # end
460
- #
461
- # def visit_Arel_Nodes_GreaterThanOrEqual o, collector
462
- # collector = visit o.left, collector
463
- # collector << " >= "
464
- # visit o.right, collector
465
- # end
466
- #
551
+
552
+ def visit_Arel_Nodes_GreaterThanOrEqual o, collector
553
+ key = visit(o.left, collector)
554
+ value = { :gte => visit(o.right, collector) }
555
+ if key.is_a?(Hash)
556
+ if o.left.is_a?(Arel::Attributes::Cast)
557
+ merge_to_bottom_hash(key, value)
558
+ else
559
+ add_to_bottom_of_hash(key, value)
560
+ end
561
+ else
562
+ { key => value }
563
+ end
564
+ end
565
+
467
566
  def visit_Arel_Nodes_GreaterThan o, collector
468
- {
469
- visit(o.left, collector) => { :greater_than => visit(o.right, collector) }
470
- }
567
+ key = visit(o.left, collector)
568
+ value = { :gt => visit(o.right, collector) }
569
+ if key.is_a?(Hash)
570
+ if o.left.is_a?(Arel::Attributes::Cast)
571
+ merge_to_bottom_hash(key, value)
572
+ else
573
+ add_to_bottom_of_hash(key, value)
574
+ end
575
+ else
576
+ { key => value }
577
+ end
578
+ end
579
+
580
+ def visit_Arel_Nodes_LessThanOrEqual o, collector
581
+ key = visit(o.left, collector)
582
+ value = { :lte => visit(o.right, collector) }
583
+ if key.is_a?(Hash)
584
+ if o.left.is_a?(Arel::Attributes::Cast)
585
+ merge_to_bottom_hash(key, value)
586
+ else
587
+ add_to_bottom_of_hash(key, value)
588
+ end
589
+ else
590
+ { key => value }
591
+ end
592
+ end
593
+
594
+ def visit_Arel_Nodes_LessThan o, collector
595
+ key = visit(o.left, collector)
596
+ value = { :lte => visit(o.right, collector) }
597
+ if key.is_a?(Hash)
598
+ if o.left.is_a?(Arel::Attributes::Cast)
599
+ merge_to_bottom_hash(key, value)
600
+ else
601
+ add_to_bottom_of_hash(key, value)
602
+ end
603
+ else
604
+ { key => value }
605
+ end
471
606
  end
472
607
 
473
- # def visit_Arel_Nodes_LessThanOrEqual o, collector
474
- # collector = visit o.left, collector
475
- # collector << " <= "
476
- # visit o.right, collector
477
- # end
478
- #
479
- # def visit_Arel_Nodes_LessThan o, collector
480
- # collector = visit o.left, collector
481
- # collector << " < "
482
- # visit o.right, collector
483
- # end
484
- #
485
608
  # def visit_Arel_Nodes_Matches o, collector
486
609
  # collector = visit o.left, collector
487
610
  # collector << " LIKE "
@@ -561,15 +684,11 @@ module Arel
561
684
  end
562
685
  end
563
686
 
564
- # def visit_Arel_Nodes_In o, collector
565
- # if Array === o.right && o.right.empty?
566
- # collector << '1=0'
567
- # else
568
- # collector = visit o.left, collector
569
- # collector << " IN ("
570
- # visit(o.right, collector) << ")"
571
- # end
572
- # end
687
+ def visit_Arel_Nodes_In o, collector
688
+ {
689
+ visit(o.left, collector) => {in: visit(o.right, collector)}
690
+ }
691
+ end
573
692
  #
574
693
  # def visit_Arel_Nodes_NotIn o, collector
575
694
  # if Array === o.right && o.right.empty?
@@ -587,10 +706,11 @@ module Arel
587
706
  ors << o.children.inject({}) do |c, x|
588
707
  value = visit(x, collector)
589
708
  if value.is_a?(Hash)
590
- c.deep_merge(value)
709
+ c.deep_merge!(value)
591
710
  elsif value.is_a?(Array)
592
711
  value.size == 1 ? ors << value : ors += value
593
712
  end
713
+ c
594
714
  end
595
715
  ors
596
716
  end
@@ -605,8 +725,10 @@ module Arel
605
725
  end
606
726
 
607
727
  def visit_Arel_Nodes_Assignment o, collector
608
- case o.right
609
- when Arel::Nodes::UnqualifiedColumn, Arel::Attributes::Attribute, Arel::Nodes::BindParam
728
+ case o.left
729
+ when Arel::Nodes::UnqualifiedColumn
730
+ { visit(o.left.expr, collector) => visit(o.right, collector) }
731
+ when Arel::Attributes::Attribute, Arel::Nodes::BindParam
610
732
  { visit(o.left, collector) => visit(o.right, collector) }
611
733
  else
612
734
  collector = visit o.left, collector
@@ -615,20 +737,91 @@ module Arel
615
737
  end
616
738
  end
617
739
 
740
+ def merge_to_bottom_hash(hash, value)
741
+ okey = hash
742
+ while okey.values.first.is_a?(Hash)
743
+ okey = okey.values.first
744
+ end
745
+ okey.merge!(value)
746
+ hash
747
+ end
748
+
749
+ def add_to_bottom_of_hash(hash, value)
750
+ okey = hash
751
+ while okey.is_a?(Hash) && (okey.values.first.is_a?(Hash) || okey.values.first.is_a?(Array))
752
+ if okey.is_a?(Array)
753
+ okey = okey.find { |i| !i.nil? }
754
+ else
755
+ okey = okey.values.first
756
+ end
757
+ end
758
+ nkey = okey.keys.first
759
+ nvalue = okey.values.first
760
+ okey[nkey] = { nvalue => value }
761
+ hash
762
+ end
763
+
618
764
  def visit_Arel_Nodes_Equality o, collector
619
- key = visit(o.left, collector).to_s.split('.')
765
+ key = visit(o.left, collector)
620
766
  value = (o.right.nil? ? nil : visit(o.right, collector))
621
767
 
622
- hash = {
623
- key.pop => value
624
- }
625
-
626
- while key.size > 0
627
- hash = { key.pop => hash }
768
+ if key.is_a?(Hash)
769
+ add_to_bottom_of_hash(key, {eq: value})
770
+ else
771
+ key = key.to_s.split('.')
772
+ hash = { key.pop => value }
773
+ while key.size > 0
774
+ hash = { key.pop => hash }
775
+ end
776
+ hash
628
777
  end
629
- hash
630
778
  end
779
+
780
+ def visit_Arel_Nodes_TSMatch(o, collector)
781
+ key = visit(o.left, collector)
782
+ value = { ts_match: (o.right.nil? ? nil : visit(o.right, collector)) }
631
783
 
784
+ if key.is_a?(Hash)
785
+ add_to_bottom_of_hash(key, value)
786
+ else
787
+ key = key.to_s.split('.')
788
+ hash = { key.pop => value }
789
+ while key.size > 0
790
+ hash = { key.pop => hash }
791
+ end
792
+ hash
793
+ end
794
+ end
795
+
796
+ def visit_Arel_Nodes_TSVector(o, collector)
797
+ visit(o.attribute, collector)
798
+ end
799
+
800
+ def visit_Arel_Nodes_TSQuery(o, collector)
801
+ if o.language
802
+ [visit(o.expression, collector), visit(o.language, collector)]
803
+ else
804
+ visit(o.expression, collector)
805
+ end
806
+ end
807
+
808
+ def visit_Arel_Nodes_HasKey o, collector
809
+ key = visit(o.left, collector)
810
+ value = {has_key: (o.right.nil? ? nil : o.right.to_s)}
811
+
812
+ if key.is_a?(Hash)
813
+ okey = key
814
+ while okey.values.first.is_a?(Hash)
815
+ okey = okey.values.first
816
+ end
817
+ nkey = okey.keys.first
818
+ nvalue = okey.values.first
819
+ okey[nkey] = { nvalue => value }
820
+ else
821
+ { key => value }
822
+ end
823
+ end
824
+
632
825
  def visit_Arel_Nodes_NotEqual o, collector
633
826
  {
634
827
  visit(o.left, collector) => { :not => visit(o.right, collector) }
@@ -645,11 +838,47 @@ module Arel
645
838
  def visit_Arel_Nodes_UnqualifiedColumn o, collector
646
839
  o.name
647
840
  end
841
+
842
+ def visit_Arel_Attributes_Cast(o, collector)
843
+ key = visit(o.relation, collector)
844
+ value = { :cast => o.name }
845
+ if key.is_a?(Hash)
846
+ add_to_bottom_of_hash(key, value)
847
+ else
848
+ { key => value }
849
+ end
850
+ end
851
+
852
+ def visit_Arel_Attributes_Key o, collector
853
+ key = visit(o.relation, collector)
854
+ if key.is_a?(Hash)
855
+ okey = key
856
+ while okey.values.first.is_a?(Hash)
857
+ okey = okey.values.first
858
+ end
859
+ nkey = okey.keys.first
860
+ value = okey.values.first
861
+ okey[nkey] = {value => o.name}
862
+ key
863
+ else
864
+ { key => o.name }
865
+ end
866
+ end
648
867
 
868
+ def visit_Arel_Attributes_Relation o, collector
869
+ if o.collection
870
+ ary = []
871
+ ary[o.collection] = visit(o.relation, collector).to_s.split('.').last
872
+ {"#{o.name}_attributes" => ary}
873
+ else
874
+ {"#{o.name}_attributes" => visit(o.relation, collector).to_s.split('.').last}
875
+ end
876
+ end
877
+
649
878
  def visit_Arel_Attributes_Attribute o, collector
650
879
  join_name = o.relation.table_alias || o.relation.name
651
- # collector <<
652
880
  collector.table == join_name ? o.name : "#{join_name}.#{o.name}"
881
+ # o.name
653
882
  end
654
883
  alias :visit_Arel_Attributes_Integer :visit_Arel_Attributes_Attribute
655
884
  alias :visit_Arel_Attributes_Float :visit_Arel_Attributes_Attribute