tina4ruby 0.5.2 → 3.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/CHANGELOG.md +1 -1
- data/README.md +360 -559
- data/exe/{tina4 → tina4ruby} +1 -0
- data/lib/tina4/ai.rb +312 -0
- data/lib/tina4/auth.rb +44 -3
- data/lib/tina4/auto_crud.rb +163 -0
- data/lib/tina4/cli.rb +242 -77
- data/lib/tina4/constants.rb +46 -0
- data/lib/tina4/cors.rb +74 -0
- data/lib/tina4/database/sqlite3_adapter.rb +139 -0
- data/lib/tina4/database.rb +43 -7
- data/lib/tina4/debug.rb +4 -79
- data/lib/tina4/dev_admin.rb +1162 -0
- data/lib/tina4/dev_mailbox.rb +191 -0
- data/lib/tina4/dev_reload.rb +9 -9
- data/lib/tina4/drivers/firebird_driver.rb +19 -3
- data/lib/tina4/drivers/mssql_driver.rb +3 -3
- data/lib/tina4/drivers/mysql_driver.rb +4 -4
- data/lib/tina4/drivers/postgres_driver.rb +9 -2
- data/lib/tina4/drivers/sqlite_driver.rb +1 -1
- data/lib/tina4/env.rb +42 -2
- data/lib/tina4/error_overlay.rb +252 -0
- data/lib/tina4/events.rb +90 -0
- data/lib/tina4/field_types.rb +4 -0
- data/lib/tina4/frond.rb +1336 -0
- data/lib/tina4/gallery/auth/meta.json +1 -0
- data/lib/tina4/gallery/auth/src/routes/api/gallery_auth.rb +114 -0
- data/lib/tina4/gallery/database/meta.json +1 -0
- data/lib/tina4/gallery/database/src/routes/api/gallery_db.rb +43 -0
- data/lib/tina4/gallery/error-overlay/meta.json +1 -0
- data/lib/tina4/gallery/error-overlay/src/routes/api/gallery_crash.rb +17 -0
- data/lib/tina4/gallery/orm/meta.json +1 -0
- data/lib/tina4/gallery/orm/src/routes/api/gallery_products.rb +16 -0
- data/lib/tina4/gallery/queue/meta.json +1 -0
- data/lib/tina4/gallery/queue/src/routes/api/gallery_queue.rb +27 -0
- data/lib/tina4/gallery/rest-api/meta.json +1 -0
- data/lib/tina4/gallery/rest-api/src/routes/api/gallery_hello.rb +14 -0
- data/lib/tina4/gallery/templates/meta.json +1 -0
- data/lib/tina4/gallery/templates/src/routes/gallery_page.rb +12 -0
- data/lib/tina4/gallery/templates/src/templates/gallery_page.twig +257 -0
- data/lib/tina4/health.rb +39 -0
- data/lib/tina4/html_element.rb +148 -0
- data/lib/tina4/localization.rb +2 -2
- data/lib/tina4/log.rb +203 -0
- data/lib/tina4/messenger.rb +484 -0
- data/lib/tina4/migration.rb +132 -29
- data/lib/tina4/orm.rb +337 -31
- data/lib/tina4/public/css/tina4.css +178 -1
- data/lib/tina4/public/css/tina4.min.css +1 -2
- data/lib/tina4/public/favicon.ico +0 -0
- data/lib/tina4/public/images/logo.svg +5 -0
- data/lib/tina4/public/images/tina4-logo-icon.webp +0 -0
- data/lib/tina4/public/js/frond.min.js +420 -0
- data/lib/tina4/public/js/tina4-dev-admin.min.js +367 -0
- data/lib/tina4/public/js/tina4.min.js +93 -0
- data/lib/tina4/public/swagger/index.html +90 -0
- data/lib/tina4/public/swagger/oauth2-redirect.html +63 -0
- data/lib/tina4/queue.rb +40 -4
- data/lib/tina4/queue_backends/lite_backend.rb +88 -0
- data/lib/tina4/rack_app.rb +314 -23
- data/lib/tina4/rate_limiter.rb +123 -0
- data/lib/tina4/request.rb +61 -15
- data/lib/tina4/response.rb +54 -24
- data/lib/tina4/response_cache.rb +134 -0
- data/lib/tina4/router.rb +90 -15
- data/lib/tina4/scss_compiler.rb +2 -2
- data/lib/tina4/seeder.rb +56 -61
- data/lib/tina4/service_runner.rb +303 -0
- data/lib/tina4/session.rb +85 -0
- data/lib/tina4/session_handlers/mongo_handler.rb +1 -1
- data/lib/tina4/session_handlers/valkey_handler.rb +43 -0
- data/lib/tina4/shutdown.rb +84 -0
- data/lib/tina4/sql_translation.rb +295 -0
- data/lib/tina4/template.rb +36 -6
- data/lib/tina4/templates/base.twig +2 -2
- data/lib/tina4/templates/errors/302.twig +14 -0
- data/lib/tina4/templates/errors/401.twig +9 -0
- data/lib/tina4/templates/errors/403.twig +22 -15
- data/lib/tina4/templates/errors/404.twig +22 -15
- data/lib/tina4/templates/errors/500.twig +31 -15
- data/lib/tina4/templates/errors/502.twig +9 -0
- data/lib/tina4/templates/errors/503.twig +12 -0
- data/lib/tina4/templates/errors/base.twig +37 -0
- data/lib/tina4/version.rb +1 -1
- data/lib/tina4/webserver.rb +28 -18
- data/lib/tina4.rb +57 -21
- metadata +51 -19
- data/lib/tina4/public/js/tina4.js +0 -134
- data/lib/tina4/public/js/tina4helper.js +0 -387
data/lib/tina4/router.rb
CHANGED
|
@@ -2,14 +2,17 @@
|
|
|
2
2
|
|
|
3
3
|
module Tina4
|
|
4
4
|
class Route
|
|
5
|
-
attr_reader :method, :path, :handler, :auth_handler, :swagger_meta,
|
|
5
|
+
attr_reader :method, :path, :handler, :auth_handler, :swagger_meta,
|
|
6
|
+
:path_regex, :param_names, :middleware, :template
|
|
6
7
|
|
|
7
|
-
def initialize(method, path, handler, auth_handler: nil, swagger_meta: {})
|
|
8
|
+
def initialize(method, path, handler, auth_handler: nil, swagger_meta: {}, middleware: [], template: nil)
|
|
8
9
|
@method = method.to_s.upcase.freeze
|
|
9
10
|
@path = normalize_path(path).freeze
|
|
10
11
|
@handler = handler
|
|
11
12
|
@auth_handler = auth_handler
|
|
12
13
|
@swagger_meta = swagger_meta
|
|
14
|
+
@middleware = middleware.freeze
|
|
15
|
+
@template = template&.freeze
|
|
13
16
|
@param_names = []
|
|
14
17
|
@path_regex = compile_pattern(@path)
|
|
15
18
|
@param_names.freeze
|
|
@@ -17,7 +20,7 @@ module Tina4
|
|
|
17
20
|
|
|
18
21
|
# Returns params hash if matched, false otherwise
|
|
19
22
|
def match?(request_path, request_method = nil)
|
|
20
|
-
return false if request_method && @method != request_method.to_s.upcase
|
|
23
|
+
return false if request_method && @method != "ANY" && @method != request_method.to_s.upcase
|
|
21
24
|
match_path(request_path)
|
|
22
25
|
end
|
|
23
26
|
|
|
@@ -27,7 +30,6 @@ module Tina4
|
|
|
27
30
|
return false unless match
|
|
28
31
|
|
|
29
32
|
if @param_names.empty?
|
|
30
|
-
# Static route — no params to extract
|
|
31
33
|
{}
|
|
32
34
|
else
|
|
33
35
|
params = {}
|
|
@@ -39,6 +41,15 @@ module Tina4
|
|
|
39
41
|
end
|
|
40
42
|
end
|
|
41
43
|
|
|
44
|
+
# Run per-route middleware chain; returns true if all pass
|
|
45
|
+
def run_middleware(request, response)
|
|
46
|
+
@middleware.each do |mw|
|
|
47
|
+
result = mw.call(request, response)
|
|
48
|
+
return false if result == false
|
|
49
|
+
end
|
|
50
|
+
true
|
|
51
|
+
end
|
|
52
|
+
|
|
42
53
|
private
|
|
43
54
|
|
|
44
55
|
def normalize_path(path)
|
|
@@ -53,7 +64,15 @@ module Tina4
|
|
|
53
64
|
|
|
54
65
|
parts = path.split("/").reject(&:empty?)
|
|
55
66
|
regex_parts = parts.map do |part|
|
|
56
|
-
if part =~ /\A
|
|
67
|
+
if part =~ /\A\*(\w+)\z/
|
|
68
|
+
# Catch-all splat parameter: *path captures everything after
|
|
69
|
+
name = Regexp.last_match(1)
|
|
70
|
+
@param_names << { name: name.to_sym, type: "path" }
|
|
71
|
+
'(.+)'
|
|
72
|
+
elsif part =~ /\A\{(\w+)(?::(\w+))?\}\z/
|
|
73
|
+
# Tina4/Python-style brace params: {id} or {id:int}
|
|
74
|
+
# This is the ONLY supported param syntax, matching Python exactly.
|
|
75
|
+
# Do NOT add :id (colon) style params.
|
|
57
76
|
name = Regexp.last_match(1)
|
|
58
77
|
type = Regexp.last_match(2) || "string"
|
|
59
78
|
@param_names << { name: name.to_sym, type: type }
|
|
@@ -97,14 +116,43 @@ module Tina4
|
|
|
97
116
|
@method_index ||= Hash.new { |h, k| h[k] = [] }
|
|
98
117
|
end
|
|
99
118
|
|
|
100
|
-
def add_route(method, path, handler, auth_handler: nil, swagger_meta: {})
|
|
101
|
-
route = Route.new(method, path, handler,
|
|
119
|
+
def add_route(method, path, handler, auth_handler: nil, swagger_meta: {}, middleware: [], template: nil)
|
|
120
|
+
route = Route.new(method, path, handler,
|
|
121
|
+
auth_handler: auth_handler,
|
|
122
|
+
swagger_meta: swagger_meta,
|
|
123
|
+
middleware: middleware,
|
|
124
|
+
template: template)
|
|
102
125
|
routes << route
|
|
103
126
|
method_index[route.method] << route
|
|
104
|
-
Tina4::
|
|
127
|
+
Tina4::Log.debug("Route registered: #{method.upcase} #{path}")
|
|
105
128
|
route
|
|
106
129
|
end
|
|
107
130
|
|
|
131
|
+
# Convenience registration methods matching tina4-python pattern
|
|
132
|
+
def get(path, middleware: [], swagger_meta: {}, template: nil, &block)
|
|
133
|
+
add_route("GET", path, block, middleware: middleware, swagger_meta: swagger_meta, template: template)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def post(path, middleware: [], swagger_meta: {}, template: nil, &block)
|
|
137
|
+
add_route("POST", path, block, middleware: middleware, swagger_meta: swagger_meta, template: template)
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
def put(path, middleware: [], swagger_meta: {}, template: nil, &block)
|
|
141
|
+
add_route("PUT", path, block, middleware: middleware, swagger_meta: swagger_meta, template: template)
|
|
142
|
+
end
|
|
143
|
+
|
|
144
|
+
def patch(path, middleware: [], swagger_meta: {}, template: nil, &block)
|
|
145
|
+
add_route("PATCH", path, block, middleware: middleware, swagger_meta: swagger_meta, template: template)
|
|
146
|
+
end
|
|
147
|
+
|
|
148
|
+
def delete(path, middleware: [], swagger_meta: {}, template: nil, &block)
|
|
149
|
+
add_route("DELETE", path, block, middleware: middleware, swagger_meta: swagger_meta, template: template)
|
|
150
|
+
end
|
|
151
|
+
|
|
152
|
+
def any(path, middleware: [], swagger_meta: {}, template: nil, &block)
|
|
153
|
+
add_route("ANY", path, block, middleware: middleware, swagger_meta: swagger_meta, template: template)
|
|
154
|
+
end
|
|
155
|
+
|
|
108
156
|
def find_route(path, method)
|
|
109
157
|
normalized_method = method.upcase
|
|
110
158
|
# Normalize path once (not per-route)
|
|
@@ -112,8 +160,8 @@ module Tina4
|
|
|
112
160
|
normalized_path = "/#{normalized_path}" unless normalized_path.start_with?("/")
|
|
113
161
|
normalized_path = normalized_path.chomp("/") unless normalized_path == "/"
|
|
114
162
|
|
|
115
|
-
#
|
|
116
|
-
candidates = method_index[normalized_method]
|
|
163
|
+
# Check ANY routes first, then method-specific routes
|
|
164
|
+
candidates = (method_index["ANY"] || []) + (method_index[normalized_method] || [])
|
|
117
165
|
candidates.each do |route|
|
|
118
166
|
params = route.match_path(normalized_path)
|
|
119
167
|
return [route, params] if params
|
|
@@ -126,23 +174,50 @@ module Tina4
|
|
|
126
174
|
@method_index = Hash.new { |h, k| h[k] = [] }
|
|
127
175
|
end
|
|
128
176
|
|
|
129
|
-
def group(prefix, auth_handler: nil, &block)
|
|
130
|
-
GroupContext.new(prefix, auth_handler).instance_eval(&block)
|
|
177
|
+
def group(prefix, auth_handler: nil, middleware: [], &block)
|
|
178
|
+
GroupContext.new(prefix, auth_handler, middleware).instance_eval(&block)
|
|
179
|
+
end
|
|
180
|
+
|
|
181
|
+
# Load route files from a directory (file-based route discovery)
|
|
182
|
+
def load_routes(directory)
|
|
183
|
+
return unless Dir.exist?(directory)
|
|
184
|
+
Dir.glob(File.join(directory, "**/*.rb")).sort.each do |file|
|
|
185
|
+
begin
|
|
186
|
+
load file
|
|
187
|
+
Tina4::Log.debug("Route loaded: #{file}")
|
|
188
|
+
rescue => e
|
|
189
|
+
Tina4::Log.error("Failed to load route #{file}: #{e.message}")
|
|
190
|
+
end
|
|
191
|
+
end
|
|
131
192
|
end
|
|
132
193
|
end
|
|
133
194
|
|
|
134
195
|
class GroupContext
|
|
135
|
-
def initialize(prefix, auth_handler = nil)
|
|
196
|
+
def initialize(prefix, auth_handler = nil, middleware = [])
|
|
136
197
|
@prefix = prefix.chomp("/")
|
|
137
198
|
@auth_handler = auth_handler
|
|
199
|
+
@middleware = middleware
|
|
138
200
|
end
|
|
139
201
|
|
|
140
202
|
%w[get post put patch delete any].each do |m|
|
|
141
|
-
define_method(m) do |path, swagger_meta: {}, &handler|
|
|
203
|
+
define_method(m) do |path, middleware: [], swagger_meta: {}, template: nil, &handler|
|
|
142
204
|
full_path = "#{@prefix}#{path}"
|
|
143
|
-
|
|
205
|
+
combined_middleware = @middleware + middleware
|
|
206
|
+
Tina4::Router.add_route(m, full_path, handler,
|
|
207
|
+
auth_handler: @auth_handler,
|
|
208
|
+
swagger_meta: swagger_meta,
|
|
209
|
+
middleware: combined_middleware,
|
|
210
|
+
template: template)
|
|
144
211
|
end
|
|
145
212
|
end
|
|
213
|
+
|
|
214
|
+
# Nested groups
|
|
215
|
+
def group(prefix, auth_handler: nil, middleware: [], &block)
|
|
216
|
+
full_prefix = "#{@prefix}#{prefix}"
|
|
217
|
+
combined_middleware = @middleware + middleware
|
|
218
|
+
nested_auth = auth_handler || @auth_handler
|
|
219
|
+
GroupContext.new(full_prefix, nested_auth, combined_middleware).instance_eval(&block)
|
|
220
|
+
end
|
|
146
221
|
end
|
|
147
222
|
end
|
|
148
223
|
end
|
data/lib/tina4/scss_compiler.rb
CHANGED
|
@@ -31,9 +31,9 @@ module Tina4
|
|
|
31
31
|
css_content = compile_scss(scss_content, File.dirname(scss_file))
|
|
32
32
|
File.write(css_file, css_content)
|
|
33
33
|
|
|
34
|
-
Tina4::
|
|
34
|
+
Tina4::Log.debug("Compiled SCSS: #{scss_file} -> #{css_file}")
|
|
35
35
|
rescue => e
|
|
36
|
-
Tina4::
|
|
36
|
+
Tina4::Log.error("SCSS compilation failed: #{scss_file} - #{e.message}")
|
|
37
37
|
end
|
|
38
38
|
|
|
39
39
|
def compile_scss(content, base_dir)
|
data/lib/tina4/seeder.rb
CHANGED
|
@@ -90,6 +90,13 @@ module Tina4
|
|
|
90
90
|
@rng = seed ? Random.new(seed) : Random.new
|
|
91
91
|
end
|
|
92
92
|
|
|
93
|
+
# Static factory — create a seeded FakeData instance.
|
|
94
|
+
# fake = FakeData.seed(42)
|
|
95
|
+
# fake.name # deterministic
|
|
96
|
+
def self.seed(seed)
|
|
97
|
+
new(seed: seed)
|
|
98
|
+
end
|
|
99
|
+
|
|
93
100
|
def first_name
|
|
94
101
|
FIRST_NAMES[@rng.rand(FIRST_NAMES.length)]
|
|
95
102
|
end
|
|
@@ -328,13 +335,13 @@ module Tina4
|
|
|
328
335
|
table = orm_class.table_name
|
|
329
336
|
|
|
330
337
|
if fields.empty?
|
|
331
|
-
Tina4::
|
|
338
|
+
Tina4::Log.error("Seeder: No fields found on #{orm_class.name}")
|
|
332
339
|
return 0
|
|
333
340
|
end
|
|
334
341
|
|
|
335
342
|
db = Tina4.database
|
|
336
343
|
unless db
|
|
337
|
-
Tina4::
|
|
344
|
+
Tina4::Log.error("Seeder: No database connection. Set Tina4.database first.")
|
|
338
345
|
return 0
|
|
339
346
|
end
|
|
340
347
|
|
|
@@ -343,7 +350,7 @@ module Tina4
|
|
|
343
350
|
begin
|
|
344
351
|
result = db.fetch_one("SELECT count(*) as cnt FROM #{table}")
|
|
345
352
|
if result && result[:cnt].to_i >= count
|
|
346
|
-
Tina4::
|
|
353
|
+
Tina4::Log.info("Seeder: #{table} already has #{result[:cnt]} records, skipping")
|
|
347
354
|
return 0
|
|
348
355
|
end
|
|
349
356
|
rescue => e
|
|
@@ -355,9 +362,9 @@ module Tina4
|
|
|
355
362
|
if clear
|
|
356
363
|
begin
|
|
357
364
|
db.execute("DELETE FROM #{table}")
|
|
358
|
-
Tina4::
|
|
365
|
+
Tina4::Log.info("Seeder: Cleared #{table}")
|
|
359
366
|
rescue => e
|
|
360
|
-
Tina4::
|
|
367
|
+
Tina4::Log.warn("Seeder: Could not clear #{table}: #{e.message}")
|
|
361
368
|
end
|
|
362
369
|
end
|
|
363
370
|
|
|
@@ -384,14 +391,14 @@ module Tina4
|
|
|
384
391
|
if obj.save
|
|
385
392
|
inserted += 1
|
|
386
393
|
else
|
|
387
|
-
Tina4::
|
|
394
|
+
Tina4::Log.warn("Seeder: Insert failed for #{table} row #{i + 1}: #{obj.errors.join(', ')}")
|
|
388
395
|
end
|
|
389
396
|
rescue => e
|
|
390
|
-
Tina4::
|
|
397
|
+
Tina4::Log.warn("Seeder: Insert failed for #{table} row #{i + 1}: #{e.message}")
|
|
391
398
|
end
|
|
392
399
|
end
|
|
393
400
|
|
|
394
|
-
Tina4::
|
|
401
|
+
Tina4::Log.info("Seeder: Inserted #{inserted}/#{count} records into #{table}")
|
|
395
402
|
inserted
|
|
396
403
|
end
|
|
397
404
|
|
|
@@ -409,7 +416,7 @@ module Tina4
|
|
|
409
416
|
db = Tina4.database
|
|
410
417
|
|
|
411
418
|
unless db
|
|
412
|
-
Tina4::
|
|
419
|
+
Tina4::Log.error("Seeder: No database connection.")
|
|
413
420
|
return 0
|
|
414
421
|
end
|
|
415
422
|
|
|
@@ -417,7 +424,7 @@ module Tina4
|
|
|
417
424
|
begin
|
|
418
425
|
db.execute("DELETE FROM #{table_name}")
|
|
419
426
|
rescue => e
|
|
420
|
-
Tina4::
|
|
427
|
+
Tina4::Log.warn("Seeder: Could not clear #{table_name}: #{e.message}")
|
|
421
428
|
end
|
|
422
429
|
end
|
|
423
430
|
|
|
@@ -438,63 +445,51 @@ module Tina4
|
|
|
438
445
|
db.insert(table_name, row)
|
|
439
446
|
inserted += 1
|
|
440
447
|
rescue => e
|
|
441
|
-
Tina4::
|
|
448
|
+
Tina4::Log.warn("Seeder: Insert failed for #{table_name} row #{i + 1}: #{e.message}")
|
|
442
449
|
end
|
|
443
450
|
end
|
|
444
451
|
|
|
445
|
-
Tina4::
|
|
452
|
+
Tina4::Log.info("Seeder: Inserted #{inserted}/#{count} records into #{table_name}")
|
|
446
453
|
inserted
|
|
447
454
|
end
|
|
448
455
|
|
|
449
|
-
#
|
|
456
|
+
# Seed multiple ORM classes in batch with optional dependency-aware clearing.
|
|
457
|
+
#
|
|
458
|
+
# @param tasks [Array<Hash>] each hash has :orm_class, :count, :overrides, :seed
|
|
459
|
+
# @param clear [Boolean] delete existing records (in reverse order) before seeding
|
|
460
|
+
# @return [Hash] { "ClassName" => inserted_count, ... }
|
|
450
461
|
#
|
|
451
462
|
# @example
|
|
452
|
-
#
|
|
453
|
-
#
|
|
454
|
-
#
|
|
455
|
-
#
|
|
456
|
-
|
|
457
|
-
|
|
458
|
-
@tasks = []
|
|
459
|
-
end
|
|
460
|
-
|
|
461
|
-
def add(orm_class, count: 10, overrides: {}, seed: nil)
|
|
462
|
-
@tasks << {
|
|
463
|
-
orm_class: orm_class,
|
|
464
|
-
count: count,
|
|
465
|
-
overrides: overrides,
|
|
466
|
-
seed: seed
|
|
467
|
-
}
|
|
468
|
-
self
|
|
469
|
-
end
|
|
470
|
-
|
|
471
|
-
def run(clear: false)
|
|
472
|
-
results = {}
|
|
473
|
-
|
|
474
|
-
if clear
|
|
475
|
-
@tasks.reverse_each do |task|
|
|
476
|
-
begin
|
|
477
|
-
Tina4.database&.execute("DELETE FROM #{task[:orm_class].table_name}")
|
|
478
|
-
Tina4::Debug.info("Seeder: Cleared #{task[:orm_class].table_name}")
|
|
479
|
-
rescue => e
|
|
480
|
-
Tina4::Debug.warn("Seeder: Could not clear #{task[:orm_class].table_name}: #{e.message}")
|
|
481
|
-
end
|
|
482
|
-
end
|
|
483
|
-
end
|
|
463
|
+
# Tina4.seed_batch([
|
|
464
|
+
# { orm_class: User, count: 20 },
|
|
465
|
+
# { orm_class: Order, count: 100, overrides: { status: "pending" } }
|
|
466
|
+
# ], clear: true)
|
|
467
|
+
def self.seed_batch(tasks, clear: false)
|
|
468
|
+
results = {}
|
|
484
469
|
|
|
485
|
-
|
|
486
|
-
|
|
487
|
-
|
|
488
|
-
|
|
489
|
-
|
|
490
|
-
|
|
491
|
-
|
|
492
|
-
|
|
493
|
-
results[task[:orm_class].name] = n
|
|
470
|
+
if clear
|
|
471
|
+
tasks.reverse_each do |task|
|
|
472
|
+
begin
|
|
473
|
+
Tina4.database&.execute("DELETE FROM #{task[:orm_class].table_name}")
|
|
474
|
+
Tina4::Log.info("Seeder: Cleared #{task[:orm_class].table_name}")
|
|
475
|
+
rescue => e
|
|
476
|
+
Tina4::Log.warn("Seeder: Could not clear #{task[:orm_class].table_name}: #{e.message}")
|
|
477
|
+
end
|
|
494
478
|
end
|
|
479
|
+
end
|
|
495
480
|
|
|
496
|
-
|
|
481
|
+
tasks.each do |task|
|
|
482
|
+
n = Tina4.seed_orm(
|
|
483
|
+
task[:orm_class],
|
|
484
|
+
count: task[:count] || 10,
|
|
485
|
+
overrides: task[:overrides] || {},
|
|
486
|
+
clear: false,
|
|
487
|
+
seed: task[:seed]
|
|
488
|
+
)
|
|
489
|
+
results[task[:orm_class].name] = n
|
|
497
490
|
end
|
|
491
|
+
|
|
492
|
+
results
|
|
498
493
|
end
|
|
499
494
|
|
|
500
495
|
# Run all seed files in the given folder.
|
|
@@ -502,7 +497,7 @@ module Tina4
|
|
|
502
497
|
# @param seed_folder [String] path to seed files (default: "seeds")
|
|
503
498
|
def self.seed(seed_folder: "seeds", clear: false)
|
|
504
499
|
unless Dir.exist?(seed_folder)
|
|
505
|
-
Tina4::
|
|
500
|
+
Tina4::Log.info("Seeder: No seeds folder found at #{seed_folder}")
|
|
506
501
|
return
|
|
507
502
|
end
|
|
508
503
|
|
|
@@ -510,19 +505,19 @@ module Tina4
|
|
|
510
505
|
files.reject! { |f| File.basename(f).start_with?("_") }
|
|
511
506
|
|
|
512
507
|
if files.empty?
|
|
513
|
-
Tina4::
|
|
508
|
+
Tina4::Log.info("Seeder: No seed files found in #{seed_folder}")
|
|
514
509
|
return
|
|
515
510
|
end
|
|
516
511
|
|
|
517
|
-
Tina4::
|
|
512
|
+
Tina4::Log.info("Seeder: Found #{files.length} seed file(s) in #{seed_folder}")
|
|
518
513
|
|
|
519
514
|
files.each do |filepath|
|
|
520
515
|
begin
|
|
521
|
-
Tina4::
|
|
516
|
+
Tina4::Log.info("Seeder: Running #{File.basename(filepath)}...")
|
|
522
517
|
load filepath
|
|
523
|
-
Tina4::
|
|
518
|
+
Tina4::Log.info("Seeder: Completed #{File.basename(filepath)}")
|
|
524
519
|
rescue => e
|
|
525
|
-
Tina4::
|
|
520
|
+
Tina4::Log.error("Seeder: Failed to run #{File.basename(filepath)}: #{e.message}")
|
|
526
521
|
end
|
|
527
522
|
end
|
|
528
523
|
end
|