sunstone 2.0.0 → 2.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
  SHA1:
3
- metadata.gz: 5971616d7a67d451d0d618ed1aaa6f9de9b3daa0
4
- data.tar.gz: df3a218c951f5070e2cfccdc91cfa88c0c6a895c
3
+ metadata.gz: e7571ad32bf7197a480c1f59c5a5158ce0f1d492
4
+ data.tar.gz: d10ec4207fc78c2e6ec8d3dee815469a7b4b868a
5
5
  SHA512:
6
- metadata.gz: 6c2eed7323ae88fe0200bfbe83dff412602174d0f3559d94c8bce01117768b1f11b70b95f3b016f75de4751f051db8eb5dbee9ea9efa94743d0e5f9fc49ccfa0
7
- data.tar.gz: 87f7fe2cf78a6d7b0e8a4d0c10b00f606b31d4058c4a8b0fe1ed5f70ab16d39414da4d8d350e778dc389fa19408fd3c980dd9cf03fc9cf7ec8acc94c6beb91fc
6
+ metadata.gz: 121532495ba520b5e66de7cc054e9fc1958076c6953c2dc10e710816d9944fc76e940a4dd6018cea3a5599aa43faecdee9c81259fd7d569ea659abcbc6ccb4d9
7
+ data.tar.gz: 815d5f4f6a5c89a1552b8dc8cde45ac8cf508608b5403c75f4516569fd834f2f3becf1fa3af3cf25c622cba2d3ade471dca215029d4aa2230a9b46fc916e730b
data/README.md CHANGED
@@ -1,4 +1,11 @@
1
- sunstone
1
+ Sunstone
2
2
  ========
3
3
 
4
- A library for interacting with REST APIs
4
+ An [ActiveRecord](https://rubygems.org/gems/activerecord) adapter for quering
5
+ APIs over Standard API (https://github.com/waratuman/standardapi).
6
+
7
+
8
+ TODO:
9
+ =====
10
+ Make `cookie_store` and optional
11
+ stream building model instances with wankel
@@ -1,48 +1,52 @@
1
- module ActiveRecord::Associations::Builder
2
- class HasAndBelongsToMany # :nodoc:
3
-
4
- def through_model
5
- habtm = JoinTableResolver.build lhs_model, association_name, options
6
-
7
- join_model = Class.new(lhs_model.base_class.superclass) {
8
- class << self;
9
- attr_accessor :class_resolver
10
- attr_accessor :name
11
- attr_accessor :table_name_resolver
12
- attr_accessor :left_reflection
13
- attr_accessor :right_reflection
14
- end
15
-
16
- def self.table_name
17
- table_name_resolver.join_table
18
- end
19
-
20
- def self.compute_type(class_name)
21
- class_resolver.compute_type class_name
22
- end
23
-
24
- def self.add_left_association(name, options)
25
- belongs_to name, options
26
- self.left_reflection = _reflect_on_association(name)
27
- end
28
-
29
- def self.add_right_association(name, options)
30
- rhs_name = name.to_s.singularize.to_sym
31
- belongs_to rhs_name, options
32
- self.right_reflection = _reflect_on_association(rhs_name)
33
- end
34
-
35
- }
36
-
37
- join_model.name = "HABTM_#{association_name.to_s.camelize}"
38
- join_model.table_name_resolver = habtm
39
- join_model.class_resolver = lhs_model
40
- join_model.primary_key = nil
41
-
42
- join_model.add_left_association :left_side, anonymous_class: lhs_model
43
- join_model.add_right_association association_name, belongs_to_options(options)
44
- join_model
45
- end
46
-
47
- end
48
- end
1
+ # module ActiveRecord::Associations::Builder
2
+ # class HasAndBelongsToMany # :nodoc:
3
+ #
4
+ # def through_model
5
+ # habtm = JoinTableResolver.build lhs_model, association_name, options
6
+ #
7
+ # join_model = Class.new(lhs_model.base_class.superclass) { # Don't use ActiveRecord::Base here because that might not be the abstract class that we need and the connection may be different
8
+ # class << self;
9
+ # attr_accessor :left_model
10
+ # attr_accessor :name
11
+ # attr_accessor :table_name_resolver
12
+ # attr_accessor :left_reflection
13
+ # attr_accessor :right_reflection
14
+ # end
15
+ #
16
+ # def self.table_name
17
+ # table_name_resolver.join_table
18
+ # end
19
+ #
20
+ # def self.compute_type(class_name)
21
+ # left_model.compute_type class_name
22
+ # end
23
+ #
24
+ # def self.add_left_association(name, options)
25
+ # belongs_to name, options
26
+ # self.left_reflection = _reflect_on_association(name)
27
+ # end
28
+ #
29
+ # def self.add_right_association(name, options)
30
+ # rhs_name = name.to_s.singularize.to_sym
31
+ # belongs_to rhs_name, options
32
+ # self.right_reflection = _reflect_on_association(rhs_name)
33
+ # end
34
+ #
35
+ # def self.retrieve_connection
36
+ # left_model.retrieve_connection
37
+ # end
38
+ #
39
+ # }
40
+ #
41
+ # join_model.name = "HABTM_#{association_name.to_s.camelize}"
42
+ # join_model.table_name_resolver = habtm
43
+ # join_model.class_resolver = lhs_model
44
+ # join_model.primary_key = nil
45
+ #
46
+ # join_model.add_left_association :left_side, anonymous_class: lhs_model
47
+ # join_model.add_right_association association_name, belongs_to_options(options)
48
+ # join_model
49
+ # end
50
+ #
51
+ # end
52
+ # end
@@ -3,9 +3,9 @@ module ActiveRecord
3
3
 
4
4
  private
5
5
 
6
- # "#{quoted_table_name}.#{quoted_primary_key} ASC"
6
+ # Arrrr Rails hard coding SQL
7
7
  def batch_order
8
- {:id => :asc}
8
+ primary_key ? {primary_key => :asc} : {}
9
9
  end
10
10
 
11
11
  end
@@ -1,28 +1,28 @@
1
- module ActiveRecord
2
- module Calculations
3
- def pluck(*column_names)
4
-
5
- # column_names.map! do |column_name|
6
- # if column_name.is_a?(Symbol) && attribute_alias?(column_name)
7
- # attribute_alias(column_name)
8
- # else
9
- # column_name.to_s
10
- # end
11
- # end
12
-
13
- if has_include?(column_names.first)
14
- construct_relation_for_association_calculations.pluck(*column_names)
15
- else
16
- relation = spawn
17
- relation.select_values = column_names.map { |cn|
18
- columns_hash.key?(cn) ? arel_table[cn] : cn
19
- }
20
-
21
- result = klass.connection.exec_query(relation.arel, nil, relation.arel.bind_values + bind_values)
22
- result.cast_values(klass.column_types)
23
- end
24
- end
25
-
26
- end
27
- end
28
-
1
+ # module ActiveRecord
2
+ # module Calculations
3
+ # def pluck(*column_names)
4
+ #
5
+ # # column_names.map! do |column_name|
6
+ # # if column_name.is_a?(Symbol) && attribute_alias?(column_name)
7
+ # # attribute_alias(column_name)
8
+ # # else
9
+ # # column_name.to_s
10
+ # # end
11
+ # # end
12
+ #
13
+ # if has_include?(column_names.first)
14
+ # construct_relation_for_association_calculations.pluck(*column_names)
15
+ # else
16
+ # relation = spawn
17
+ # relation.select_values = column_names.map { |cn|
18
+ # columns_hash.key?(cn) ? arel_table[cn] : cn
19
+ # }
20
+ #
21
+ # result = klass.connection.exec_query(relation.arel, nil, relation.arel.bind_values + bind_values)
22
+ # result.cast_values(klass.column_types)
23
+ # end
24
+ # end
25
+ #
26
+ # end
27
+ # end
28
+ #
@@ -1,22 +1,36 @@
1
1
  module ActiveRecord
2
2
  module FinderMethods
3
-
4
- def find_with_associations
5
- arel.eager_load = Arel::Nodes::EagerLoad.new(eager_load_values)
6
3
 
4
+ def find_with_associations
5
+ join_dependency = nil
6
+ aliases = nil
7
+ relation = if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
8
+ arel.eager_load = Arel::Nodes::EagerLoad.new(eager_load_values)
9
+ self
10
+ else
11
+ join_dependency = construct_join_dependency(joins_values)
12
+ aliases = join_dependency.aliases
13
+ apply_join_dependency(select(aliases.columns), join_dependency)
14
+ end
15
+
7
16
  if block_given?
8
- yield self
17
+ yield relation
9
18
  else
10
- if ActiveRecord::NullRelation === self
19
+ if ActiveRecord::NullRelation === relation
11
20
  []
12
21
  else
13
- rows = connection.select_all(arel, 'SQL', arel.bind_values + bind_values)
14
- instantiate_with_associations(rows, self)
15
- # join_dependency.instantiate(rows, aliases)
22
+ arel = relation.arel
23
+ rows = connection.select_all(arel, 'SQL', arel.bind_values + relation.bind_values)
24
+ if join_dependency
25
+ join_dependency.instantiate(rows, aliases)
26
+ else
27
+ instantiate_with_associations(rows, relation)
28
+ end
29
+
16
30
  end
17
31
  end
18
32
  end
19
-
33
+
20
34
  def instantiate_with_associations(result_set, klass)
21
35
  seen = Hash.new { |h, parent_klass|
22
36
  h[parent_klass] = Hash.new { |i, parent_id|
@@ -26,20 +40,20 @@ module ActiveRecord
26
40
 
27
41
  model_cache = Hash.new { |h,klass| h[klass] = {} }
28
42
  parents = model_cache[self.base_class]
29
-
43
+
30
44
  result_set.each { |row_hash|
31
45
  parent = parents[row_hash[primary_key]] ||= instantiate(row_hash.select{|k,v| column_names.include?(k.to_s) })
32
46
  construct(parent, row_hash.select{|k,v| !column_names.include?(k.to_s) }, seen, model_cache)
33
47
  }
34
-
48
+
35
49
  parents.values
36
50
  end
37
-
51
+
38
52
  def construct(parent, relations, seen, model_cache)
39
53
  relations.each do |key, attributes|
40
54
  reflection = parent.class.reflect_on_association(key)
41
55
  next unless reflection
42
-
56
+
43
57
  if reflection.collection?
44
58
  other = parent.association(reflection.name)
45
59
  other.loaded!
@@ -49,7 +63,7 @@ module ActiveRecord
49
63
  construct(model, attributes.select{|k,v| !reflection.klass.column_names.include?(k.to_s) }, seen, model_cache)
50
64
  end
51
65
  end
52
-
66
+
53
67
  if !reflection.collection?
54
68
  construct_association(parent, reflection, attributes, seen, model_cache)
55
69
  else
@@ -57,13 +71,13 @@ module ActiveRecord
57
71
  construct_association(parent, reflection, row, seen, model_cache)
58
72
  end
59
73
  end
60
-
74
+
61
75
  end
62
76
  end
63
-
77
+
64
78
  def construct_association(parent, reflection, attributes, seen, model_cache)
65
79
  return if attributes.nil?
66
-
80
+
67
81
  klass = if reflection.polymorphic?
68
82
  parent.send(reflection.foreign_type).constantize.base_class
69
83
  else
@@ -71,12 +85,12 @@ module ActiveRecord
71
85
  end
72
86
  id = attributes[klass.primary_key]
73
87
  model = seen[parent.class.base_class][parent.id][klass][id]
74
-
88
+
75
89
  if model
76
90
  construct(model, attributes.select{|k,v| !klass.column_names.include?(k.to_s) }, seen, model_cache)
77
91
 
78
92
  other = parent.association(reflection.name)
79
-
93
+
80
94
  if reflection.collection?
81
95
  other.target.push(model)
82
96
  else
@@ -90,7 +104,7 @@ module ActiveRecord
90
104
  construct(model, attributes.select{|k,v| !klass.column_names.include?(k.to_s) }, seen, model_cache)
91
105
  end
92
106
  end
93
-
107
+
94
108
 
95
109
  def construct_model(record, reflection, id, attributes, seen, model_cache)
96
110
  klass = if reflection.polymorphic?
@@ -98,7 +112,7 @@ module ActiveRecord
98
112
  else
99
113
  reflection.klass
100
114
  end
101
-
115
+
102
116
  model = model_cache[klass][id] ||= klass.instantiate(attributes)
103
117
  other = record.association(reflection.name)
104
118
 
@@ -111,7 +125,7 @@ module ActiveRecord
111
125
  other.set_inverse_instance(model)
112
126
  model
113
127
  end
114
-
128
+
115
129
  end
116
130
 
117
131
  end
@@ -0,0 +1,23 @@
1
+ module ActiveRecord
2
+ module QueryMethods
3
+
4
+ def reverse_sql_order(order_query)
5
+ order_query = [arel_table[primary_key].asc] if order_query.empty?
6
+
7
+ order_query.flat_map do |o|
8
+ case o
9
+ when Arel::Nodes::Ordering
10
+ o.reverse
11
+ when String
12
+ o.to_s.split(',').map! do |s|
13
+ s.strip!
14
+ s.gsub!(/\sasc\Z/i, ' DESC') || s.gsub!(/\sdesc\Z/i, ' ASC') || s.concat(' DESC')
15
+ end
16
+ else
17
+ o
18
+ end
19
+ end
20
+ end
21
+
22
+ end
23
+ end
@@ -1,11 +1,11 @@
1
1
  module ActiveRecord
2
2
  class Relation
3
+
3
4
  def to_sql
4
5
  @to_sql ||= begin
5
6
  relation = self
6
7
  connection = klass.connection
7
- visitor = connection.visitor
8
- collector = connection.collector
8
+ visitor = connection.visitor.is_a?(Arel::Visitors::Sunstone) ? Arel::Visitors::ToSql.new(connection) : connection.visitor
9
9
 
10
10
  if eager_loading?
11
11
  find_with_associations { |rel| relation = rel }
@@ -14,13 +14,11 @@ module ActiveRecord
14
14
  arel = relation.arel
15
15
  binds = (arel.bind_values + relation.bind_values).dup
16
16
  binds.map! { |bv| connection.quote(*bv.reverse) }
17
- collect = visitor.accept(arel.ast, collector)
18
- if collector.is_a?(Arel::Collectors::Sunstone)
19
- collect.compile(binds)
20
- else
21
- collect.substitute_binds(binds).join
22
- end
17
+ collect = visitor.accept(arel.ast, Arel::Collectors::Bind.new)
18
+ collect.substitute_binds(binds).join
23
19
  end
24
20
  end
21
+
22
+
25
23
  end
26
24
  end
@@ -1,23 +1,29 @@
1
- module ActiveRecord
2
- class PredicateBuilder # :nodoc:
3
-
4
- def self.expand(klass, table, column, value)
5
- queries = []
6
-
7
- # In standard Rails where takes :table => { columns }, but in sunstone we
8
- # can can do nested tables eg: where(:properties => { :regions => {:id => 1}})
9
- if klass && reflection = klass._reflect_on_association(column)
10
- if reflection.polymorphic? && base_class = polymorphic_base_class_from_value(value)
11
- queries << build(table[reflection.foreign_type], base_class)
12
- end
13
-
14
- # column = reflection.foreign_key
15
- column # Don't need Rails to assume we are referencing a table
16
- end
17
-
18
- queries << build(table[column], value)
19
- queries
20
- end
21
-
22
- end
23
- end
1
+ # module ActiveRecord
2
+ # class PredicateBuilder # :nodoc:
3
+ #
4
+ # def self.expand(klass, table, column, value)
5
+ # queries = []
6
+ #
7
+ # # In standard Rails where takes :table => { columns }, but in sunstone we
8
+ # # can can do nested tables eg: where(:properties => { :regions => {:id => 1}})
9
+ # if klass && reflection = klass._reflect_on_association(column)
10
+ # base_class = polymorphic_base_class_from_value(value)
11
+ #
12
+ # if reflection.polymorphic? && base_class
13
+ # queries << build(table[reflection.foreign_type], base_class)
14
+ # end
15
+ #
16
+ # column = reflection.foreign_key
17
+ #
18
+ # if base_class
19
+ # primary_key = reflection.association_primary_key(base_class)
20
+ # value = convert_value_to_association_ids(value, primary_key)
21
+ # end
22
+ # end
23
+ #
24
+ # queries << build(table[column], value)
25
+ # queries
26
+ # end
27
+ #
28
+ # end
29
+ # end
@@ -1,23 +1,36 @@
1
1
  module ActiveRecord
2
2
  class StatementCache
3
3
  class PartialQuery
4
-
5
- def initialize collector
6
- @collector = collector
7
- @indexes = collector.value.find_all { |thing|
8
- Arel::Nodes::BindParam === thing
9
- }
4
+
5
+ def initialize(values, sunstone=false)
6
+ @values = values
7
+ if sunstone
8
+ @indexes = values.value.find_all { |thing|
9
+ Arel::Nodes::BindParam === thing
10
+ }
11
+ else
12
+ @indexes = values.each_with_index.find_all { |thing,i|
13
+ Arel::Nodes::BindParam === thing
14
+ }.map(&:last)
15
+ end
10
16
  end
11
17
 
12
18
  def sql_for(binds, connection)
13
19
  binds = binds.dup
14
- @collector.compile(binds)
20
+
21
+ if connection.is_a?(ActiveRecord::ConnectionAdapters::SunstoneAPIAdapter)
22
+ @values.compile(binds)
23
+ else
24
+ val = @values.dup
25
+ @indexes.each { |i| val[i] = connection.quote(*binds.shift.reverse) }
26
+ val.join
27
+ end
15
28
  end
16
29
  end
17
30
 
18
31
  def self.partial_query(visitor, ast, collector)
19
32
  collected = visitor.accept(ast, collector)
20
- PartialQuery.new collected
33
+ PartialQuery.new(visitor.is_a?(Arel::Visitors::Sunstone) ? collected : collected.value, visitor.is_a?(Arel::Visitors::Sunstone))
21
34
  end
22
35
 
23
36
  end