Class: Trophonius::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/trophonius_model.rb

Overview

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.

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(config:) ⇒ Model

Returns a new instance of Model.



14
15
16
17
18
# File 'lib/trophonius_model.rb', line 14

def initialize(config:)
  @configuration = config
  @offset = ''
  @limit = ''
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missing(method, *args, &block) ⇒ Object



135
136
137
138
139
140
141
142
143
144
145
# File 'lib/trophonius_model.rb', line 135

def method_missing(method, *args, &block)
  if @current_query.respond_to?(method)
    args << self
    @current_query.send(method, args)
  elsif @current_query.response.respond_to?(method)
    ret_val = @current_query.run_query(method, *args, &block)
    @limit = ''
    @offset = ''
    ret_val
  end
end

Instance Attribute Details

#configurationObject (readonly)

Returns the value of attribute configuration.



11
12
13
# File 'lib/trophonius_model.rb', line 11

def configuration
  @configuration
end

#current_queryObject

Returns the value of attribute current_query.



12
13
14
# File 'lib/trophonius_model.rb', line 12

def current_query
  @current_query
end

Class Method Details

.all(sort: {}) ⇒ RecordSet

Retrieve the first 10000000 records from FileMaker from the context of the Model.

Parameters:

  • sort: (Hash) (defaults to: {})

    a hash containing the fields to sort by and the direction to sort in (optional)

Returns:

  • (RecordSet)

    : a RecordSet containing all the Record objects that correspond to the FileMaker records.



473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
# File 'lib/trophonius_model.rb', line 473

def self.all(sort: {})
  uri = URI::RFC2396_Parser.new
  results = Request.retrieve_all(layout_name, sort)
  count = results['response']['scriptResult'].to_i
  url = if @limit.empty? || @offset.empty?
          URI(
            uri.escape(
              "http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{
            Trophonius.config.database
          }/layouts/#{layout_name}/records?_limit=#{count == 0 ? 1_000_000 : count}"
            )
          )
        else
          URI(
            uri.escape(
              "http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{
            Trophonius.config.database
          }/layouts/#{layout_name}/records?_offset=#{@offset}&_limit=#{@limit}"
            )
          )
        end
  @limit = ''
  @offset = ''
  results = Request.make_request(url, "Bearer #{Request.get_token}", 'get', '{}')
  if results['messages'][0]['code'] == '0'
    r_results = results['response']['data']
    ret_val = RecordSet.new(layout_name, non_modifiable_fields)
    r_results.each do |r|
      hash = build_result(r)
      ret_val << hash
    end
    ret_val.result_count = count
    ret_val
  else
    Error.throw_error(results['messages'][0]['code'])
  end
end

.belongs_to(model_name, primary_key:, foreign_key:) ⇒ Object

Add a belongs to relationship.

Parameters:

  • model_name: (Symbol)

    the name of the model to build a relation with

  • primary_key: (String)

    the name of the field containing the primary to build the relation over

  • foreign_key: (String)

    the name of the field containing the primary to build the relation over



43
44
45
# File 'lib/trophonius_model.rb', line 43

def self.belongs_to(model_name, primary_key:, foreign_key:)
  @configuration.belongs_to_relations.merge!({ model_name => { primary_key: primary_key, foreign_key: foreign_key } })
end

.belongs_to_relationsHash

Returns the Hash containing the related parent models

Returns:

  • (Hash)

    parent models



90
91
92
# File 'lib/trophonius_model.rb', line 90

def self.belongs_to_relations
  @configuration.belongs_to_relations
end

.build_result(result) ⇒ Record

Builds the resulting Record

Parameters:

  • result: (JSON)

    the HTTP result from FileMaker

Returns:

  • (Record)

    A Record with singleton_methods for the fields where possible



378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
# File 'lib/trophonius_model.rb', line 378

def self.build_result(result)
  hash = Trophonius::Record.new(name)
  hash.record_id = result['recordId']
  hash.layout_name = layout_name
  hash.model_name = name

  result['fieldData'].keys.each do |key|
    # unless key[/\s/] || key[/\W/]
    @configuration.translations.merge!(
      { ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.underscore(key.to_s), separator: '_').downcase.to_s => key.to_s }
    )
    hash.send(:define_singleton_method, ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.underscore(key.to_s), separator: '_')) do
      hash[key]
    end
    unless non_modifiable_fields&.include?(key)
      @configuration.all_fields.merge!(
        ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.underscore(key.to_s), separator: '_').downcase =>
          ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.underscore(key.to_s), separator: '_')
      )
      hash.send(
        :define_singleton_method,
        "#{ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.underscore(key.to_s), separator: '_')}="
      ) do |new_val|
        hash[key] = new_val
        hash.modifiable_fields[key] = new_val
        hash.modified_fields[key] = new_val
      end
    end
    # end
    hash.merge!({ key => result['fieldData'][key] })
    hash.modifiable_fields.merge!({ key => result['fieldData'][key] }) unless non_modifiable_fields&.include?(key)
  end
  result['portalData'].keys.each do |key|
    unless key[/\s/] || key[/\W/]
      hash.send(:define_singleton_method, ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.underscore(key.to_s), separator: '_')) do
        hash[key]
      end
    end
    result['portalData'][key].each do |inner_hash|
      inner_hash.keys.each do |inner_key|
        inner_method =
          ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.underscore(inner_key.gsub(/\w+::/, '').to_s), separator: '_')
        unless inner_method[/\s/] || inner_method[/\W/]
          inner_hash.send(:define_singleton_method, inner_method.to_s) { inner_hash[inner_key] }
          inner_hash.send(:define_singleton_method, 'record_id') { inner_hash['recordId'] }
        end
      end
    end
    hash.merge!({ key => result['portalData'][key] })
  end
  hash
end

.config(configuration) ⇒ Object

Sets up the configuration for the model.

Parameters:

  • configuration: (Hash)

    the hash containing the config to setup the model correctly. configuration = “theFileMakerLayoutForThisModel”, non_modifiable_fields: [“an”, “array”, “containing”, “calculation_fields”, “etc.”]



25
26
27
28
29
30
31
32
33
34
35
# File 'lib/trophonius_model.rb', line 25

def self.config(configuration)
  @configuration ||= Configuration.new
  @configuration.layout_name = configuration[:layout_name]
  @configuration.non_modifiable_fields = configuration[:non_modifiable_fields]
  @configuration.all_fields = {}
  @configuration.translations = {}
  @configuration.has_many_relations = {}
  @configuration.belongs_to_relations = {}
  @offset = ''
  @limit = ''
end

.create(field_data, portalData: {}) ⇒ Record

Creates and saves a record in FileMaker

Parameters:

  • fieldData: (Hash)

    the fields to fill with the data

Returns:

  • (Record)

    the created record Model.create(fieldOne: “Data”)



178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
# File 'lib/trophonius_model.rb', line 178

def self.create(field_data, portalData: {})
  uri = URI::RFC2396_Parser.new
  url =
    URI(
      uri.escape(
        "http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{
          Trophonius.config.database
        }/layouts/#{layout_name}/records"
      )
    )
  new_field_data = {}
  create_translations if @configuration.translations.keys.empty?
  field_data.keys.each do |k|
    if @configuration.translations.keys.include?(k.to_s)
      new_field_data.merge!({ @configuration.translations[k.to_s].to_s => field_data[k] })
    else
      new_field_data.merge!({ k.to_s => field_data[k] })
    end
  end

  new_portal_data = {}
  portalData.each do |portal_name, portal_values|
    new_portal_data.merge!(
      portal_name =>
        portal_values.map do |record|
          record.each_with_object({}) do |(key, value), new_hash|
            new_hash["#{portal_name}::#{key}"] = value
          end
        end
    )
  end

  body =
    if new_portal_data == {}
      "{\"fieldData\": #{new_field_data.to_json} }"
    else
      "{\"fieldData\": #{new_field_data.to_json}, \"portalData\": #{new_portal_data.to_json}}"
    end
  response = Request.make_request(url, "Bearer #{Request.get_token}", 'post', body)
  if response['messages'][0]['code'] == '0'
    url =
      URI(
        uri.escape(
          "http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{
            Trophonius.config.database
          }/layouts/#{layout_name}/records/#{response['response']['recordId']}"
        )
      )
    ret_val = build_result(Request.make_request(url, "Bearer #{Request.get_token}", 'get', '{}')['response']['data'][0])
    ret_val.send(:define_singleton_method, 'result_count') { 1 }
    ret_val
  else
    if response['messages'][0]['code'] == '102'
      results = Request.retrieve_first(layout_name)
      if results['messages'][0]['code'] == '0'
        r_results = results['response']['data']
        ret_val = r_results.empty? ? Error.throw_error('102') : r_results[0]['fieldData']
        Error.throw_error('102', (new_field_data.keys.map(&:downcase) - ret_val.keys.map(&:downcase)).flatten.join(', '), layout_name)
      else
        Error.throw_error('102')
      end
    end
    Error.throw_error(response['messages'][0]['code'])
  end
end

.create_translationsHash

creates Rails -> FileMaker field translations by requesting the first record

Returns:

  • (Hash)

    translations of the fields Rails -> FileMaker



114
115
116
117
118
119
120
121
122
123
124
125
126
# File 'lib/trophonius_model.rb', line 114

def self.create_translations
  if Trophonius.config.fm_18
    field_names = Trophonius::Request.get_layout_field_names(layout_name)
    field_names.each do |field|
      @configuration.translations.merge!(
        { ActiveSupport::Inflector.parameterize(ActiveSupport::Inflector.underscore(field.to_s), separator: '_').downcase.to_s => field.to_s }
      )
    end
  else
    first
  end
  @configuration.translations
end

.delete(record_id) ⇒ Boolean

Deletes a record from FileMaker

Parameters:

  • record_id: (Integer)

    the record id to retrieve from FileMaker

Returns:

  • (Boolean)

    True if the delete was successful



322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
# File 'lib/trophonius_model.rb', line 322

def self.delete(record_id)
  uri = URI::RFC2396_Parser.new
  url =
    URI(
      uri.escape(
        "http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{
          Trophonius.config.database
        }/layouts/#{layout_name}/records/#{record_id}"
      )
    )
  response = Request.make_request(url, "Bearer #{Request.get_token}", 'delete', '{}')
  if response['messages'][0]['code'] == '0'
    true
  else
    Error.throw_error(response['messages'][0]['code'])
  end
end

.edit(record_id, field_data) ⇒ Boolean

Edits a record in FileMaker

Parameters:

  • record_id: (Integer)

    the record id to edit in FileMaker

  • fieldData: (Hash)

    A hash containing the fields to edit and the new data to fill them with

Returns:

  • (Boolean)

    True if the delete was successful



348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
# File 'lib/trophonius_model.rb', line 348

def self.edit(record_id, field_data)
  uri = URI::RFC2396_Parser.new
  url =
    URI(
      uri.escape(
        "http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{
          Trophonius.config.database
        }/layouts/#{layout_name}/records/#{record_id}"
      )
    )
  new_field_data = {}
  create_translations if @configuration.translations.keys.empty?
  field_data.keys.each do |k|
    if @configuration.translations.keys.include?(k.to_s)
      new_field_data.merge!({ @configuration.translations[k.to_s].to_s => field_data[k] })
    else
      new_field_data.merge!({ k.to_s => field_data[k] })
    end
  end
  body = "{\"fieldData\": #{new_field_data.to_json}}"
  response = Request.make_request(url, "Bearer #{Request.get_token}", 'patch', body)
  response['messages'][0]['code'] == '0' ? true : Error.throw_error(response['messages'][0]['code'])
end

.find(record_id) ⇒ Record

Finds and returns a Record corresponding to the record_id

Parameters:

  • record_id: (Integer)

    the record id to retrieve from FileMaker

Returns:



296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
# File 'lib/trophonius_model.rb', line 296

def self.find(record_id)
  uri = URI::RFC2396_Parser.new
  url =
    URI(
      uri.escape(
        "http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{
          Trophonius.config.database
        }/layouts/#{layout_name}/records/#{record_id}"
      )
    )
  response = Request.make_request(url, "Bearer #{Request.get_token}", 'get', '{}')
  if response['messages'][0]['code'] == '0'
    ret_val = build_result(response['response']['data'][0])
    ret_val.send(:define_singleton_method, 'result_count') { 1 }
    ret_val
  else
    Error.throw_error(response['messages'][0]['code'], record_id)
  end
end

.find_by(field_data) ⇒ Record

Finds and returns the first Record containing fitting the find request

Parameters:

  • fieldData: (Hash)

    the data to find

Returns:

  • (Record)

    a Record object that correspond to FileMaker record fitting the find request Model.find_by(fieldOne: “Data”)



251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
# File 'lib/trophonius_model.rb', line 251

def self.find_by(field_data)
  uri = URI::RFC2396_Parser.new
  url =
    URI(
      uri.escape(
        "http#{Trophonius.config.ssl == true ? 's' : ''}://#{Trophonius.config.host}/fmi/data/v1/databases/#{
          Trophonius.config.database
        }/layouts/#{layout_name}/_find?_limit=1"
      )
    )
  new_field_data = {}
  create_translations if @configuration.translations.keys.empty?
  field_data.keys.each do |k|
    if @configuration.translations.keys.include?(k.to_s)
      new_field_data.merge!({ @configuration.translations[k.to_s].to_s => field_data[k] })
    else
      new_field_data.merge!({ k.to_s => field_data[k] })
    end
  end
  body = { query: [new_field_data], limit: '100000' }.to_json
  response = Request.make_request(url, "Bearer #{Request.get_token}", 'post', body)

  if response['messages'][0]['code'] == '0'
    r_results = response['response']['data']
    ret_val = RecordSet.new(layout_name, non_modifiable_fields)
    r_results.each do |r|
      hash = build_result(r)
      ret_val << hash
    end
    ret_val.first
  else
    if response['messages'][0]['code'] == '101' || response['messages'][0]['code'] == '401'
      return RecordSet.new(layout_name, non_modifiable_fields)
    end

    Error.throw_error(response['messages'][0]['code'])
  end
end

.firstRecord

Retrieve the first record from FileMaker from the context of the Model.

Returns:

  • (Record)

    : a Record corresponding to the FileMaker record.



435
436
437
438
439
440
441
442
443
444
445
# File 'lib/trophonius_model.rb', line 435

def self.first
  results = Request.retrieve_first(layout_name)
  if results['messages'][0]['code'] == '0'
    r_results = results['response']['data']
    ret_val = r_results.empty? ? Trophonius::Record.new : build_result(r_results[0])
    ret_val.send(:define_singleton_method, 'result_count') { r_results.empty? ? 0 : 1 }
    ret_val
  else
    Error.throw_error(results['messages'][0]['code'])
  end
end

.has_many(model_name, primary_key:, foreign_key:) ⇒ Object

Add a has many relationship.

Parameters:

  • model_name: (Symbol)

    the name of the model to build a relation with

  • primary_key: (String)

    the name of the field containing the primary to build the relation over

  • foreign_key: (String)

    the name of the field containing the primary to build the relation over



53
54
55
# File 'lib/trophonius_model.rb', line 53

def self.has_many(model_name, primary_key:, foreign_key:)
  @configuration.has_many_relations.merge!({ model_name => { primary_key: primary_key, foreign_key: foreign_key } })
end

.has_many_relationsHash

Returns the Hash containing the related parent models

Returns:

  • (Hash)

    child models



82
83
84
# File 'lib/trophonius_model.rb', line 82

def self.has_many_relations
  @configuration.has_many_relations
end

.layout_nameString

Returns the FileMaker layout this Model corresponds to

Returns:

  • (String)

    layout name of the model



74
75
76
# File 'lib/trophonius_model.rb', line 74

def self.layout_name
  @configuration.layout_name
end

.method_missing(method, *args) ⇒ Object



128
129
130
131
132
133
# File 'lib/trophonius_model.rb', line 128

def self.method_missing(method, *args)
  new_instance = Trophonius::Model.new(config: @configuration)
  new_instance.current_query = Trophonius::Query.new(trophonius_model: self, limit: @limit, offset: @offset)
  args << new_instance
  new_instance.current_query.send(method, args) if new_instance.current_query.respond_to?(method)
end

.non_modifiable_fields[Array]

Returns the fields that FileMaker won’t allow us to modify

Returns:

  • ([Array])

    fields that FileMaker won’t allow us to modify



98
99
100
# File 'lib/trophonius_model.rb', line 98

def self.non_modifiable_fields
  @configuration.non_modifiable_fields
end

.paginate(page, limit) ⇒ Trophonius::Model

Limits the found record set.

Parameters:

  • page: (Integer)

    number of current page

  • limit: (Integer)

    number of records retreived

Returns:



64
65
66
67
68
# File 'lib/trophonius_model.rb', line 64

def self.paginate(page, limit)
  @offset = (((page * limit) - limit) + 1).to_s
  @limit = limit.to_s
  self
end

.run_script(script: '', scriptparameter: '') ⇒ String

Runs a FileMaker script from the context of the Model.

Parameters:

  • script: (String) (defaults to: '')

    the FileMaker script to run

  • scriptparameter: (String) (defaults to: '')

    the parameter required by the FileMaker script

Returns:

  • (String)

    : string representing the script result returned by FileMaker



455
456
457
458
459
460
461
462
463
464
465
# File 'lib/trophonius_model.rb', line 455

def self.run_script(script: '', scriptparameter: '')
  result = Request.run_script(script, scriptparameter, layout_name)
  if result['messages'][0]['code'] != '0'
    Error.throw_error(result['messages'][0]['code'])
  elsif result['response']['scriptResult'] == '403'
    Error.throw_error(403)
  else
    result['response']['scriptResult']

  end
end

.translationsHash

Returns the translations of the fields

Returns:

  • (Hash)

    translations of the fields Rails -> FileMaker



106
107
108
# File 'lib/trophonius_model.rb', line 106

def self.translations
  @configuration.translations
end

.where(field_data) ⇒ Trophonius::Model

Finds all records in FileMaker corresponding to the requested query

Parameters:

  • fieldData: (Hash)

    the data to find

Returns:



152
153
154
155
156
157
# File 'lib/trophonius_model.rb', line 152

def self.where(field_data)
  new_instance = Trophonius::Model.new(config: @configuration)
  new_instance.current_query = Trophonius::Query.new(trophonius_model: self, limit: @limit, offset: @offset)
  new_instance.current_query.build_query[0].merge!(field_data)
  new_instance
end

Instance Method Details

#where(field_data) ⇒ Trophonius::Model

Finds all records in FileMaker corresponding to the requested query This method is created to enable where chaining

Parameters:

  • fieldData: (Hash)

    the data to find

Returns:



166
167
168
169
# File 'lib/trophonius_model.rb', line 166

def where(field_data)
  @current_query.build_query[0].merge!(field_data)
  self
end