Class: Trophonius::Model

Inherits:
Object
  • Object
show all
Defined in:
lib/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.



21
22
23
24
25
# File 'lib/model.rb', line 21

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



225
226
227
228
229
230
231
232
233
234
235
# File 'lib/model.rb', line 225

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.



18
19
20
# File 'lib/model.rb', line 18

def configuration
  @configuration
end

#current_queryObject

Returns the value of attribute current_query.



19
20
21
# File 'lib/model.rb', line 19

def current_query
  @current_query
end

Class Method Details

.after_create(procedure, args) ⇒ Object



51
52
53
# File 'lib/model.rb', line 51

def self.after_create(procedure, args)
  @configuration.callbacks[:after_create].push({ name: procedure, args: args })
end

.after_destroy(procedure, args) ⇒ Object



75
76
77
# File 'lib/model.rb', line 75

def self.after_destroy(procedure, args)
  @configuration.callbacks[:after_destroy].push({ name: procedure, args: args })
end

.after_update(procedure, args) ⇒ Object



63
64
65
# File 'lib/model.rb', line 63

def self.after_update(procedure, args)
  @configuration.callbacks[:after_update].push({ name: procedure, args: args })
end

.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.



439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
# File 'lib/model.rb', line 439

def self.all(sort: {})
  create_translations if @configuration.translations.keys.empty?
  path = "/layouts/#{layout_name}/records?"
  path += @limit.present? ? "_limit=#{@limit}" : '_limit=10000000'
  path += "&_offset=#{@offset}" if @offset.present?
  sort = sort.map { |k, v| { fieldName: k, sortOrder: v } }
  path += "&_sort=#{sort.to_json}" unless sort.blank?

  @limit = ''
  @offset = ''
  results = DatabaseRequest.make_request(path, '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

.before_create(procedure, args) ⇒ Object



87
88
89
# File 'lib/model.rb', line 87

def self.before_create(procedure, args)
  @configuration.callbacks[:before_create].push({ name: procedure, args: args })
end

.before_destroy(procedure, args) ⇒ Object



111
112
113
# File 'lib/model.rb', line 111

def self.before_destroy(procedure, args)
  @configuration.callbacks[:before_destroy].push({ name: procedure, args: args })
end

.before_update(procedure, args) ⇒ Object



99
100
101
# File 'lib/model.rb', line 99

def self.before_update(procedure, args)
  @configuration.callbacks[:before_update].push({ name: procedure, args: args })
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



129
130
131
# File 'lib/model.rb', line 129

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



176
177
178
# File 'lib/model.rb', line 176

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



390
391
392
393
394
# File 'lib/model.rb', line 390

def self.build_result(result)
  record = Trophonius::Record.new(result, name)
  record.layout_name = layout_name
  record
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.”]



33
34
35
36
37
38
39
40
41
42
43
# File 'lib/model.rb', line 33

def self.config(configuration)
  @configuration ||= Configuration.new
  @configuration.layout_name = configuration[:layout_name]
  @configuration.non_modifiable_fields = configuration[:non_modifiable_fields] || []
  @configuration.translations = {}
  @configuration.has_many_relations = {}
  @configuration.belongs_to_relations = {}
  @configuration.callbacks = { before_create: [], before_update: [], before_destroy: [], after_create: [], after_update: [], after_destroy: [] }
  @offset = ''
  @limit = ''
end

.create(field_data, portal_data: {}) ⇒ 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”)



270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
# File 'lib/model.rb', line 270

def self.create(field_data, portal_data: {})
  create_translations if @configuration.translations.keys.empty?
  run_before_create

  field_data.transform_keys! { |k| (@configuration.translations[k.to_s] || k).to_s }

  portal_data.each do |portal_name, values|
    values.map { |record| record.transform_keys! { |k| "#{portal_name}::#{k}" } }
  end

  body = { fieldData: field_data }
  body.merge!({ portalData: portal_data }) if portal_data.present?

  response = DatabaseRequest.make_request("/layouts/#{layout_name}/records", 'post', body.to_json)

  return throw_field_missing(field_data) if response['messages'][0]['code'] == '102'

  return Error.throw_error(response['messages'][0]['code']) if response['messages'][0]['code'] != '0'

  new_record = DatabaseRequest.make_request("/layouts/#{layout_name}/records/#{response['response']['recordId']}", 'get', '{}')
  record = build_result(new_record['response']['data'][0])
  record.send(:define_singleton_method, 'result_count') { 1 }
  run_after_create

  record
end

.create_translationsHash

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

Returns:

  • (Hash)

    translations of the fields Rails -> FileMaker



200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
# File 'lib/model.rb', line 200

def self.create_translations
  extend Trophonius::Translator
  field_names = if Trophonius.config.fm_18
                  Trophonius::DatabaseRequest.get_layout_field_names(layout_name)
                else
                  DatabaseRequest.retrieve_first(layout_name).dig(
                    'response', 'data', 0, 'fieldData'
                  ).keys
                end
  field_names.each do |field|
    new_name = methodize_field(field.to_s).to_s
    @configuration.translations.merge!(
      { new_name => field.to_s }
    )
  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



348
349
350
351
352
353
354
355
356
357
358
359
# File 'lib/model.rb', line 348

def self.delete(record_id)
  create_translations if @configuration.translations.keys.empty?

  url = "layouts/#{layout_name}/records/#{record_id}"
  response = DatabaseRequest.make_request(url, '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



369
370
371
372
373
374
375
376
377
378
379
380
381
382
# File 'lib/model.rb', line 369

def self.edit(record_id, field_data)
  url = "layouts/#{layout_name}/records/#{record_id}"
  new_field_data = {}
  create_translations if @configuration.translations.keys.empty?

  field_data.each_key do |k|
    field_name = (@configuration.translations[k.to_s] || k).to_s
    new_field_data.merge!({ field_name => field_data[k] })
  end

  body = "{\"fieldData\": #{new_field_data.to_json}}"
  response = DatabaseRequest.make_request(url, '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:



328
329
330
331
332
333
334
335
336
337
338
339
340
# File 'lib/model.rb', line 328

def self.find(record_id)
  create_translations if @configuration.translations.keys.empty?

  url = "layouts/#{layout_name}/records/#{record_id}"
  response = DatabaseRequest.make_request(url, '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”)



304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
# File 'lib/model.rb', line 304

def self.find_by(field_data)
  url = "layouts/#{layout_name}/_find?_limit=1"
  create_translations if @configuration.translations.keys.empty?

  field_data.transform_keys! { |k| (@configuration.translations[k.to_s] || k).to_s }

  body = { query: [field_data], limit: '1' }.to_json
  response = DatabaseRequest.make_request(url, 'post', body)
  code = response['messages'][0]['code']

  return nil if %w[101 401].include?(code)

  Error.throw_error(code) if code != '0'

  r_results = response['response']['data']
  build_result(r_results.first) if r_results.first.present?
end

.firstRecord

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

Returns:

  • (Record)

    : a Record corresponding to the FileMaker record.



400
401
402
403
404
405
406
407
408
409
410
411
# File 'lib/model.rb', line 400

def self.first
  create_translations if @configuration.translations.keys.empty?
  results = DatabaseRequest.retrieve_first(layout_name)
  if results['messages'][0]['code'] == '0'
    r_results = results['response']['data']
    ret_val = r_results.empty? ? Trophonius::Record.new({}, name) : 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



139
140
141
# File 'lib/model.rb', line 139

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



168
169
170
# File 'lib/model.rb', line 168

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



160
161
162
# File 'lib/model.rb', line 160

def self.layout_name
  @configuration.layout_name
end

.method_missing(method, *args) ⇒ Object



218
219
220
221
222
223
# File 'lib/model.rb', line 218

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



184
185
186
# File 'lib/model.rb', line 184

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:



150
151
152
153
154
# File 'lib/model.rb', line 150

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

.run_after_createObject



55
56
57
58
59
60
61
# File 'lib/model.rb', line 55

def self.run_after_create
  @configuration.callbacks[:after_create].each do |callback|
    procedure = callback[:name]
    args = callback[:args]
    procedure.is_a?(Proc) ? procedure.call(*args) : send(procedure, *args)
  end
end

.run_after_destroyObject



79
80
81
82
83
84
85
# File 'lib/model.rb', line 79

def self.run_after_destroy
  @configuration.callbacks[:after_destroy].each do |callback|
    procedure = callback[:name]
    args = callback[:args]
    procedure.is_a?(Proc) ? procedure.call(*args) : send(procedure, *args)
  end
end

.run_after_updateObject



67
68
69
70
71
72
73
# File 'lib/model.rb', line 67

def self.run_after_update
  @configuration.callbacks[:after_update].each do |callback|
    procedure = callback[:name]
    args = callback[:args]
    procedure.is_a?(Proc) ? procedure.call(*args) : send(procedure, *args)
  end
end

.run_before_createObject



91
92
93
94
95
96
97
# File 'lib/model.rb', line 91

def self.run_before_create
  @configuration.callbacks[:before_create].each do |callback|
    procedure = callback[:name]
    args = callback[:args]
    procedure.is_a?(Proc) ? procedure.call(*args) : send(procedure, *args)
  end
end

.run_before_destroyObject



115
116
117
118
119
120
121
# File 'lib/model.rb', line 115

def self.run_before_destroy
  @configuration.callbacks[:before_destroy].each do |callback|
    procedure = callback[:name]
    args = callback[:args]
    procedure.is_a?(Proc) ? procedure.call(*args) : send(procedure, *args)
  end
end

.run_before_updateObject



103
104
105
106
107
108
109
# File 'lib/model.rb', line 103

def self.run_before_update
  @configuration.callbacks[:before_update].each do |callback|
    procedure = callback[:name]
    args = callback[:args]
    procedure.is_a?(Proc) ? procedure.call(*args) : send(procedure, *args)
  end
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



421
422
423
424
425
426
427
428
429
430
431
# File 'lib/model.rb', line 421

def self.run_script(script: '', scriptparameter: '')
  create_translations if @configuration.translations.keys.empty?
  result = DatabaseRequest.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

.scope(name, procedure, *_args) ⇒ Object



45
46
47
48
49
# File 'lib/model.rb', line 45

def self.scope(name, procedure, *_args)
  define_singleton_method(name) do |*args|
    procedure.arity.zero? ? procedure.call : procedure.call(*args)
  end
end

.translationsHash

Returns the translations of the fields

Returns:

  • (Hash)

    translations of the fields Rails -> FileMaker



192
193
194
# File 'lib/model.rb', line 192

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:



242
243
244
245
246
247
248
249
# File 'lib/model.rb', line 242

def self.where(field_data)
  create_translations if @configuration.translations.keys.empty?

  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:



258
259
260
261
# File 'lib/model.rb', line 258

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