Module: Kirei::Model::ClassMethods

Extended by:
T::Generic, T::Sig
Includes:
BaseClassInterface
Defined in:
lib/kirei/model/class_methods.rb

Instance Method Summary collapse

Instance Method Details

#allObject



53
54
55
# File 'lib/kirei/model/class_methods.rb', line 53

def all
  resolve(query.all)
end

#cast_to_vector(value) ⇒ Object



117
118
119
120
121
122
123
124
125
# File 'lib/kirei/model/class_methods.rb', line 117

def cast_to_vector(value)
  return value if value.is_a?(Sequel::SQL::Expression) || value.is_a?(Sequel::SQL::PlaceholderLiteralString)

  Kernel.raise("'pg_array' extension is not enabled") unless db.extension(:pg_array)

  pg_array = T.unsafe(Sequel).pg_array(value)

  Sequel.lit("?::vector", pg_array)
end

#create(hash) ⇒ Object



64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
# File 'lib/kirei/model/class_methods.rb', line 64

def create(hash)
  # instantiate a new object to ensure we use default values defined in the model
  without_id = !hash.key?(:id)
  hash[:id] = "kirei-fake-id" if without_id
  new_record = from_hash(Helpers.deep_stringify_keys(hash))
  all_attributes = T.let(new_record.serialize, T::Hash[String, T.untyped])
  all_attributes.delete("id") if without_id && all_attributes["id"] == "kirei-fake-id"

  wrap_jsonb_non_primivitives!(all_attributes)

  if new_record.respond_to?(:created_at) && all_attributes["created_at"].nil?
    all_attributes["created_at"] = Time.now.utc
  end
  if new_record.respond_to?(:updated_at) && all_attributes["updated_at"].nil?
    all_attributes["updated_at"] = Time.now.utc
  end

  pkey = T.let(query.insert(all_attributes), String)

  T.must(find_by({ id: pkey }))
end

#dbObject



33
34
35
# File 'lib/kirei/model/class_methods.rb', line 33

def db
  App.raw_db_connection
end

#exec_sql(sql, params) ⇒ Object



38
39
40
41
# File 'lib/kirei/model/class_methods.rb', line 38

def exec_sql(sql, params)
  # Splats aren't supported in Sorbet, see: https://sorbet.org/docs/error-reference#7019
  T.unsafe(db).fetch(sql, *params).all
end

#find_by(hash) ⇒ Object



132
133
134
# File 'lib/kirei/model/class_methods.rb', line 132

def find_by(hash)
  resolve_first(query.where(hash))
end

#generate_human_idObject



182
183
184
185
186
187
# File 'lib/kirei/model/class_methods.rb', line 182

def generate_human_id
  Kirei::Model::HumanIdGenerator.call(
    length: human_id_length,
    prefix: human_id_prefix,
  )
end

#human_id_lengthObject



171
# File 'lib/kirei/model/class_methods.rb', line 171

def human_id_length = 6

#human_id_prefixObject



175
# File 'lib/kirei/model/class_methods.rb', line 175

def human_id_prefix = model_name

#model_nameObject



23
24
25
# File 'lib/kirei/model/class_methods.rb', line 23

def model_name
  Kirei::Helpers.underscore(T.must(name.split("::").last))
end

#queryObject



28
29
30
# File 'lib/kirei/model/class_methods.rb', line 28

def query
  db[table_name.to_sym]
end

#resolve(query, strict = nil) ⇒ Object



147
148
149
150
151
152
153
154
155
# File 'lib/kirei/model/class_methods.rb', line 147

def resolve(query, strict = nil)
  strict_loading = strict.nil? ? App.config.db_strict_type_resolving : strict

  query.map do |row|
    row = T.cast(row, T::Hash[Symbol, T.untyped])
    row.transform_keys!(&:to_s) # sequel returns symbolized keys
    from_hash(row, strict_loading)
  end
end

#resolve_first(query, strict = nil) ⇒ Object



163
164
165
166
167
# File 'lib/kirei/model/class_methods.rb', line 163

def resolve_first(query, strict = nil)
  strict_loading = strict.nil? ? App.config.db_strict_type_resolving : strict

  resolve(query.limit(1), strict_loading).first
end

#table_nameObject



18
19
20
# File 'lib/kirei/model/class_methods.rb', line 18

def table_name
  @table_name ||= T.let("#{model_name}s", T.nilable(String))
end

#vector_column?(column_name) ⇒ Boolean

Returns:

  • (Boolean)


108
109
110
111
112
113
114
# File 'lib/kirei/model/class_methods.rb', line 108

def vector_column?(column_name)
  _col_name, col_info = T.let(
    db.schema(table_name.to_sym).find { _1[0] == column_name.to_sym },
    [Symbol, T::Hash[Symbol, T.untyped]],
  )
  col_info.fetch(:db_type).match?(/vector\(\d+\)/)
end

#where(hash) ⇒ Object



48
49
50
# File 'lib/kirei/model/class_methods.rb', line 48

def where(hash)
  resolve(query.where(hash))
end

#wrap_jsonb_non_primivitives!(attributes) ⇒ Object



88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/kirei/model/class_methods.rb', line 88

def wrap_jsonb_non_primivitives!(attributes)
  # setting `@raw_db_connection.wrap_json_primitives = true`
  # only works on JSON primitives, but not on blank hashes/arrays
  return unless App.config.db_extensions.include?(:pg_json)

  attributes.each_pair do |key, value|
    if vector_column?(key.to_s)
      attributes[key] = cast_to_vector(value)
    elsif value.is_a?(Hash) || value.is_a?(Array)
      attributes[key] = T.unsafe(Sequel).pg_jsonb_wrap(value)
    end
  end
end