Class: YesRecord
Defined Under Namespace
Classes: Column, Query, QueryNotFound, RecordNotFound
Constant Summary
Yescode::Strings::SNAKE_CASE_REGEX
Class Attribute Summary collapse
Instance Attribute Summary collapse
Class Method Summary
collapse
Instance Method Summary
collapse
camel_case, class_name, filename, pascal_case, snake_case
Constructor Details
#initialize(args = {}) ⇒ YesRecord
Returns a new instance of YesRecord.
171
172
173
174
|
# File 'lib/yes_record.rb', line 171
def initialize(args = {})
self.class.connect
load(args)
end
|
Class Attribute Details
.table_name ⇒ Object
14
15
16
|
# File 'lib/yes_record.rb', line 14
def table_name
@table_name || filename
end
|
Instance Attribute Details
#errors ⇒ Object
Returns the value of attribute errors.
169
170
171
|
# File 'lib/yes_record.rb', line 169
def errors
@errors
end
|
Class Method Details
.all(name = :all, *params) ⇒ Object
111
112
113
|
# File 'lib/yes_record.rb', line 111
def all(name = :all, *params)
select(name, *params)
end
|
.clear_request_cache! ⇒ Object
.column_names ⇒ Object
36
37
38
|
# File 'lib/yes_record.rb', line 36
def column_names
@column_names ||= columns.map(&:name)
end
|
.columns ⇒ Object
26
27
28
29
30
31
32
33
34
|
# File 'lib/yes_record.rb', line 26
def columns
@columns ||= schema.map do |r|
Column.new(
r["columnName"],
r["columnType"],
r["pk"] == 1
)
end
end
|
.connect ⇒ Object
50
51
52
53
54
55
56
|
# File 'lib/yes_record.rb', line 50
def connect
column_names.each do |column|
attr_accessor column.to_sym
end
self
end
|
.count(name = :count, *params) ⇒ Object
119
120
121
|
# File 'lib/yes_record.rb', line 119
def count(name = :count, *params)
value(name, *params)
end
|
.delete_all ⇒ Object
161
162
163
164
165
166
|
# File 'lib/yes_record.rb', line 161
def delete_all
result = Yescode::Database.execute "delete from #{table_name}"
clear_request_cache!
result
end
|
.execute_query(name, *params) ⇒ Object
78
79
80
81
82
83
84
85
86
87
88
89
|
# File 'lib/yes_record.rb', line 78
def execute_query(name, *params)
query = @queries[name]
key = params
request_cache[name] ||= { key => nil }
raise QueryNotFound, "Can't find a query in #{@query_filename} with name #{name}" unless query
query.statement ||= Yescode::Database.connection.prepare(query.sql)
Yescode::Database.logger&.debug(cached: !request_cache.dig(name, key).nil?, sql: query.sql, params:)
request_cache[name][key] ||= query.statement.execute(*params).to_a
end
|
.first(name, *params) ⇒ Object
91
92
93
94
95
|
# File 'lib/yes_record.rb', line 91
def first(name, *params)
row = execute_query(name, *params).first
new(row) if row
end
|
.first!(name, *params) ⇒ Object
97
98
99
100
101
102
103
|
# File 'lib/yes_record.rb', line 97
def first!(name, *params)
row = execute_query(name, *params).first
raise RecordNotFound unless row
new(row) if row
end
|
.insert(params) ⇒ Object
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
|
# File 'lib/yes_record.rb', line 135
def insert(params)
params.transform_keys!(&:to_sym)
params[:created_at] ||= Time.now.to_i if column_names.include?("created_at")
sql = insert_sql(params.keys)
inserted = Yescode::Database.get_first_row(sql, params)
clear_request_cache!
new(inserted)
rescue SQLite3::ConstraintException => e
Yescode::Database.logger.error(msg: e.message)
record = new(params)
record.rescue_constraint_error(e)
record
end
|
.insert_all ⇒ Object
153
154
155
|
# File 'lib/yes_record.rb', line 153
def insert_all
end
|
.insert_sql(keys) ⇒ Object
131
132
133
|
# File 'lib/yes_record.rb', line 131
def insert_sql(keys)
"insert into #{table_name} (#{keys.join(', ')}) #{values(keys)} returning *"
end
|
.inspect ⇒ Object
44
45
46
47
48
|
# File 'lib/yes_record.rb', line 44
def inspect
attr_str = columns.map { |c| " #{c.name} => #{c.type}" }.join("\n")
"#{self} {\n#{attr_str}\n}"
end
|
.primary_key_column ⇒ Object
40
41
42
|
# File 'lib/yes_record.rb', line 40
def primary_key_column
@primary_key_column ||= columns.find(&:primary_key).first
end
|
.queries(filename) ⇒ Object
58
59
60
61
62
63
64
65
66
67
68
|
# File 'lib/yes_record.rb', line 58
def queries(filename)
@query_filename = filename
filepath = File.join(".", "app", "models", filename)
queries = Yescode::Queries.queries(filepath)
@queries = {}
queries.each do |name, sql|
@queries[name] = Query.new(name, sql)
end
@queries
end
|
.schema ⇒ Object
22
23
24
|
# File 'lib/yes_record.rb', line 22
def schema
@schema ||= Yescode::Database.schema[table_name]
end
|
.select(name, *params) ⇒ Object
105
106
107
108
109
|
# File 'lib/yes_record.rb', line 105
def select(name, *params)
rows = execute_query(name, *params)
rows.map { |r| new(r) }
end
|
.table(name) ⇒ Object
18
19
20
|
# File 'lib/yes_record.rb', line 18
def table(name)
@table_name = name
end
|
.update_all ⇒ Object
157
158
159
|
# File 'lib/yes_record.rb', line 157
def update_all
end
|
.value(name, *params) ⇒ Object
115
116
117
|
# File 'lib/yes_record.rb', line 115
def value(name, *params)
execute_query(name, *params).first&.values&.first
end
|
.values(keys) ⇒ Object
123
124
125
126
127
128
129
|
# File 'lib/yes_record.rb', line 123
def values(keys)
if keys.empty?
"default values"
else
"values (#{keys.map(&:inspect).join(', ')})"
end
end
|
Instance Method Details
#check?(constraint_name) ⇒ Boolean
232
233
234
235
236
|
# File 'lib/yes_record.rb', line 232
def check?(constraint_name)
return false unless @errors
@errors[:check]&.include?(constraint_name.to_s)
end
|
#delete ⇒ Object
224
225
226
227
228
229
230
|
# File 'lib/yes_record.rb', line 224
def delete
sql = "delete from #{self.class.table_name} where #{pk_column} = ?"
Yescode::Database.execute(sql, pk)
self.class.clear_request_cache!
true
end
|
#duplicate?(column_name) ⇒ Boolean
244
245
246
247
248
|
# File 'lib/yes_record.rb', line 244
def duplicate?(column_name)
return false unless @errors
@errors[:unique]&.include?(column_name.to_s)
end
|
#error?(name) ⇒ Boolean
250
251
252
|
# File 'lib/yes_record.rb', line 250
def error?(name)
check?(name) || null?(name) || duplicate?(name)
end
|
#errors? ⇒ Boolean
254
255
256
|
# File 'lib/yes_record.rb', line 254
def errors?
@errors.any?
end
|
#load(args = {}) ⇒ Object
176
177
178
179
180
181
|
# File 'lib/yes_record.rb', line 176
def load(args = {})
args.each do |k, v|
self.class.attr_accessor(k.to_sym) unless respond_to?(k.to_sym)
public_send("#{k}=", v)
end
end
|
#null?(column_name) ⇒ Boolean
238
239
240
241
242
|
# File 'lib/yes_record.rb', line 238
def null?(column_name)
return false unless @errors
@errors[:null]&.include?(column_name.to_s)
end
|
#pk ⇒ Object
187
188
189
|
# File 'lib/yes_record.rb', line 187
def pk
to_h[pk_column]
end
|
#pk_column ⇒ Object
183
184
185
|
# File 'lib/yes_record.rb', line 183
def pk_column
self.class.primary_key_column.to_sym
end
|
#pk_param ⇒ Object
191
192
193
|
# File 'lib/yes_record.rb', line 191
def pk_param
{ pk_column => pk }
end
|
#rescue_constraint_error(error) ⇒ Object
258
259
260
261
262
263
264
265
266
267
268
269
270
|
# File 'lib/yes_record.rb', line 258
def rescue_constraint_error(error)
message = error.message
name = message.gsub(/(CHECK|NOT NULL|UNIQUE) constraint failed: (\w+\.)?/, '')
@errors ||= { check: [], null: [], unique: [] }
if message.start_with?("CHECK")
@errors[:check] << name
elsif message.start_with?("NOT NULL")
@errors[:null] << name
elsif message.start_with?("UNIQUE")
@errors[:unique] << name
end
end
|
#saved? ⇒ Boolean
276
277
278
|
# File 'lib/yes_record.rb', line 276
def saved?
!pk.nil?
end
|
#to_h ⇒ Object
272
273
274
|
# File 'lib/yes_record.rb', line 272
def to_h
@to_h ||= self.class.column_names.map { |c| [c.to_sym, public_send(c)] }.to_h
end
|
#to_param ⇒ Object
280
281
282
|
# File 'lib/yes_record.rb', line 280
def to_param
to_h.slice(self.class.primary_key_column.to_sym)
end
|
#update(params) ⇒ Object
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
|
# File 'lib/yes_record.rb', line 208
def update(params)
update_params = update_params(params)
sql = update_sql(update_params.keys)
update_params.merge!(pk_param)
updated = Yescode::Database.get_first_row(sql, update_params)
self.class.clear_request_cache!
load(updated)
true
rescue SQLite3::ConstraintException => e
Yescode::Database.logger.error(msg: e.message)
rescue_constraint_error(e)
false
end
|
#update_params(params) ⇒ Object
195
196
197
198
199
200
|
# File 'lib/yes_record.rb', line 195
def update_params(params)
params.transform_keys!(&:to_sym)
params[:updated_at] ||= Time.now.to_i if self.class.column_names.include?("updated_at")
params
end
|
#update_sql(keys) ⇒ Object
202
203
204
205
206
|
# File 'lib/yes_record.rb', line 202
def update_sql(keys)
set_clause = keys.map { |k| "#{k} = :#{k}" }.join(", ")
"update #{self.class.table_name} set #{set_clause} where #{pk_column} = :#{pk_column} returning *"
end
|