trophonius 1.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 ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 5c744efd7c138bb2666a5fbe75aca5098a8503e06c235ed19014e175e331efbb
4
+ data.tar.gz: e58679a2dd7b909e5349b3493a58262c74f3a251de1ff7245d7491379606cae3
5
+ SHA512:
6
+ metadata.gz: 8fcf452c57e99c7bd282712c46d564d21801f383a9a4af39cfbb49c81077bd03133c738f7ce343afaed05efa1b13394f51a8f6afacf5c5880896b2c6735fad8b
7
+ data.tar.gz: 9dfe62d1a27018d9d2cf9f706af9333f84ff92680a68d8afd891d3c572ee1b0ea475679d73a8f85a6a3aab170ffdd6850acf8f06e0ac98246b57ce950aaaeaf9
data/lib/trophonius.rb ADDED
@@ -0,0 +1,19 @@
1
+ require 'trophonius_request'
2
+ require 'trophonius_model'
3
+ require 'trophonius_config'
4
+
5
+ module Trophonius # :nodoc:
6
+ def self.configuration
7
+ @configuration ||= Configuration.new
8
+ end
9
+
10
+ def self.configure
11
+ yield configuration
12
+ end
13
+
14
+ def self.config
15
+ @configuration
16
+ end
17
+
18
+ private
19
+ end
@@ -0,0 +1,18 @@
1
+ require 'active_support/configurable'
2
+
3
+ module Trophonius
4
+ class Trophonius::Configuration # :nodoc:
5
+ include ActiveSupport::Configurable
6
+
7
+ config_accessor(:host) { '127.0.0.1' }
8
+ config_accessor(:port) { 0 }
9
+ config_accessor(:database) { '' }
10
+ config_accessor(:username) { 'Admin' }
11
+ config_accessor(:password) { '' }
12
+ config_accessor(:ssl) { true }
13
+ config_accessor(:count_result_script) { '' }
14
+ config_accessor(:layout_name) { '' }
15
+ config_accessor(:non_modifiable_fields) { [] }
16
+ config_accessor(:local_network) { false }
17
+ end
18
+ end
@@ -0,0 +1,90 @@
1
+ require 'base64'
2
+ require 'typhoeus'
3
+
4
+ module Trophonius
5
+ module Trophonius::Connection
6
+ ##
7
+ # Creates a new connection to FileMaker
8
+ #
9
+ # @return [String] the *token* used to connect with the FileMaker data api
10
+
11
+ def self.connect
12
+ @token = setup_connection
13
+ @last_connection = Time.now
14
+ @token
15
+ end
16
+
17
+ ##
18
+ # Creates and runs a HTTP request to create a new data api connection
19
+ # This method throws an error when the request returns with a HTTP error or a FileMaker error
20
+ # @return [String] the *token* used to connect with the FileMaker data api if successful
21
+
22
+ def self.setup_connection
23
+ @token = ''
24
+ ssl_verifyhost = Trophonius.config.local_network ? 0 : 2
25
+ ssl_verifypeer = !Trophonius.config.local_network
26
+ url = URI("http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/sessions")
27
+ request = Typhoeus::Request.new(
28
+ url,
29
+ method: :post,
30
+ body: {},
31
+ params: {},
32
+ ssl_verifyhost: ssl_verifyhost,
33
+ ssl_verifypeer: ssl_verifypeer,
34
+ headers: { 'Content-Type' => 'application/json', Authorization: "Basic #{Base64.strict_encode64("#{Trophonius.config.username}:#{Trophonius.config.password}")}" }
35
+ )
36
+ temp = request.run
37
+
38
+ begin
39
+ parsed = JSON.parse(temp.response_body)
40
+ if parsed['messages'][0]['code'] != '0'
41
+ Error.throw_error(response['messages'][0]['code'])
42
+ end
43
+ return parsed['response']['token']
44
+ rescue Exception
45
+ Error.throw_error('1631')
46
+ end
47
+ end
48
+
49
+ ##
50
+ # Returns the last received token
51
+ # @return [String] the last valid *token* used to connect with the FileMaker data api
52
+ def self.token
53
+ @token
54
+ end
55
+
56
+ ##
57
+ # Returns the receive time of the last received token
58
+ # @return [Time] Returns the receive time of the last received token
59
+ def self.last_connection
60
+ @last_connection
61
+ end
62
+
63
+ ##
64
+ # Tests whether the FileMaker token is still valid
65
+ # @return [Boolean] True if the token is valid False if invalid
66
+ def self.test_connection
67
+ url = URI("http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{Trophonius.config.layout_name}/records?_limit=1")
68
+ begin
69
+ request = Typhoeus::Request.new(
70
+ url,
71
+ method: :get,
72
+ body: {},
73
+ params: {},
74
+ headers: { 'Content-Type' => 'application/json', Authorization: "Bearer #{@token}" }
75
+ )
76
+ temp = request.run
77
+ JSON.parse(temp.response_body)['messages'][0]['code'] == '0'
78
+ rescue StandardError
79
+ return false
80
+ end
81
+ end
82
+
83
+ ##
84
+ # Returns whether the current connection is still valid
85
+ # @return [Boolean] True if the connection is valid False if invalid
86
+ def self.valid_connection?
87
+ @last_connection.nil? ? false : (((Time.now - last_connection) / 60).round <= 15 || test_connection)
88
+ end
89
+ end
90
+ end
@@ -0,0 +1,297 @@
1
+ require 'json'
2
+ require 'trophonius_config'
3
+
4
+ module Trophonius
5
+ module Trophonius::Error
6
+ class RecordNotFoundError < StandardError; end # :nodoc:
7
+ class FieldUnexistingError < NoMethodError; end # :nodoc:
8
+ class ScriptUnexistingError < NoMethodError; end # :nodoc:
9
+ class LayoutUnexistingError < NoMethodError; end # :nodoc:
10
+ class InvalidTokenError < StandardError; end # :nodoc:
11
+ class UnauthenticatedError < StandardError; end # :nodoc:
12
+ class FieldNotModifiableError < StandardError; end # :nodoc:
13
+ class ResponseNotYetImplementedError < StandardError; end # :nodoc:
14
+ class UnknownFileMakerError < StandardError; end # :nodoc:
15
+ class UserCanceledError < StandardError; end # :nodoc:
16
+ class MemoryError < StandardError; end # :nodoc:
17
+ class FileError < StandardError; end # :nodoc:
18
+ class CommandError < StandardError; end # :nodoc:
19
+ class ConnectionError < StandardError; end # :nodoc:
20
+
21
+ ##
22
+ # Throws an error corresponding to the error number
23
+ # :args: error_id, more_info
24
+ def self.throw_error(error_id, more_info = 0)
25
+ case error_id
26
+ when '-1'
27
+ raise UnknownFileMakerError.new, 'Unknown Error Ocurred'
28
+ when '0'
29
+ raise UnknownFileMakerError.new, 'Unknown Error Ocurred'
30
+ when '1'
31
+ raise UserCanceledError.new, 'An outside source canceled the action'
32
+ when '2'
33
+ raise MemoryError.new, 'FileMaker encountered a memory error'
34
+ when '3'
35
+ raise CommandError.new, 'Command is unavailable (for example, wrong operating system or mode)'
36
+ when '4'
37
+ raise CommandError.new, 'Command is unknown'
38
+ when '5'
39
+ raise CommandError.new, 'Command is invalid, check your FileMaker script/calculation'
40
+ when '6'
41
+ raise FileError.new, 'File is read-only'
42
+ when '7'
43
+ raise MemoryError.new, 'FileMaker is running out of memory'
44
+ when '8'
45
+ raise RecordNotFoundError.new, 'Empty result'
46
+ when '9'
47
+ raise UnauthenticatedError.new, 'User has insufficient privileges'
48
+ # when "10"
49
+ # when "11"
50
+ # when "12"
51
+ # when "13"
52
+ # when "14"
53
+ # when "15"
54
+ # when "16"
55
+ # when "17"
56
+ # when "16"
57
+ # when "18"
58
+ # when "19"
59
+ # when "09"
60
+ # when "20"
61
+ # when "21"
62
+ # when "100"
63
+ when '101'
64
+ raise RecordNotFoundError.new, "Record #{more_info} was not found"
65
+ when '102'
66
+ raise FieldUnexistingError.new, 'Field does not exist'
67
+ # when "103"
68
+ when '104'
69
+ raise ScriptUnexistingError.new, 'Script does not exist'
70
+ when '105'
71
+ raise LayoutUnexistingError.new, 'Layout does not exist'
72
+ # when "106"
73
+ # when "107"
74
+ # when "108"
75
+ # when "109"
76
+ # when "110"
77
+ # when "111"
78
+ # when "112"
79
+ # when "113"
80
+ # when "114"
81
+ # when "115"
82
+ # when "116"
83
+ # when "117"
84
+ # when "118"
85
+ # when "130"
86
+ # when "131"
87
+ # when "200"
88
+ when '201'
89
+ raise FieldNotModifiableError.new, 'Trying to write to a read-only field'
90
+ # when "202"
91
+ # when "203"
92
+ # when "204"
93
+ # when "205"
94
+ # when "206"
95
+ # when "207"
96
+ # when "208"
97
+ # when "209"
98
+ # when "210"
99
+ # when "211"
100
+ # when "212"
101
+ # when "213"
102
+ # when "214"
103
+ # when "215"
104
+ # when "216"
105
+ # when "217"
106
+ # when "218"
107
+ # when "300"
108
+ # when "301"
109
+ # when "302"
110
+ # when "303"
111
+ # when "304"
112
+ # when "306"
113
+ # when "307"
114
+ # when "308"
115
+ # when "400"
116
+ when '401'
117
+ raise RecordNotFoundError.new, "Record #{more_info} was not found"
118
+ # when "402"
119
+ when '403'
120
+ raise UnauthenticatedError.new, 'You are unauthenticated to perform this request'
121
+ # when "404"
122
+ # when "405"
123
+ # when "406"
124
+ # when "407"
125
+ # when "408"
126
+ # when "409"
127
+ # when "410"
128
+ # when "412"
129
+ # when "413"
130
+ # when "414"
131
+ # when "415"
132
+ # when "416"
133
+ # when "417"
134
+ # when "418"
135
+ # when "500"
136
+ # when "501"
137
+ # when "502"
138
+ # when "503"
139
+ # when "504"
140
+ # when "505"
141
+ # when "506"
142
+ # when "507"
143
+ # when "508"
144
+ # when "509"
145
+ # when "510"
146
+ # when "511"
147
+ # when "512"
148
+ # when "513"
149
+ # when "600"
150
+ # when "601"
151
+ # when "602"
152
+ # when "603"
153
+ # when "700"
154
+ # when "706"
155
+ # when "707"
156
+ # when "708"
157
+ # when "711"
158
+ # when "714"
159
+ # when "715"
160
+ # when "716"
161
+ # when "717"
162
+ # when "718"
163
+ # when "719"
164
+ # when "720"
165
+ # when "721"
166
+ # when "722"
167
+ # when "723"
168
+ # when "724"
169
+ # when "725"
170
+ # when "726"
171
+ # when "727"
172
+ # when "729"
173
+ # when "730"
174
+ # when "731"
175
+ # when "732"
176
+ # when "733"
177
+ # when "734"
178
+ # when "735"
179
+ # when "736"
180
+ # when "738"
181
+ # when "800"
182
+ # when "801"
183
+ # when "802"
184
+ # when "803"
185
+ # when "804"
186
+ # when "805"
187
+ # when "806"
188
+ # when "807"
189
+ # when "808"
190
+ # when "809"
191
+ # when "810"
192
+ # when "811"
193
+ # when "812"
194
+ # when "813"
195
+ # when "814"
196
+ # when "815"
197
+ # when "816"
198
+ # when "817"
199
+ # when "819"
200
+ # when "820"
201
+ # when "821"
202
+ # when "822"
203
+ # when "823"
204
+ # when "824"
205
+ # when "825"
206
+ # when "826"
207
+ # when "827"
208
+ # when "850"
209
+ # when "851"
210
+ # when "852"
211
+ # when "853"
212
+ # when "900"
213
+ # when "901"
214
+ # when "902"
215
+ # when "903"
216
+ # when "905"
217
+ # when "906"
218
+ # when "920"
219
+ # when "921"
220
+ # when "922"
221
+ # when "923"
222
+ # when "951"
223
+ when '952'
224
+ raise InvalidTokenError.new, 'Could not retrieve a valid token from FileMaker, check your FileMaker server'
225
+ # when "954"
226
+ # when "955"
227
+ # when "956"
228
+ # when "957"
229
+ # when "958"
230
+ # when "959"
231
+ # when "960"
232
+ # when "1200"
233
+ # when "1201"
234
+ # when "1202"
235
+ # when "1203"
236
+ # when "1204"
237
+ # when "1205"
238
+ # when "1206"
239
+ # when "1207"
240
+ # when "1208"
241
+ # when "1209"
242
+ # when "1210"
243
+ # when "1211"
244
+ # when "1212"
245
+ # when "1213"
246
+ # when "1214"
247
+ # when "1215"
248
+ # when "1216"
249
+ # when "1217"
250
+ # when "1218"
251
+ # when "1219"
252
+ # when "1220"
253
+ # when "1221"
254
+ # when "1222"
255
+ # when "1223"
256
+ # when "1224"
257
+ # when "1225"
258
+ # when "1300"
259
+ # when "1301"
260
+ # when "1400"
261
+ # when "1401"
262
+ # when "1402"
263
+ # when "1403"
264
+ # when "1404"
265
+ # when "1405"
266
+ # when "1406"
267
+ # when "1407"
268
+ # when "1408"
269
+ # when "1409"
270
+ # when "1413"
271
+ # when "1414"
272
+ # when "1450"
273
+ # when "1451"
274
+ # when "1501"
275
+ # when "1502"
276
+ # when "1503"
277
+ # when "1504"
278
+ # when "1505"
279
+ # when "1506"
280
+ # when "1507"
281
+ # when "1550"
282
+ # when "1551"
283
+ # when "1626"
284
+ # when "1627"
285
+ # when "1628"
286
+ # when "1629"
287
+ # when "1630"
288
+ when '1631'
289
+ raise ConnectionError.new, 'An error occurred while attempting to connect to the FileMaker server'
290
+ # when "1632"
291
+ # when "1633"
292
+ else
293
+ raise ResponseNotYetImplementedError.new, "An unknown error has been encountered: err_no was #{error_id}"
294
+ end
295
+ end
296
+ end
297
+ end
@@ -0,0 +1,251 @@
1
+ require "json"
2
+ require "trophonius_config"
3
+ require "trophonius_record"
4
+ require "trophonius_recordset"
5
+ require "trophonius_error"
6
+
7
+ module Trophonius
8
+ # This class will retrieve the records from the FileMaker database and build a RecordSet filled with Record objects. One Record object represents a record in FileMaker.
9
+ class Trophonius::Model
10
+ # Contains all the fields on the model (modifiable and non_modifiable)
11
+ attr_reader :all_fields
12
+
13
+ ##
14
+ # Sets up the configuration for the model.
15
+ #
16
+ # @param [Hash] configuration: the hash containing the config to setup the model correctly.
17
+ # configuration = {layout_name: "theFileMakerLayoutForThisModel", non_modifiable_fields: ["an", "array", "containing", "calculation_fields", "etc."]}
18
+ def self.config(configuration)
19
+ @configuration ||= Configuration.new
20
+ @configuration.layout_name = configuration[:layout_name]
21
+ @configuration.non_modifiable_fields = configuration[:non_modifiable_fields]
22
+ @all_fields = {}
23
+ end
24
+
25
+ ##
26
+ # Returns the FileMaker layout this Model corresponds to
27
+ def self.layout_name
28
+ @configuration.layout_name
29
+ end
30
+
31
+ ##
32
+ # Returns the fields that FileMaker won't allow us to modify
33
+ def self.non_modifiable_fields
34
+ @configuration.non_modifiable_fields
35
+ end
36
+
37
+ ##
38
+ # Creates and saves a record in FileMaker
39
+ #
40
+ # @param [Hash] fieldData: the fields to fill with the data
41
+ #
42
+ # @return [Record] the created record
43
+ # Model.create(fieldOne: "Data")
44
+ def self.create(fieldData)
45
+ url = URI("http#{Trophonius.config.ssl == true ? "s" : ""}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records")
46
+ body = "{\"fieldData\": #{fieldData.to_json}}"
47
+ response = Request.make_request(url, "Bearer #{Request.get_token}", "post", body)
48
+ if response["messages"][0]["code"] != "0"
49
+ Error.throw_error(response["messages"][0]["code"])
50
+ else
51
+ url = URI("http#{Trophonius.config.ssl == true ? "s" : ""}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records/#{response["response"]["recordId"]}")
52
+ ret_val = build_result(Request.make_request(url, "Bearer #{Request.get_token}", "get", "{}")["response"]["data"][0])
53
+ ret_val.send(:define_singleton_method, "result_count") do
54
+ 1
55
+ end
56
+ return ret_val
57
+ end
58
+ end
59
+
60
+ ##
61
+ # Finds and returns a RecordSet containing the records fitting the find request
62
+ #
63
+ # @param [Hash] fieldData: the data to find
64
+ #
65
+ # @return [RecordSet] a RecordSet containing all the Record objects that correspond to FileMaker records fitting the find request
66
+ # Model.where(fieldOne: "Data")
67
+ def self.where(fieldData)
68
+ url = URI("http#{Trophonius.config.ssl == true ? "s" : ""}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{self.layout_name}/_find")
69
+ body = "{\"query\": [#{fieldData.to_json}]}"
70
+ response = Request.make_request(url, "Bearer #{Request.get_token}", "post", body)
71
+ if response["messages"][0]["code"] != "0"
72
+ return RecordSet.new(self.layout_name, self.non_modifiable_fields) if response["messages"][0]["code"] == "101" || response["messages"][0]["code"] == "401"
73
+ Error.throw_error(response["messages"][0]["code"])
74
+ else
75
+ r_results = response["response"]["data"]
76
+ ret_val = RecordSet.new(self.layout_name, self.non_modifiable_fields)
77
+ r_results.each do |r|
78
+ hash = build_result(r)
79
+ ret_val << hash
80
+ end
81
+ return ret_val
82
+ end
83
+ end
84
+
85
+ ##
86
+ # Finds and returns a Record corresponding to the record_id
87
+ #
88
+ # @param [Integer] record_id: the record id to retrieve from FileMaker
89
+ #
90
+ # @return [Record] the record
91
+ def self.find(record_id)
92
+ url = URI("http#{Trophonius.config.ssl == true ? "s" : ""}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records/#{record_id}")
93
+ response = Request.make_request(url, "Bearer #{Request.get_token}", "get", "{}")
94
+ if response["messages"][0]["code"] != "0"
95
+ Error.throw_error(response["messages"][0]["code"], record_id)
96
+ else
97
+ ret_val = build_result(response["response"]["data"][0])
98
+ ret_val.send(:define_singleton_method, "result_count") do
99
+ 1
100
+ end
101
+ return ret_val
102
+ end
103
+ end
104
+
105
+ ##
106
+ # Deletes a record from FileMaker
107
+ #
108
+ # @param [Integer] record_id: the record id to retrieve from FileMaker
109
+ #
110
+ # @return [Boolean] True if the delete was successful
111
+ def self.delete(record_id)
112
+ url = URI("http#{Trophonius.config.ssl == true ? "s" : ""}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records/#{record_id}")
113
+ response = Request.make_request(url, "Bearer #{Request.get_token}", "delete", "{}")
114
+ if response["messages"][0]["code"] != "0"
115
+ Error.throw_error(response["messages"][0]["code"])
116
+ else
117
+ return true
118
+ end
119
+ end
120
+
121
+ ##
122
+ # Edits a record in FileMaker
123
+ #
124
+ # @param [Integer] record_id: the record id to edit in FileMaker
125
+ #
126
+ # @param [Hash] fieldData: A hash containing the fields to edit and the new data to fill them with
127
+ #
128
+ # @return [Boolean] True if the delete was successful
129
+ def self.edit(record_id, fieldData)
130
+ url = URI("http#{Trophonius.config.ssl == true ? "s" : ""}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records/#{record_id}")
131
+ body = "{\"fieldData\": #{fieldData.to_json}}"
132
+ response = Request.make_request(url, "Bearer #{Request.get_token}", "patch", body)
133
+ if response["messages"][0]["code"] != "0"
134
+ Error.throw_error(response["messages"][0]["code"])
135
+ else
136
+ true
137
+ end
138
+ end
139
+
140
+ ##
141
+ # Builds the resulting Record
142
+ #
143
+ # @param [JSON] result: the HTTP result from FileMaker
144
+ #
145
+ # @return [Record] A Record with singleton_methods for the fields where possible
146
+ def self.build_result(result)
147
+ hash = Trophonius::Record.new()
148
+ hash.id = result["recordId"]
149
+ hash.layout_name = layout_name
150
+ result["fieldData"].keys.each do |key|
151
+ unless key[/\s/] || key[/\W/]
152
+ hash.send(:define_singleton_method, key.to_s) do
153
+ hash[key]
154
+ end
155
+ unless non_modifiable_fields&.include?(key)
156
+ @all_fields.merge!(key.to_s.downcase => key.to_s)
157
+ hash.send(:define_singleton_method, "#{key.to_s}=") do |new_val|
158
+ hash[key] = new_val
159
+ hash.modifiable_fields[key] = new_val
160
+ end
161
+ end
162
+ end
163
+ hash.merge!({key => result["fieldData"][key]})
164
+ unless non_modifiable_fields&.include?(key)
165
+ hash.modifiable_fields.merge!({key => result["fieldData"][key]})
166
+ end
167
+ end
168
+ result["portalData"].keys.each do |key|
169
+ unless key[/\s/] || key[/\W/]
170
+ hash.send(:define_singleton_method, key.to_s) do
171
+ hash[key]
172
+ end
173
+ end
174
+ result["portalData"][key].each_with_index do |inner_hash|
175
+ inner_hash.keys.each do |inner_key|
176
+ inner_method = inner_key.gsub(/\w+::/, "")
177
+ unless inner_method[/\s/] || inner_method[/\W/]
178
+ inner_hash.send(:define_singleton_method, inner_method.to_s) { inner_hash[inner_key] }
179
+ inner_hash.send(:define_singleton_method, "id") { inner_hash["recordId"] }
180
+ end
181
+ end
182
+ end
183
+ hash.merge!({key => result["portalData"][key]})
184
+ end
185
+ return hash
186
+ end
187
+
188
+ ##
189
+ # Retrieve the first record from FileMaker from the context of the Model.
190
+ #
191
+ # @return [Record]: a Record corresponding to the FileMaker record.
192
+ def self.first
193
+ results = Request.retrieve_first(layout_name)
194
+ if results["messages"][0]["code"] != "0"
195
+ Error.throw_error(results["messages"][0]["code"])
196
+ else
197
+ r_results = results["response"]["data"]
198
+ ret_val = r_results.empty? ? Trophonius::Record.new({}) : build_result(r_results[0])
199
+ ret_val.send(:define_singleton_method, "result_count") do
200
+ r_results.empty? ? 0 : 1
201
+ end
202
+ return ret_val
203
+ end
204
+ end
205
+
206
+ ##
207
+ # Runs a FileMaker script from the context of the Model.
208
+ #
209
+ # @param [String] script: the FileMaker script to run
210
+ #
211
+ # @param [String] scriptparameter: the parameter required by the FileMaker script
212
+ #
213
+ # @return [String]: string representing the script result returned by FileMaker
214
+ def self.run_script(script: "", scriptparameter: "")
215
+ result = Request.run_script(script, scriptparameter, layout_name)
216
+ if result["messages"][0]["code"] != "0"
217
+ Error.throw_error(result["messages"][0]["code"])
218
+ elsif result["response"]["scriptResult"] == "403"
219
+ Error.throw_error(403)
220
+ else
221
+ ret_val = result["response"]["scriptResult"]
222
+ return ret_val
223
+ end
224
+ end
225
+
226
+ ##
227
+ # Retrieve the first 10000000 records from FileMaker from the context of the Model.
228
+ #
229
+ # @param [Hash] sort: a hash containing the fields to sort by and the direction to sort in (optional)
230
+ #
231
+ # @return [RecordSet]: a RecordSet containing all the Record objects that correspond to the FileMaker records.
232
+ def self.all(sort: {})
233
+ results = Request.retrieve_all(layout_name, sort)
234
+ count = results["response"]["scriptResult"].to_i
235
+ url = URI("http#{Trophonius.config.ssl == true ? "s" : ""}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records?_limit=#{count == 0 ? 1000000 : count}")
236
+ results = Request.make_request(url, "Bearer #{Request.get_token}", "get", "{}")
237
+ if results["messages"][0]["code"] != "0"
238
+ Error.throw_error(results["messages"][0]["code"])
239
+ else
240
+ r_results = results["response"]["data"]
241
+ ret_val = RecordSet.new(self.layout_name, self.non_modifiable_fields)
242
+ r_results.each do |r|
243
+ hash = build_result(r)
244
+ ret_val << hash
245
+ end
246
+ ret_val.result_count = count
247
+ return ret_val
248
+ end
249
+ end
250
+ end
251
+ end
@@ -0,0 +1,74 @@
1
+ require 'json'
2
+ require 'trophonius_config'
3
+
4
+ module Trophonius
5
+ # This class will hold a singular record
6
+ #
7
+ # A Record is contained in a RecordSet and has methods to retrieve data from the fields inside the Record-hash
8
+ class Trophonius::Record < Hash
9
+ attr_accessor :id, :layout_name, :modifiable_fields
10
+
11
+ ##
12
+ # Initializes a new Record
13
+ def initialize
14
+ @modifiable_fields = {}
15
+ end
16
+
17
+ def []=(field, new_val)
18
+ modifiable_fields[field] = new_val
19
+ super
20
+ end
21
+
22
+ ##
23
+ # Saves the last changes made to the Record to FileMaker.
24
+ # Throws a FileMaker error if save failed
25
+ #
26
+ # @return [True] if successful
27
+ def save
28
+ url = URI("http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records/#{id}")
29
+ body = "{\"fieldData\": #{modifiable_fields.to_json}}"
30
+ response = Request.make_request(url, "Bearer #{Request.get_token}", 'patch', body)
31
+ if response['messages'][0]['code'] != '0'
32
+ Error.throw_error(response['messages'][0]['code'])
33
+ else
34
+ return true
35
+ end
36
+ end
37
+
38
+ ##
39
+ # Deletes the corresponding record from FileMaker
40
+ # Throws a FileMaker error if save failed
41
+ #
42
+ # @return [True] if successful
43
+ def delete
44
+ url = URI("http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records/#{id}")
45
+ response = Request.make_request(url, "Bearer #{Request.get_token}", 'delete', '{}')
46
+ if response['messages'][0]['code'] != '0'
47
+ Error.throw_error(response['messages'][0]['code'])
48
+ else
49
+ return true
50
+ end
51
+ end
52
+
53
+ ##
54
+ # Changes and saves the corresponding record in FileMaker
55
+ # Throws a FileMaker error if save failed
56
+ #
57
+ # @param [Hash] fieldData: Fields to be changed and data to fill the fields with
58
+ #
59
+ # @return [True] if successful
60
+ def update(fieldData)
61
+ url = URI("http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records/#{id}")
62
+ fieldData.keys.each do |field|
63
+ modifiable_fields[field] = fieldData[field]
64
+ end
65
+ body = "{\"fieldData\": #{fieldData.to_json}}"
66
+ response = Request.make_request(url, "Bearer #{Request.get_token}", 'patch', body)
67
+ if response['messages'][0]['code'] != '0'
68
+ Error.throw_error(response['messages'][0]['code'])
69
+ else
70
+ return true
71
+ end
72
+ end
73
+ end
74
+ end
@@ -0,0 +1,58 @@
1
+ require 'json'
2
+ require 'trophonius_config'
3
+ require 'trophonius_model'
4
+ require 'trophonius_connection'
5
+
6
+ module Trophonius
7
+ # A RecordSet contains all records, as Record, retrieved from the FileMaker database
8
+ class Trophonius::RecordSet < Array
9
+ attr_accessor :result_count, :layout_name, :non_modifiable_fields, :records
10
+
11
+ class EmptyParameterError < ArgumentError; end # :nodoc:
12
+
13
+ ##
14
+ # Initializes a new RecordSet
15
+ #
16
+ # @param [String] l_name: name of the FileMaker layout
17
+ #
18
+ # @param [Array] nmf: names of the fields that cannot be modified (calculation fields etc.)
19
+ def initialize(l_name, nmf)
20
+ self.layout_name = l_name
21
+ self.non_modifiable_fields = nmf
22
+ self.records = []
23
+ end
24
+
25
+ def <<(data)
26
+ records << data
27
+ super
28
+ end
29
+
30
+ ##
31
+ # This method allows to chain where statements
32
+ #
33
+ # @param [Hash] fielddata: hash containing the query
34
+ #
35
+ # @return [RecordSet] the records where the statement holds
36
+ def where(fielddata)
37
+ raise EmptyParameterError.new, 'No requested data to find' if fielddata.nil? || fielddata.empty?
38
+
39
+ temp = Trophonius::Model
40
+ temp.config layout_name: layout_name, non_modifiable_fields: non_modifiable_fields
41
+ retval = temp.where(fielddata)
42
+ retval
43
+ end
44
+
45
+ ##
46
+ # This method chops the RecordSet up in parts.
47
+ #
48
+ # @param [Integer] page: the current page
49
+ #
50
+ # @param [Integer] records_per_page: the amount of records on the page
51
+ #
52
+ # @return [RecordSet] the records in the range ((page * records_per_page) - records_per_page) + 1 until ((page * records_per_page) - records_per_page) + 1 + records_per_page
53
+ def paginate(page, records_per_page)
54
+ offset = ((page * records_per_page) - records_per_page) + 1
55
+ records[offset...offset + records_per_page]
56
+ end
57
+ end
58
+ end
@@ -0,0 +1,84 @@
1
+ require 'base64'
2
+ require 'trophonius_connection'
3
+
4
+ module Trophonius
5
+ module Trophonius::Request
6
+ ##
7
+ # Crafts and runs a HTTP request of any type
8
+ #
9
+ # @param [URI] urlparam: the url to make the request to
10
+ #
11
+ # @param [String] auth: the authentication required for the request
12
+ #
13
+ # @param [String] method: the type of HTTP request to make (i.e. get)
14
+ #
15
+ # @param [JSONString] body: the body of the HTTP request
16
+ #
17
+ # @param [String] params: optional parameters added to the request
18
+ #
19
+ # @return [JSON] parsed json of the response
20
+ def self.make_request(url_param, auth, method, body, params = '')
21
+ ssl_verifyhost = Trophonius.config.local_network ? 0 : 2
22
+ ssl_verifypeer = !Trophonius.config.local_network
23
+ request = Typhoeus::Request.new(
24
+ url_param,
25
+ method: method.to_sym,
26
+ body: body,
27
+ params: params,
28
+ ssl_verifyhost: ssl_verifyhost,
29
+ ssl_verifypeer: ssl_verifypeer,
30
+ headers: { 'Content-Type' => 'application/json', Authorization: auth.to_s }
31
+ )
32
+ temp = request.run
33
+ begin
34
+ JSON.parse(temp.response_body)
35
+ rescue Exception
36
+ Error.throw_error('1631')
37
+ end
38
+ end
39
+
40
+ ##
41
+ # Gets the current FileMaker token
42
+ #
43
+ # @return [String] a valid FileMaker token
44
+ def self.get_token
45
+ if Connection.valid_connection?
46
+ Connection.token
47
+ else
48
+ Connection.connect
49
+ end
50
+ end
51
+
52
+ ##
53
+ # Retrieves the first record from FileMaker
54
+ #
55
+ # @return [JSON] The first record from FileMaker
56
+ def self.retrieve_first(layout_name)
57
+ url = URI("http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records?_limit=1")
58
+ make_request(url, "Bearer #{get_token}", 'get', '{}')
59
+ end
60
+
61
+ ##
62
+ # Runs a FileMaker script
63
+ #
64
+ # @return [JSON] The script result from FileMaker
65
+ def self.run_script(script, scriptparameter, layout_name)
66
+ url = URI("http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records?_limit=1&script=#{script}&script.param=#{scriptparameter}")
67
+ make_request(url, "Bearer #{get_token}", 'get', '{}')
68
+ end
69
+
70
+ ##
71
+ # Retrieves the 10000000 records from FileMaker
72
+ #
73
+ # @return [JSON] The first 10000000 records from FileMaker
74
+ def self.retrieve_all(layout_name, sort)
75
+ if !sort.empty?
76
+ sort_order = sort.to_json.to_s
77
+ url = URI("http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records?_limit=10000000_sort=#{sort_order}#{Trophonius.config.count_result_script == '' ? '' : "&script=#{Trophonius.config.count_result_script}"}")
78
+ else
79
+ url = URI("http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{Trophonius.config.database}/layouts/#{layout_name}/records?_limit=10000000#{Trophonius.config.count_result_script == '' ? '' : "&script=#{Trophonius.config.count_result_script}"}")
80
+ end
81
+ make_request(url, "Bearer #{get_token}", 'get', '{}')
82
+ end
83
+ end
84
+ end
metadata ADDED
@@ -0,0 +1,114 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: trophonius
3
+ version: !ruby/object:Gem::Version
4
+ version: 1.0.0
5
+ platform: ruby
6
+ authors:
7
+ - Kempen Automatisering
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2018-11-13 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: typhoeus
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - "~>"
18
+ - !ruby/object:Gem::Version
19
+ version: '1.3'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - "~>"
25
+ - !ruby/object:Gem::Version
26
+ version: '1.3'
27
+ - !ruby/object:Gem::Dependency
28
+ name: redis
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "~>"
32
+ - !ruby/object:Gem::Version
33
+ version: '3.0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - "~>"
39
+ - !ruby/object:Gem::Version
40
+ version: '3.0'
41
+ - !ruby/object:Gem::Dependency
42
+ name: activesupport
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - "~>"
46
+ - !ruby/object:Gem::Version
47
+ version: '5.2'
48
+ type: :runtime
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - "~>"
53
+ - !ruby/object:Gem::Version
54
+ version: '5.2'
55
+ - !ruby/object:Gem::Dependency
56
+ name: solargraph
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - ">="
60
+ - !ruby/object:Gem::Version
61
+ version: 0.32.0
62
+ - - "~>"
63
+ - !ruby/object:Gem::Version
64
+ version: '0.32'
65
+ type: :development
66
+ prerelease: false
67
+ version_requirements: !ruby/object:Gem::Requirement
68
+ requirements:
69
+ - - ">="
70
+ - !ruby/object:Gem::Version
71
+ version: 0.32.0
72
+ - - "~>"
73
+ - !ruby/object:Gem::Version
74
+ version: '0.32'
75
+ description: An easy to use link between Ruby (on Rails) and FileMaker using the FileMaker
76
+ Data-API.
77
+ email:
78
+ executables: []
79
+ extensions: []
80
+ extra_rdoc_files: []
81
+ files:
82
+ - lib/trophonius.rb
83
+ - lib/trophonius_config.rb
84
+ - lib/trophonius_connection.rb
85
+ - lib/trophonius_error.rb
86
+ - lib/trophonius_model.rb
87
+ - lib/trophonius_record.rb
88
+ - lib/trophonius_recordset.rb
89
+ - lib/trophonius_request.rb
90
+ homepage:
91
+ licenses:
92
+ - MIT
93
+ metadata: {}
94
+ post_install_message:
95
+ rdoc_options: []
96
+ require_paths:
97
+ - lib
98
+ required_ruby_version: !ruby/object:Gem::Requirement
99
+ requirements:
100
+ - - ">="
101
+ - !ruby/object:Gem::Version
102
+ version: '0'
103
+ required_rubygems_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: '0'
108
+ requirements: []
109
+ rubyforge_project:
110
+ rubygems_version: 2.7.9
111
+ signing_key:
112
+ specification_version: 4
113
+ summary: Link between Ruby (on Rails) and FileMaker.
114
+ test_files: []