Module: StandardAPI::Helpers

Defined in:
lib/standard_api/helpers.rb

Instance Method Summary collapse

Instance Method Details

#association_cache_key(record, relation, subincludes) ⇒ Object



40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
# File 'lib/standard_api/helpers.rb', line 40

def association_cache_key(record, relation, subincludes)
  timestamp = ["#{relation}_cached_at"] + cached_at_columns_for_includes(subincludes).map {|c| "#{relation}_#{c}"}
  timestamp.map! { |col| record.send(col) }
  timestamp = timestamp.max
  
  case association = record.class.reflect_on_association(relation)
  when ActiveRecord::Reflection::HasManyReflection, ActiveRecord::Reflection::HasAndBelongsToManyReflection, ActiveRecord::Reflection::HasOneReflection, ActiveRecord::Reflection::ThroughReflection
    "#{record.model_name.cache_key}/#{record.id}/#{includes_to_cache_key(relation, subincludes)}-#{timestamp.utc.to_s(record.cache_timestamp_format)}"
  when ActiveRecord::Reflection::BelongsToReflection
    klass = association.options[:polymorphic] ? record.send(association.foreign_type).constantize : association.klass
    if subincludes.empty?
      "#{klass.model_name.cache_key}/#{record.send(association.foreign_key)}-#{timestamp.utc.to_s(klass.cache_timestamp_format)}"
    else
      "#{klass.model_name.cache_key}/#{record.send(association.foreign_key)}/#{digest_hash(sort_hash(subincludes))}-#{timestamp.utc.to_s(klass.cache_timestamp_format)}"
    end
  else
    raise ArgumentError, 'Unkown association type'
  end
end

#cache_key(record, includes) ⇒ Object



21
22
23
24
25
26
27
28
29
# File 'lib/standard_api/helpers.rb', line 21

def cache_key(record, includes)
  timestamp_keys = ['cached_at'] + record.class.column_names.select{|x| x.ends_with? "_cached_at"}
  if includes.empty?
    record.cache_key(*timestamp_keys)
  else
    timestamp = timestamp_keys.map { |attr| record[attr]&.to_time }.compact.max
    "#{record.model_name.cache_key}/#{record.id}-#{digest_hash(sort_hash(includes))}-#{timestamp.utc.to_s(record.cache_timestamp_format)}"
  end
end

#cached_at_columns_for_includes(includes) ⇒ Object



60
61
62
63
64
# File 'lib/standard_api/helpers.rb', line 60

def cached_at_columns_for_includes(includes)
  includes.select { |k,v| !['when', 'where', 'limit', 'order', 'distinct'].include?(k) }.map do |k, v|
    ["#{k}_cached_at"] + cached_at_columns_for_includes(v).map { |v2| "#{k}_#{v2}" }
  end.flatten
end

#can_cache?(klass, includes) ⇒ Boolean

Returns:

  • (Boolean)


12
13
14
15
16
17
18
19
# File 'lib/standard_api/helpers.rb', line 12

def can_cache?(klass, includes)
  cache_columns = ['cached_at'] + cached_at_columns_for_includes(includes)
  if (cache_columns - klass.column_names).empty?
    true
  else
    false
  end
end

#can_cache_relation?(klass, relation, subincludes) ⇒ Boolean

Returns:

  • (Boolean)


31
32
33
34
35
36
37
38
# File 'lib/standard_api/helpers.rb', line 31

def can_cache_relation?(klass, relation, subincludes)
  cache_columns = ["#{relation}_cached_at"] + cached_at_columns_for_includes(subincludes).map {|c| "#{relation}_#{c}"}
  if (cache_columns - klass.column_names).empty?
    true
  else
    false
  end
end

#digest_hash(*hashes) ⇒ Object



85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/standard_api/helpers.rb', line 85

def digest_hash(*hashes)
  hashes.compact!
  hashes.map! { |h| sort_hash(h) }

  digest =  Digest::MD5.new()
  hashes.each do |hash|
    hash.each do |key, value|
      digest << key.to_s
      if value.is_a?(Hash)
        digest << digest_hash(value)
      else
        digest << value.to_s
      end
    end
  end

  digest.hexdigest
end

#includes_to_cache_key(relation, subincludes) ⇒ Object



66
67
68
69
70
71
72
# File 'lib/standard_api/helpers.rb', line 66

def includes_to_cache_key(relation, subincludes)
  if subincludes.empty?
    relation.to_s
  else
    "#{relation}-#{digest_hash(sort_hash(subincludes))}"
  end
end

#json_column_type(sql_type) ⇒ Object



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
# File 'lib/standard_api/helpers.rb', line 104

def json_column_type(sql_type)
  case sql_type
  when /character varying(\(\d+\))?/
    'string'
  when 'timestamp without time zone'
    'datetime'
  when 'time without time zone'
    'datetime'
  when 'text'
    'string'
  when 'json'
    'hash'
  when 'bigint'
    'integer'
  when 'integer'
    'integer'
  when 'jsonb'
    'hash'
  when 'inet'
    'string' # TODO: should be inet
  when 'hstore'
    'hash'
  when 'date'
    'datetime'
  when /numeric(\(\d+(,\d+)?\))?/
    'decimal'
  when 'double precision'
    'decimal'
  when 'ltree'
   'string'
  when 'boolean'
    'boolean'
  when 'geometry'
    'ewkb'
  when 'uuid' # TODO: should be uuid
    'string'
  end
end

#model_partial(record) ⇒ Object



4
5
6
7
8
9
10
# File 'lib/standard_api/helpers.rb', line 4

def model_partial(record)
  if lookup_context.exists?(record.model_name.element, record.model_name.plural, true)
    [record.model_name.plural, record.model_name.element].join('/')
  else
    'application/record'
  end
end

#sort_hash(hash) ⇒ Object



74
75
76
77
78
79
80
81
82
83
# File 'lib/standard_api/helpers.rb', line 74

def sort_hash(hash)
  hash.keys.sort.reduce({}) do |seed, key|
    if seed[key].is_a?(Hash)
      seed[key] = sort_hash(hash[key])
    else
      seed[key] = hash[key]
    end
    seed
  end
end