trophonius 2.1.7 → 2.2.1
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/connectors/connection.rb +5 -1
- data/lib/connectors/connection_manager.rb +2 -1
- data/lib/record.rb +140 -109
- data/lib/translator.rb +6 -0
- metadata +3 -3
checksums.yaml
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
---
|
|
2
2
|
SHA256:
|
|
3
|
-
metadata.gz:
|
|
4
|
-
data.tar.gz:
|
|
3
|
+
metadata.gz: 4a84b2bfd47dee89330a357ee38cee77f490e3eba810f9743bac995b61b3601f
|
|
4
|
+
data.tar.gz: 19209c6e6b419c624be3b25e3d6bbda7cf68340e719b7ab5851c6a98f635cafc
|
|
5
5
|
SHA512:
|
|
6
|
-
metadata.gz:
|
|
7
|
-
data.tar.gz:
|
|
6
|
+
metadata.gz: 1d1d01693932f60cce0f79011efecbe5610bf594725850c468ed1ecb4363d8c16c87b97eb556d7499de63e830b41a8247fb6e97644e0a899ab4cc42f52024606
|
|
7
|
+
data.tar.gz: a851707b8c5cd2dd9e6680a66065eebebbcdc3c131280c69d91c7366e863e9e7f4feb84ba72decc23b6f08b45cf2f3aebe7eca2c3979f6c1581998bfa0fd0da2
|
|
@@ -30,6 +30,8 @@ module Trophonius
|
|
|
30
30
|
# Disconnects from the FileMaker server
|
|
31
31
|
#
|
|
32
32
|
def disconnect
|
|
33
|
+
return unless test_connection
|
|
34
|
+
|
|
33
35
|
uri = URI::RFC2396_Parser.new
|
|
34
36
|
url =
|
|
35
37
|
URI(
|
|
@@ -174,8 +176,10 @@ module Trophonius
|
|
|
174
176
|
return !last_connection.nil? && last_connection > Time.now - (15 * 60) if Trophonius.config.layout_name == ''
|
|
175
177
|
|
|
176
178
|
path = "/layouts/#{Trophonius.config.layout_name}/records?_limit=1"
|
|
179
|
+
|
|
180
|
+
token_to_check = Trophonius.config.redis_connection ? Trophonius::RedisManager.get_key(key: 'token') : @token
|
|
177
181
|
response =
|
|
178
|
-
Trophonius::DatabaseRequest.make_request(path, :get, {}, bypass_queue_with: "Bearer #{
|
|
182
|
+
Trophonius::DatabaseRequest.make_request(path, :get, {}, bypass_queue_with: "Bearer #{token_to_check}")
|
|
179
183
|
response['messages'][0]['code'] == '0'
|
|
180
184
|
rescue StandardError => e
|
|
181
185
|
puts e
|
|
@@ -27,7 +27,8 @@ module Trophonius
|
|
|
27
27
|
end
|
|
28
28
|
|
|
29
29
|
def disconnect_all
|
|
30
|
-
@connections.
|
|
30
|
+
@connections.reject { |_connection_id, connection| connection[:token].blank? }
|
|
31
|
+
.each { |_connection_id, connection| connection[:connection].disconnect }
|
|
31
32
|
end
|
|
32
33
|
|
|
33
34
|
private
|
data/lib/record.rb
CHANGED
|
@@ -22,10 +22,11 @@ module Trophonius
|
|
|
22
22
|
@modifiable_fields = {}
|
|
23
23
|
@modified_fields = {}
|
|
24
24
|
@model_name = model
|
|
25
|
-
@model = model_name.instance_of?(String) ?
|
|
25
|
+
@model = model_name.instance_of?(String) ? constantize_model(model_name) : model_name
|
|
26
26
|
@layout_name = @model.layout_name
|
|
27
|
-
|
|
28
|
-
|
|
27
|
+
@portals = []
|
|
28
|
+
define_field_methods(fm_record) if fm_record.present?
|
|
29
|
+
define_portal_methods(fm_record) if fm_record.present?
|
|
29
30
|
super()
|
|
30
31
|
end
|
|
31
32
|
|
|
@@ -41,113 +42,14 @@ module Trophonius
|
|
|
41
42
|
|
|
42
43
|
def method_missing(method, *args, &block)
|
|
43
44
|
if ActiveSupport::Inflector.pluralize(method).to_s == method.to_s
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
layout = model.layout_name
|
|
50
|
-
model.create_translations if model.translations.keys.empty?
|
|
51
|
-
|
|
52
|
-
url = "/layouts/#{layout}/_find"
|
|
53
|
-
foreign_key_field = if model.translations.key?(relation[:foreign_key])
|
|
54
|
-
model.translations[relation[:foreign_key]].to_s
|
|
55
|
-
else
|
|
56
|
-
relation[:foreign_key].to_s
|
|
57
|
-
end
|
|
58
|
-
|
|
59
|
-
primary_key_field = if pk_model.translations.key?(relation[:primary_key])
|
|
60
|
-
pk_model.translations[relation[:primary_key]].to_s
|
|
61
|
-
else
|
|
62
|
-
relation[:primary_key].to_s
|
|
63
|
-
end
|
|
64
|
-
|
|
65
|
-
body = { query: [{ foreign_key_field => self[primary_key_field].to_s }], limit: 100_000 }.to_json
|
|
66
|
-
response = DatabaseRequest.make_request(url, 'post', body)
|
|
67
|
-
|
|
68
|
-
if response['messages'][0]['code'] == '0'
|
|
69
|
-
r_results = response['response']['data']
|
|
70
|
-
ret_val = RecordSet.new(layout, model.non_modifiable_fields)
|
|
71
|
-
r_results.each do |r|
|
|
72
|
-
hash = model.build_result(r)
|
|
73
|
-
ret_val << hash
|
|
74
|
-
end
|
|
75
|
-
@response = ret_val
|
|
76
|
-
@response
|
|
77
|
-
elsif response['messages'][0]['code'] == '101' || response['messages'][0]['code'] == '401'
|
|
78
|
-
RecordSet.new(layout, model.non_modifiable_fields)
|
|
79
|
-
|
|
80
|
-
else
|
|
81
|
-
if response['messages'][0]['code'] == '102'
|
|
82
|
-
results = DatabaseRequest.retrieve_first(layout)
|
|
83
|
-
if results['messages'][0]['code'] == '0'
|
|
84
|
-
r_results = results['response']['data']
|
|
85
|
-
ret_val = r_results.empty? ? Error.throw_error('102') : r_results[0]['fieldData']
|
|
86
|
-
query_keys = [foreign_key_field]
|
|
87
|
-
Error.throw_error('102', (query_keys - ret_val.keys.map(&:downcase)).flatten.join(', '), layout)
|
|
88
|
-
else
|
|
89
|
-
Error.throw_error('102')
|
|
90
|
-
end
|
|
91
|
-
end
|
|
92
|
-
Error.throw_error(response['messages'][0]['code'])
|
|
93
|
-
end
|
|
94
|
-
end
|
|
95
|
-
elsif ActiveSupport::Inflector.constantize(ActiveSupport::Inflector.classify(ActiveSupport::Inflector.singularize(method))).respond_to?('first')
|
|
96
|
-
fk_model = ActiveSupport::Inflector.constantize(ActiveSupport::Inflector.classify(ActiveSupport::Inflector.singularize(model_name)))
|
|
97
|
-
pk_model = ActiveSupport::Inflector.constantize(ActiveSupport::Inflector.classify(ActiveSupport::Inflector.singularize(method)))
|
|
98
|
-
|
|
99
|
-
if pk_model.has_many_relations[ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.pluralize(model_name)).to_sym]
|
|
100
|
-
relation = pk_model.has_many_relations[ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.pluralize(model_name)).to_sym]
|
|
101
|
-
layout = pk_model.layout_name
|
|
102
|
-
pk_model.create_translations if pk_model.translations.keys.empty?
|
|
103
|
-
|
|
104
|
-
url = "/layouts/#{layout}/_find"
|
|
105
|
-
|
|
106
|
-
foreign_key_field = if fk_model.translations.key?(relation[:foreign_key])
|
|
107
|
-
fk_model.translations[relation[:foreign_key]].to_s
|
|
108
|
-
else
|
|
109
|
-
relation[:foreign_key].to_s
|
|
110
|
-
end
|
|
111
|
-
|
|
112
|
-
primary_key_field = if pk_model.translations.key?(relation[:primary_key])
|
|
113
|
-
pk_model.translations[relation[:primary_key]].to_s
|
|
114
|
-
else
|
|
115
|
-
relation[:primary_key].to_s
|
|
116
|
-
end
|
|
117
|
-
|
|
118
|
-
body = { query: [{ primary_key_field => self[foreign_key_field].to_s }], limit: 1 }.to_json
|
|
119
|
-
|
|
120
|
-
response = DatabaseRequest.make_request(url, 'post', body)
|
|
121
|
-
if response['messages'][0]['code'] == '0'
|
|
122
|
-
r_results = response['response']['data']
|
|
123
|
-
ret_val = RecordSet.new(layout, pk_model.non_modifiable_fields)
|
|
124
|
-
r_results.each do |r|
|
|
125
|
-
hash = pk_model.build_result(r)
|
|
126
|
-
ret_val << hash
|
|
127
|
-
end
|
|
128
|
-
@response = ret_val
|
|
129
|
-
@response.first
|
|
130
|
-
elsif response['messages'][0]['code'] == '101' || response['messages'][0]['code'] == '401'
|
|
131
|
-
RecordSet.new(layout, pk_model.non_modifiable_fields)
|
|
132
|
-
|
|
133
|
-
else
|
|
134
|
-
if response['messages'][0]['code'] == '102'
|
|
135
|
-
results = DatabaseRequest.retrieve_first(layout)
|
|
136
|
-
if results['messages'][0]['code'] == '0'
|
|
137
|
-
r_results = results['response']['data']
|
|
138
|
-
ret_val = r_results.empty? ? Error.throw_error('102') : r_results[0]['fieldData']
|
|
139
|
-
query_keys = [primary_key_field]
|
|
140
|
-
Error.throw_error('102', (query_keys - ret_val.keys.map(&:downcase)).flatten.join(', '), layout)
|
|
141
|
-
else
|
|
142
|
-
Error.throw_error('102')
|
|
143
|
-
end
|
|
144
|
-
end
|
|
145
|
-
Error.throw_error(response['messages'][0]['code'])
|
|
146
|
-
end
|
|
147
|
-
end
|
|
148
|
-
else
|
|
149
|
-
super
|
|
45
|
+
result = find_has_many_relation(method)
|
|
46
|
+
return result if result
|
|
47
|
+
elsif constantize_model(method).respond_to?('first')
|
|
48
|
+
result = find_belongs_to_relation(method)
|
|
49
|
+
return result if result
|
|
150
50
|
end
|
|
51
|
+
|
|
52
|
+
super
|
|
151
53
|
rescue NameError => e
|
|
152
54
|
if e.message.include?('constant')
|
|
153
55
|
Error.throw_error('102', e.message.split(' ')[-1], layout_name)
|
|
@@ -156,6 +58,20 @@ module Trophonius
|
|
|
156
58
|
end
|
|
157
59
|
end
|
|
158
60
|
|
|
61
|
+
def respond_to_missing?(method, include_private = false)
|
|
62
|
+
if ActiveSupport::Inflector.pluralize(method).to_s == method.to_s
|
|
63
|
+
target_model = constantize_model(method)
|
|
64
|
+
return true if target_model.belongs_to_relations[parameterize_name(model_name)]
|
|
65
|
+
else
|
|
66
|
+
target_model = constantize_model(method)
|
|
67
|
+
relation_key = parameterize_name(ActiveSupport::Inflector.pluralize(model_name))
|
|
68
|
+
return true if target_model.has_many_relations[relation_key]
|
|
69
|
+
end
|
|
70
|
+
super
|
|
71
|
+
rescue NameError
|
|
72
|
+
super
|
|
73
|
+
end
|
|
74
|
+
|
|
159
75
|
##
|
|
160
76
|
# Runs a FileMaker script from the context of the Model.
|
|
161
77
|
#
|
|
@@ -216,6 +132,11 @@ module Trophonius
|
|
|
216
132
|
# @return [True] if successful
|
|
217
133
|
def update(field_data, portal_data: {})
|
|
218
134
|
url = "layouts/#{layout_name}/records/#{record_id}"
|
|
135
|
+
differences = calculate_differences_before_update(field_data, portal_data)
|
|
136
|
+
puts differences
|
|
137
|
+
puts differences.all? { |diff| diff.length.zero? }
|
|
138
|
+
return if differences.all? { |diff| diff.length.zero? }
|
|
139
|
+
|
|
219
140
|
field_data.each_key { |field| modifiable_fields[field] = field_data[field] }
|
|
220
141
|
field_data.transform_keys! { |k| (@model.translations[k.to_s] || k).to_s }
|
|
221
142
|
@model.run_before_update
|
|
@@ -289,6 +210,10 @@ module Trophonius
|
|
|
289
210
|
def define_portal_methods(fm_record)
|
|
290
211
|
fm_record['portalData'].each_key do |key|
|
|
291
212
|
method_name = methodize_field(key)
|
|
213
|
+
relation_name = portal_relation_name(fm_record.dig('portalData', key, 0))
|
|
214
|
+
@portals.push(key)
|
|
215
|
+
@portals.push(relation_name) unless relation_name == key
|
|
216
|
+
|
|
292
217
|
define_singleton_method(method_name) { self[key] }
|
|
293
218
|
fm_record['portalData'][key].each do |portal_record|
|
|
294
219
|
portal_record.each_key do |inner_key|
|
|
@@ -311,5 +236,111 @@ module Trophonius
|
|
|
311
236
|
Error.throw_error('102')
|
|
312
237
|
end
|
|
313
238
|
end
|
|
239
|
+
|
|
240
|
+
def constantize_model(name)
|
|
241
|
+
ActiveSupport::Inflector.constantize(
|
|
242
|
+
ActiveSupport::Inflector.classify(
|
|
243
|
+
ActiveSupport::Inflector.singularize(name.to_s)
|
|
244
|
+
)
|
|
245
|
+
)
|
|
246
|
+
end
|
|
247
|
+
|
|
248
|
+
def parameterize_name(name)
|
|
249
|
+
ActiveSupport::Inflector.parameterize(name.to_s).to_sym
|
|
250
|
+
end
|
|
251
|
+
|
|
252
|
+
def resolve_field(model, field_key)
|
|
253
|
+
model.create_translations if model.translations.keys.empty?
|
|
254
|
+
if model.translations.key?(field_key)
|
|
255
|
+
model.translations[field_key].to_s
|
|
256
|
+
else
|
|
257
|
+
field_key.to_s
|
|
258
|
+
end
|
|
259
|
+
end
|
|
260
|
+
|
|
261
|
+
def build_relation_record_set(model, layout, data)
|
|
262
|
+
ret_val = RecordSet.new(layout, model.non_modifiable_fields)
|
|
263
|
+
data.each { |r| ret_val << model.build_result(r) }
|
|
264
|
+
ret_val
|
|
265
|
+
end
|
|
266
|
+
|
|
267
|
+
def handle_relation_field_error(code, query_field, layout)
|
|
268
|
+
return unless code == '102'
|
|
269
|
+
|
|
270
|
+
results = DatabaseRequest.retrieve_first(layout)
|
|
271
|
+
if results['messages'][0]['code'] == '0'
|
|
272
|
+
r_results = results['response']['data']
|
|
273
|
+
if r_results.empty?
|
|
274
|
+
Error.throw_error('102')
|
|
275
|
+
else
|
|
276
|
+
ret_val = r_results[0]['fieldData']
|
|
277
|
+
Error.throw_error('102', ([query_field] - ret_val.keys.map(&:downcase)).flatten.join(', '), layout)
|
|
278
|
+
end
|
|
279
|
+
else
|
|
280
|
+
Error.throw_error('102')
|
|
281
|
+
end
|
|
282
|
+
end
|
|
283
|
+
|
|
284
|
+
def execute_relation_query(target_model, query_field, query_value, limit:)
|
|
285
|
+
layout = target_model.layout_name
|
|
286
|
+
url = "/layouts/#{layout}/_find"
|
|
287
|
+
body = { query: [{ query_field => query_value.to_s }], limit: limit }.to_json
|
|
288
|
+
response = DatabaseRequest.make_request(url, 'post', body)
|
|
289
|
+
code = response['messages'][0]['code']
|
|
290
|
+
|
|
291
|
+
if code == '0'
|
|
292
|
+
build_relation_record_set(target_model, layout, response['response']['data'])
|
|
293
|
+
elsif code == '101' || code == '401'
|
|
294
|
+
RecordSet.new(layout, target_model.non_modifiable_fields)
|
|
295
|
+
else
|
|
296
|
+
handle_relation_field_error(code, query_field, layout)
|
|
297
|
+
Error.throw_error(code)
|
|
298
|
+
end
|
|
299
|
+
end
|
|
300
|
+
|
|
301
|
+
def find_has_many_relation(method)
|
|
302
|
+
target_model = constantize_model(method)
|
|
303
|
+
current_model = constantize_model(model_name)
|
|
304
|
+
relation = target_model.belongs_to_relations[parameterize_name(model_name)]
|
|
305
|
+
return nil unless relation
|
|
306
|
+
|
|
307
|
+
foreign_key_field = resolve_field(target_model, relation[:foreign_key])
|
|
308
|
+
primary_key_field = resolve_field(current_model, relation[:primary_key])
|
|
309
|
+
|
|
310
|
+
@response = execute_relation_query(
|
|
311
|
+
target_model,
|
|
312
|
+
foreign_key_field,
|
|
313
|
+
self[primary_key_field],
|
|
314
|
+
limit: 100_000
|
|
315
|
+
)
|
|
316
|
+
end
|
|
317
|
+
|
|
318
|
+
def find_belongs_to_relation(method)
|
|
319
|
+
current_model = constantize_model(model_name)
|
|
320
|
+
target_model = constantize_model(method)
|
|
321
|
+
relation = target_model.has_many_relations[parameterize_name(ActiveSupport::Inflector.pluralize(model_name))]
|
|
322
|
+
return nil unless relation
|
|
323
|
+
|
|
324
|
+
foreign_key_field = resolve_field(current_model, relation[:foreign_key])
|
|
325
|
+
primary_key_field = resolve_field(target_model, relation[:primary_key])
|
|
326
|
+
|
|
327
|
+
@response = execute_relation_query(
|
|
328
|
+
target_model,
|
|
329
|
+
primary_key_field,
|
|
330
|
+
self[foreign_key_field],
|
|
331
|
+
limit: 1
|
|
332
|
+
)
|
|
333
|
+
@response.first
|
|
334
|
+
end
|
|
335
|
+
|
|
336
|
+
def calculate_differences_before_update(field_data, portal_data)
|
|
337
|
+
fields = self.reject { |k,v| @portals.include?(k) || !field_data.keys.include?(k) }
|
|
338
|
+
portals = self.select { |k,v| @portals.include?(k) && portal_data.keys.include?(k) }
|
|
339
|
+
|
|
340
|
+
updated_fields = field_data.present? ? field_data.to_set - fields.to_set : []
|
|
341
|
+
updated_portals = portal_data.present? ? portal_data.to_set - portals.to_set : []
|
|
342
|
+
|
|
343
|
+
[updated_fields.to_h, updated_portals.to_h]
|
|
344
|
+
end
|
|
314
345
|
end
|
|
315
346
|
end
|
data/lib/translator.rb
CHANGED
|
@@ -11,5 +11,11 @@ module Trophonius
|
|
|
11
11
|
def methodize_portal_field(field_name)
|
|
12
12
|
ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.underscore(field_name.gsub(/\w+::/, '').to_s), separator: '_')
|
|
13
13
|
end
|
|
14
|
+
|
|
15
|
+
def portal_relation_name(first_related_record)
|
|
16
|
+
return '' if first_related_record.nil?
|
|
17
|
+
|
|
18
|
+
first_related_record.keys.map{ |f| f[/.*(?=::)/] }.tally.max_by(&:last).first
|
|
19
|
+
end
|
|
14
20
|
end
|
|
15
21
|
end
|
metadata
CHANGED
|
@@ -1,14 +1,14 @@
|
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
|
2
2
|
name: trophonius
|
|
3
3
|
version: !ruby/object:Gem::Version
|
|
4
|
-
version: 2.1
|
|
4
|
+
version: 2.2.1
|
|
5
5
|
platform: ruby
|
|
6
6
|
authors:
|
|
7
7
|
- Kempen Automatisering
|
|
8
8
|
autorequire:
|
|
9
9
|
bindir: bin
|
|
10
10
|
cert_chain: []
|
|
11
|
-
date:
|
|
11
|
+
date: 2026-04-13 00:00:00.000000000 Z
|
|
12
12
|
dependencies:
|
|
13
13
|
- !ruby/object:Gem::Dependency
|
|
14
14
|
name: redis
|
|
@@ -98,7 +98,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
|
98
98
|
- !ruby/object:Gem::Version
|
|
99
99
|
version: '0'
|
|
100
100
|
requirements: []
|
|
101
|
-
rubygems_version: 3.
|
|
101
|
+
rubygems_version: 3.5.5
|
|
102
102
|
signing_key:
|
|
103
103
|
specification_version: 4
|
|
104
104
|
summary: Link between Ruby (on Rails) and FileMaker.
|