trophonius 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
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: []