tina4ruby 3.13.18 → 3.13.19
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/lib/tina4/orm.rb +34 -8
- data/lib/tina4/response.rb +20 -0
- data/lib/tina4/seeder.rb +1 -1
- data/lib/tina4/version.rb +1 -1
- data/lib/tina4.rb +21 -2
- metadata +1 -1
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 93597b3b5afd4c56593d4c2d107b573790b68fbae4b0dd28f07d4f636a462381
|
|
4
|
+
data.tar.gz: c384790499ba27f16fc95efec1053a34c201d5444f742a9581167f6450418526
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: fd30dce3ddb8de6ec35fa4416f105b52df238951d723df7887ad24787a9e657bd04c90e904427dae4365faf602ef273cfb1716dcd655b15b0ac0caf45ecfa4d0
|
|
7
|
+
data.tar.gz: 1febfd89b40487edc5c51314d6bd5878ecd22244720959e58f54e56d90f2751d0543be833f4f0ddb2da51bcdee5ba8aa5d3c06d6723fe28df644ae4f6f2ef3db
|
data/lib/tina4/orm.rb
CHANGED
|
@@ -41,14 +41,32 @@ module Tina4
|
|
|
41
41
|
|
|
42
42
|
class << self
|
|
43
43
|
def db
|
|
44
|
-
#
|
|
45
|
-
#
|
|
46
|
-
#
|
|
47
|
-
#
|
|
48
|
-
@db
|
|
44
|
+
# Resolution order:
|
|
45
|
+
# 1. @db is a Symbol/String → named connection from Tina4.databases
|
|
46
|
+
# (bound via Tina4.bind_database(db, name:)). Raises a clear
|
|
47
|
+
# error if that named connection was never registered.
|
|
48
|
+
# 2. @db is a Database/driver instance → use it directly.
|
|
49
|
+
# 3. Otherwise → global Tina4.database, else env-derived
|
|
50
|
+
# auto-discovery (TINA4_DATABASE_URL). v3.13.12 wired this
|
|
51
|
+
# fallback; before that auto_discover_db was never called.
|
|
52
|
+
case @db
|
|
53
|
+
when Symbol, String
|
|
54
|
+
name = @db.to_sym
|
|
55
|
+
Tina4.databases[name] || raise(
|
|
56
|
+
"Tina4 named database connection '#{@db}' is not registered for #{name}. " \
|
|
57
|
+
"Call Tina4.bind_database(db, name: #{@db.inspect}) before using this model."
|
|
58
|
+
)
|
|
59
|
+
when nil
|
|
60
|
+
Tina4.database || auto_discover_db
|
|
61
|
+
else
|
|
62
|
+
@db
|
|
63
|
+
end
|
|
49
64
|
end
|
|
50
65
|
|
|
51
|
-
# Per-model database binding
|
|
66
|
+
# Per-model database binding.
|
|
67
|
+
# self.db = some_database_instance → use that connection
|
|
68
|
+
# self.db = :analytics → resolve a named connection
|
|
69
|
+
# from Tina4.databases at access time
|
|
52
70
|
def db=(database)
|
|
53
71
|
@db = database
|
|
54
72
|
end
|
|
@@ -476,8 +494,7 @@ module Tina4
|
|
|
476
494
|
def auto_discover_db
|
|
477
495
|
url = ENV["TINA4_DATABASE_URL"]
|
|
478
496
|
return nil unless url
|
|
479
|
-
Tina4.
|
|
480
|
-
Tina4.database
|
|
497
|
+
Tina4.bind_database(Tina4::Database.new(url, username: ENV.fetch("TINA4_DATABASE_USERNAME", ""), password: ENV.fetch("TINA4_DATABASE_PASSWORD", "")))
|
|
481
498
|
end
|
|
482
499
|
|
|
483
500
|
def find_by_filter(filter)
|
|
@@ -517,6 +534,15 @@ module Tina4
|
|
|
517
534
|
@persisted = false
|
|
518
535
|
@errors = []
|
|
519
536
|
@relationship_cache = {}
|
|
537
|
+
# Accept a JSON object string (parity with Python/PHP/Node):
|
|
538
|
+
# Widget.new('{"id":1,"name":"alpha"}')
|
|
539
|
+
attributes = JSON.parse(attributes) if attributes.is_a?(String)
|
|
540
|
+
# A single model is one record — reject an Array with a clear message.
|
|
541
|
+
if attributes.is_a?(Array)
|
|
542
|
+
raise ArgumentError,
|
|
543
|
+
"#{self.class}.new expects a Hash, keyword args, or a JSON object string " \
|
|
544
|
+
"for one record — got an Array. Map over the list to build many records."
|
|
545
|
+
end
|
|
520
546
|
attributes.each do |key, value|
|
|
521
547
|
setter = "#{key}="
|
|
522
548
|
__send__(setter, value) if respond_to?(setter)
|
data/lib/tina4/response.rb
CHANGED
|
@@ -80,6 +80,7 @@ module Tina4
|
|
|
80
80
|
# Matches Python __call__ / PHP __invoke / Node response() pattern.
|
|
81
81
|
def call(data = nil, status_code = 200, content_type = nil)
|
|
82
82
|
@status_code = status_code
|
|
83
|
+
data = jsonable(data)
|
|
83
84
|
if content_type
|
|
84
85
|
@headers["content-type"] = content_type
|
|
85
86
|
@body = data.to_s
|
|
@@ -96,10 +97,29 @@ module Tina4
|
|
|
96
97
|
def json(data, status_or_opts = nil, status: nil)
|
|
97
98
|
@status_code = status || (status_or_opts.is_a?(Integer) ? status_or_opts : 200)
|
|
98
99
|
@headers["content-type"] = JSON_CONTENT_TYPE
|
|
100
|
+
data = jsonable(data)
|
|
99
101
|
@body = data.is_a?(String) ? data : JSON.generate(data)
|
|
100
102
|
self
|
|
101
103
|
end
|
|
102
104
|
|
|
105
|
+
# Normalise domain objects into JSON-serialisable structures so handlers can
|
|
106
|
+
# `response.(model)` / `response.json(model)` without calling .to_h by hand:
|
|
107
|
+
#
|
|
108
|
+
# response.json(user) # ORM model -> Hash
|
|
109
|
+
# response.json(User.all) # Array<ORM> -> Array<Hash>
|
|
110
|
+
# response.json(db.fetch(sql)) # DatabaseResult -> Array<Hash>
|
|
111
|
+
#
|
|
112
|
+
# Plain Hash / Array / String pass through unchanged (Array members that are
|
|
113
|
+
# models are still converted).
|
|
114
|
+
def jsonable(data)
|
|
115
|
+
return data.to_h if data.is_a?(Tina4::ORM)
|
|
116
|
+
return data.records if data.is_a?(Tina4::DatabaseResult)
|
|
117
|
+
return data.map { |item| item.is_a?(Tina4::ORM) ? item.to_h : item } if data.is_a?(Array)
|
|
118
|
+
|
|
119
|
+
data
|
|
120
|
+
end
|
|
121
|
+
private :jsonable
|
|
122
|
+
|
|
103
123
|
def html(content, status_or_opts = nil, status: nil)
|
|
104
124
|
@status_code = status || (status_or_opts.is_a?(Integer) ? status_or_opts : 200)
|
|
105
125
|
@headers["content-type"] = HTML_CONTENT_TYPE
|
data/lib/tina4/seeder.rb
CHANGED
|
@@ -373,7 +373,7 @@ module Tina4
|
|
|
373
373
|
|
|
374
374
|
db = Tina4.database
|
|
375
375
|
unless db
|
|
376
|
-
Tina4::Log.error("Seeder: No database connection.
|
|
376
|
+
Tina4::Log.error("Seeder: No database connection. Call Tina4.bind_database(db) first.")
|
|
377
377
|
return 0
|
|
378
378
|
end
|
|
379
379
|
|
data/lib/tina4/version.rb
CHANGED
data/lib/tina4.rb
CHANGED
|
@@ -120,7 +120,26 @@ module Tina4
|
|
|
120
120
|
BANNER
|
|
121
121
|
|
|
122
122
|
class << self
|
|
123
|
-
attr_accessor :root_dir
|
|
123
|
+
attr_accessor :root_dir
|
|
124
|
+
attr_reader :database
|
|
125
|
+
|
|
126
|
+
# Bind a database connection.
|
|
127
|
+
# bind_database(db) → sets the global default (Tina4.database)
|
|
128
|
+
# bind_database(db, name: :analytics) → registers a named connection
|
|
129
|
+
# A model with `self.db = :analytics` resolves from this named registry;
|
|
130
|
+
# otherwise models fall back to the global default / TINA4_DATABASE_URL.
|
|
131
|
+
def bind_database(db, name: nil)
|
|
132
|
+
if name.nil?
|
|
133
|
+
@database = db
|
|
134
|
+
else
|
|
135
|
+
(@databases ||= {})[name.to_sym] = db
|
|
136
|
+
end
|
|
137
|
+
db
|
|
138
|
+
end
|
|
139
|
+
|
|
140
|
+
# Named connection registry. bind_database(db, name:) populates it;
|
|
141
|
+
# models with a Symbol/String `self.db` resolve against it.
|
|
142
|
+
def databases = (@databases ||= {})
|
|
124
143
|
|
|
125
144
|
def print_banner(host: "0.0.0.0", port: 7147, server_name: nil)
|
|
126
145
|
# TINA4_SUPPRESS — short-circuit ALL banner output for headless / CI runs.
|
|
@@ -450,7 +469,7 @@ module Tina4
|
|
|
450
469
|
db_url = ENV["TINA4_DATABASE_URL"]
|
|
451
470
|
if db_url && !db_url.empty?
|
|
452
471
|
begin
|
|
453
|
-
|
|
472
|
+
bind_database(Tina4::Database.new(db_url))
|
|
454
473
|
Tina4::Log.info("Database connected: #{db_url.sub(/:[^:@]+@/, ':***@')}")
|
|
455
474
|
rescue => e
|
|
456
475
|
Tina4::Log.error("Database connection failed: #{e.message}")
|