Class: AuroraDataApi::Depot

Inherits:
Object
  • Object
show all
Defined in:
lib/aurora-data-api/depot.rb

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(model, block) ⇒ Depot

Returns a new instance of Depot.



15
16
17
18
19
20
# File 'lib/aurora-data-api/depot.rb', line 15

def initialize(model, block)
  @model = model
  instance_eval { block.call }
  @data_service = DataService.new
  @observed_utc_offset = TZInfo::Timezone.get(ENV["TZ"] || "UTC").observed_utc_offset
end

Class Method Details

.[](model, &block) ⇒ Object



8
9
10
11
12
13
# File 'lib/aurora-data-api/depot.rb', line 8

def self.[](model, &block)
  # @type var block: Proc
  depot = new(model, block)
  AuroraDataApi.const_set("#{model.name}Depot".to_sym, depot)
  depot
end

Instance Method Details

#column_data(meta, col) ⇒ Object



104
105
106
107
108
109
110
111
112
113
114
115
116
# File 'lib/aurora-data-api/depot.rb', line 104

def column_data(meta, col)
  return nil if col.is_null
  case meta.type_name
  when "text"
    col.value.gsub("''", "'")
  when "timestamptz"
    Time.parse(col.value) + @observed_utc_offset
  when "date"
    Date.parse(col.value)
  else
    col.value
  end
end

#count(str = "", **params) ⇒ Object



62
63
64
65
66
67
# File 'lib/aurora-data-api/depot.rb', line 62

def count(str = "", **params)
  query(
    "SELECT COUNT(\"#{literal_id}\") FROM \"#{table_name}\" #{str};",
    **params
  ).records[0][0].long_value
end

#delete(obj) ⇒ Object



54
55
56
57
58
59
60
# File 'lib/aurora-data-api/depot.rb', line 54

def delete(obj)
  query(<<~SQL, id: obj.id)
    DELETE FROM "#{obj.table_name}" WHERE "#{obj.literal_id}" = :id;
  SQL
  obj._destroy
  true
end

#insert(obj) ⇒ Object



30
31
32
33
34
35
36
37
38
39
40
41
# File 'lib/aurora-data-api/depot.rb', line 30

def insert(obj)
  obj.set_timestamp(at: :create)
  params = obj.build_params
  res = query(<<~SQL, **params)
    INSERT INTO "#{obj.table_name}"
      (#{params.keys.map { |k| "\"#{k}\"" }.join(",")})
      VALUES
      (#{params.keys.map { |k| ":#{k}" }.join(",")})
      RETURNING "#{obj.literal_id}";
  SQL
  obj._set_id(res.records[0][0].value)
end

#literal_idObject



26
27
28
# File 'lib/aurora-data-api/depot.rb', line 26

def literal_id
  @literal_id ||= Model::SCHEMA[@model.name.to_sym][:literal_id] || :id
end

#query(str, **params) ⇒ Object



118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/aurora-data-api/depot.rb', line 118

def query(str, **params)
  @data_service.execute({
    sql: str,
    parameters: params.map do |param|
      hash = {name: param[0].to_s, value: {}}
      case param[1]
      when Integer
        hash[:value][:long_value] = param[1]
      when Float
        hash[:value][:double_value] = param[1]
      when TrueClass, FalseClass
        hash[:value][:boolean_value] = param[1]
      else # TODO: confirm format and timezone when Time
        hash[:value][:string_value] = param[1].to_s.gsub("'", "''")
      end
      hash
    end
  })
end

#select(str, **params) ⇒ Object



69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/aurora-data-api/depot.rb', line 69

def select(str, **params)
  result = query("select * from \"#{table_name}\" #{str};", **params)
  related_objects = {}
  result.records.map do |record|
    relationships = {}
    attributes = {}.tap do |attrribute|
      result..each_with_index do |meta, index|
        if meta.table_name == table_name.to_s
          attrribute[meta.name.to_sym] = column_data(meta, record[index])
        else
          table_sym = meta.table_name.to_sym
          name, rel_model = @model.relationship_by(table_sym)
          if name
            relationships[name] ||= {}
            relationships[name][:attr] ||= {}
            relationships[name][:model] ||= rel_model
            relationships[name][:attr][meta.name.to_sym] = column_data(meta, record[index])
          end
        end
      end
    end
    relationships.each do |name, data|
      related_objects[name] ||= {}
      id = data[:attr][literal_id]
      obj = related_objects.dig(name, id)
      unless obj
        obj = Kernel.const_get(data[:model]).new(**data[:attr])
        related_objects[name][id] = obj
      end
      attributes[name] = obj
    end
    @model.new(attributes)
  end
end

#table_nameObject



22
23
24
# File 'lib/aurora-data-api/depot.rb', line 22

def table_name
  @table_name ||= Model::SCHEMA[@model.name.to_sym][:table_name] || "#{@model.to_s.downcase}s"
end

#update(obj) ⇒ Object



43
44
45
46
47
48
49
50
51
52
# File 'lib/aurora-data-api/depot.rb', line 43

def update(obj)
  obj.set_timestamp(at: :update)
  params = obj.build_params
  query(<<~SQL, **params)
    UPDATE "#{obj.table_name}" SET
      #{params.keys.reject { |k| k == obj.literal_id }.map { |k| "\"#{k}\" = :#{k}" }.join(", ")}
      WHERE "#{obj.literal_id}" = :#{obj.literal_id};
  SQL
  true
end