Class: Arel::Collectors::Sunstone

Inherits:
Bind
  • Object
show all
Defined in:
lib/arel/collectors/sunstone.rb

Constant Summary collapse

MAX_URI_LENGTH =
2083

Instance Attribute Summary collapse

Instance Method Summary collapse

Constructor Details

#initializeSunstone

Returns a new instance of Sunstone.



14
15
16
17
# File 'lib/arel/collectors/sunstone.rb', line 14

def initialize
  @join_source = []
  @binds = []
end

Instance Attribute Details

#bindsObject (readonly)

Returns the value of attribute binds.



12
13
14
# File 'lib/arel/collectors/sunstone.rb', line 12

def binds
  @binds
end

#columnsObject

Returns the value of attribute columns.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def columns
  @columns
end

#distinctObject

Returns the value of attribute distinct.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def distinct
  @distinct
end

#distinct_onObject

Returns the value of attribute distinct_on.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def distinct_on
  @distinct_on
end

#eager_loadsObject

Returns the value of attribute eager_loads.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def eager_loads
  @eager_loads
end

#idObject

Returns the value of attribute id.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def id
  @id
end

#join_sourceObject

This is used to removed an bind values. It is not used in the request



10
11
12
# File 'lib/arel/collectors/sunstone.rb', line 10

def join_source
  @join_source
end

#limitObject

Returns the value of attribute limit.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def limit
  @limit
end

#offsetObject

Returns the value of attribute offset.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def offset
  @offset
end

#operationObject

Returns the value of attribute operation.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def operation
  @operation
end

#orderObject

Returns the value of attribute order.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def order
  @order
end

#request_typeObject

Returns the value of attribute request_type.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def request_type
  @request_type
end

#tableObject

Returns the value of attribute table.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def table
  @table
end

#updatesObject

Returns the value of attribute updates.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def updates
  @updates
end

#whereObject

Returns the value of attribute where.



7
8
9
# File 'lib/arel/collectors/sunstone.rb', line 7

def where
  @where
end

Instance Method Details

#add_bind(bind) ⇒ Object



19
20
21
22
# File 'lib/arel/collectors/sunstone.rb', line 19

def add_bind(bind)
  @binds << bind.value_for_database
  bind
end

#compile(bvs, conn = nil) ⇒ Object



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
# File 'lib/arel/collectors/sunstone.rb', line 94

def compile bvs, conn = nil
  path = "/#{table}"
  headers = {}
  request_type_override = nil

  body = nil
  if updates
    body = {
      table.singularize => substitute_binds(updates.clone, bvs)
    }
  end

  if !join_source.empty?
    substitute_binds(join_source.clone, bvs)
  end

  params = {}
  params[:where] = substitute_binds(where.clone, bvs) if where

  if eager_loads
    params[:include] = eager_loads.clone
  end

  if distinct_on
    params[:distinct_on] = distinct_on
  elsif distinct
    params[:distinct] = true 
  end

  if limit.is_a?(Arel::Nodes::BindParam)
    params[:limit] = substitute_binds(limit, bvs)
  elsif limit
    params[:limit] = limit
  end

  params[:order] = substitute_binds(order, bvs) if order

  if offset.is_a?(Arel::Nodes::BindParam)
    params[:offset] = substitute_binds(offset, bvs)
  elsif offset
    params[:offset] = offset
  end
  
  case operation
  when :count
    path += "/#{operation}"
  when :calculate
    path += "/calculate"
    params[:select] = columns
  when :update, :delete
    path += "/#{params[:where]['id']}"
    params.delete(:where)
  end

  if params.size > 0 && request_type == Net::HTTP::Get
    newpath = path + "?#{CGI.escape(MessagePack.pack(params))}"
    if newpath.length > MAX_URI_LENGTH
      request_type_override = Net::HTTP::Post
      headers['X-Http-Method-Override'] = 'GET'
      if body
        body.merge!(params)
      else
        body = params
      end
    else
      path = newpath
      headers['Query-Encoding'] = 'application/msgpack'
    end
  end

  request = (request_type_override || request_type).new(path)
  headers.each { |k,v| request[k] = v }
  request.instance_variable_set(:@sunstone_calculation, true) if [:calculate, :delete].include?(operation)

  if body
    request.body = body.to_json
  end

  request
end

#flatten_nested(obj) ⇒ Object



77
78
79
80
81
82
83
84
85
# File 'lib/arel/collectors/sunstone.rb', line 77

def flatten_nested(obj)
  if obj.is_a?(Array)
    obj.map { |w| flatten_nested(w) }
  elsif obj.is_a?(Hash)
    obj.map{ |k,v| [k, flatten_nested(v)] }.flatten
  else
    obj
  end
end

#sql_for(bvs, conn = nil) ⇒ Object



91
92
93
# File 'lib/arel/collectors/sunstone.rb', line 91

def sql_for(bvs, conn = nil)
  compile(bvs, conn)
end

#substitute_binds(hash, bvs) ⇒ Object



24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
# File 'lib/arel/collectors/sunstone.rb', line 24

def substitute_binds hash, bvs
  if hash.is_a?(Array)
    hash.map do |v|
      if v.is_a?(ActiveRecord::Relation::QueryAttribute)
        new_v = bvs.shift
        if new_v.is_a?(ActiveRecord::Relation::QueryAttribute)
          new_v.value_for_database
        else
          v.type.serialize(new_v)
        end
      elsif v.is_a?(Arel::Nodes::BindParam)
        bvs.shift#.value_for_database
      elsif v.is_a?(Hash) || v.is_a?(Array)
        substitute_binds(v, bvs)
      else
        v
      end
    end
  elsif hash.is_a?(Hash)
    newhash = {}
    hash.each do |k, v|
      if v.is_a?(ActiveRecord::Relation::QueryAttribute)
        new_v = bvs.shift
        newhash[k] = if new_v.is_a?(ActiveRecord::Relation::QueryAttribute)
          new_v.value_for_database
        else
          v.type.serialize(new_v)
        end
      elsif v.is_a?(Arel::Nodes::BindParam)
        newhash[k] = bvs.shift || v.value.value_for_database
      elsif v.is_a?(Hash)
        newhash[k] = substitute_binds(v, bvs)
      elsif v.is_a?(Array)
        newhash[k] = substitute_binds(v, bvs)
      else
        newhash[k] = v
      end
    end
    newhash
  elsif hash.is_a?(Arel::Nodes::BindParam)
    bvs.shift
  elsif hash.is_a?(ActiveRecord::Relation::QueryAttribute)
    new_v = bvs.shift
    if new_v.is_a?(ActiveRecord::Relation::QueryAttribute)
      new_v.value_for_database
    else
      v.type.serialize(new_v)
    end
  else
    bvs.shift
  end
end

#valueObject



87
88
89
# File 'lib/arel/collectors/sunstone.rb', line 87

def value
  self
end