lardawge-rfm 1.4.0 → 1.4.1
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/rfm/{commands/database.rb → database.rb} +0 -0
- data/lib/rfm/error.rb +146 -216
- data/lib/rfm/{commands/layout.rb → layout.rb} +3 -56
- data/lib/rfm/metadata/field.rb +93 -0
- data/lib/rfm/metadata/script.rb +20 -0
- data/lib/rfm/record.rb +219 -0
- data/lib/rfm/resultset.rb +136 -0
- data/lib/rfm/{commands/server.rb → server.rb} +10 -11
- data/lib/rfm/utilities/case_insensitive_hash.rb +10 -0
- data/lib/rfm/{factory.rb → utilities/factory.rb} +6 -6
- data/lib/rfm.rb +12 -234
- data/spec/rfm/error_spec.rb +69 -0
- data/spec/spec_helper.rb +9 -0
- metadata +40 -20
- data/lib/rfm/commands/field_control.rb +0 -50
- data/lib/rfm/commands/script.rb +0 -18
- data/lib/rfm/result.rb +0 -446
- data/lib/rfm/utility.rb +0 -12
- data/test/errors_test.rb +0 -53
data/lib/rfm/result.rb
DELETED
@@ -1,446 +0,0 @@
|
|
1
|
-
# This module includes classes that represent FileMaker data. When you communicate with FileMaker
|
2
|
-
# using, ie, the Layout object, you typically get back ResultSet objects. These contain Records,
|
3
|
-
# which in turn contain Fields, Portals, and arrays of data.
|
4
|
-
#
|
5
|
-
# Author:: Geoff Coffey (mailto:gwcoffey@gmail.com)
|
6
|
-
# Copyright:: Copyright (c) 2007 Six Fried Rice, LLC and Mufaddal Khumri
|
7
|
-
# License:: See MIT-LICENSE for details
|
8
|
-
require 'nokogiri'
|
9
|
-
require 'bigdecimal'
|
10
|
-
require 'date'
|
11
|
-
|
12
|
-
module Rfm
|
13
|
-
module Result
|
14
|
-
|
15
|
-
# The ResultSet object represents a set of records in FileMaker. It is, in every way, a real Ruby
|
16
|
-
# Array, so everything you expect to be able to do with an Array can be done with a ResultSet as well.
|
17
|
-
# In this case, the elements in the array are Record objects.
|
18
|
-
#
|
19
|
-
# Here's a typical example, displaying the results of a Find:
|
20
|
-
#
|
21
|
-
# myServer = Rfm::Server.new(...)
|
22
|
-
# results = myServer["Customers"]["Details"].find("First Name" => "Bill")
|
23
|
-
# results.each {|record|
|
24
|
-
# puts record["First Name"]
|
25
|
-
# puts record["Last Name"]
|
26
|
-
# puts record["Email Address"]
|
27
|
-
# }
|
28
|
-
#
|
29
|
-
# =Attributes
|
30
|
-
#
|
31
|
-
# The ResultSet object has several useful attributes:
|
32
|
-
#
|
33
|
-
# * *server* is the server object this ResultSet came from
|
34
|
-
#
|
35
|
-
# * *fields* is a hash with field names for keys and Field objects for values; it provides
|
36
|
-
# metadata about the fields in the ResultSet
|
37
|
-
#
|
38
|
-
# * *portals* is a hash with table occurrence names for keys and arrays of Field objects for values;
|
39
|
-
# it provides metadata about the portals in the ResultSet and the Fields on those portals
|
40
|
-
|
41
|
-
class ResultSet < Array
|
42
|
-
|
43
|
-
# Initializes a new ResultSet object. You will probably never do this your self (instead, use the Layout
|
44
|
-
# object to get various ResultSet obejects).
|
45
|
-
#
|
46
|
-
# If you feel so inclined, though, pass a Server object, and some +fmpxmlresult+ compliant XML in a String.
|
47
|
-
#
|
48
|
-
# =Attributes
|
49
|
-
#
|
50
|
-
# The ResultSet object includes several useful attributes:
|
51
|
-
#
|
52
|
-
# * *fields* is a hash (with field names for keys and Field objects for values). It includes an entry for
|
53
|
-
# every field in the ResultSet. Note: You don't use Field objects to access _data_. If you're after
|
54
|
-
# data, get a Record object (ResultSet is an array of records). Field objects tell you about the fields
|
55
|
-
# (their type, repetitions, and so forth) in case you find that information useful programmatically.
|
56
|
-
#
|
57
|
-
# Note: keys in the +fields+ hash are downcased for convenience (and [] automatically downcases on
|
58
|
-
# lookup, so it should be seamless). But if you +each+ a field hash and need to know a field's real
|
59
|
-
# name, with correct case, do +myField.name+ instead of relying on the key in the hash.
|
60
|
-
#
|
61
|
-
# * *portals* is a hash (with table occurrence names for keys and Field objects for values). If your
|
62
|
-
# layout contains portals, you can find out what fields they contain here. Again, if it's the data you're
|
63
|
-
# after, you want to look at the Record object.
|
64
|
-
def initialize(server, fmresultset, layout = nil)
|
65
|
-
@server = server
|
66
|
-
@resultset = nil
|
67
|
-
@layout = layout
|
68
|
-
@fields = Rfm::Utility::CaseInsensitiveHash.new
|
69
|
-
@portals = Rfm::Utility::CaseInsensitiveHash.new
|
70
|
-
@date_format = nil
|
71
|
-
@time_format = nil
|
72
|
-
@timestamp_format = nil
|
73
|
-
@total_count = nil
|
74
|
-
@foundset_count = nil
|
75
|
-
|
76
|
-
doc = Nokogiri.XML(fmresultset)
|
77
|
-
|
78
|
-
#seperate content for less searching
|
79
|
-
datasource = doc.search('datasource')
|
80
|
-
resultset = doc.search('resultset')
|
81
|
-
metadata = doc.search('metadata')
|
82
|
-
|
83
|
-
# check for errors
|
84
|
-
error = doc.search('error').attribute('code').value.to_i
|
85
|
-
if error != 0 && (error != 401 || @server.state[:raise_on_401])
|
86
|
-
raise Rfm::Error::FileMakerError.getError(error)
|
87
|
-
end
|
88
|
-
|
89
|
-
# ascertain date and time formats
|
90
|
-
@date_format = convertFormatString(datasource.attribute('date-format').value)
|
91
|
-
@time_format = convertFormatString(datasource.attribute('time-format').value)
|
92
|
-
@timestamp_format = convertFormatString(datasource.attribute('timestamp-format').value)
|
93
|
-
|
94
|
-
# retrieve count
|
95
|
-
@foundset_count = resultset.attribute('count').value.to_i
|
96
|
-
@total_count = datasource.attribute('total-count').value.to_i
|
97
|
-
|
98
|
-
# process field metadata
|
99
|
-
metadata.search('field-definition').each do |field|
|
100
|
-
@fields[field['name']] = Field.new(self, field)
|
101
|
-
end
|
102
|
-
@fields.freeze
|
103
|
-
|
104
|
-
# process relatedset metadata
|
105
|
-
metadata.search('relatedset-definition').each do |relatedset|
|
106
|
-
table = relatedset.attribute('table').value
|
107
|
-
fields = {}
|
108
|
-
relatedset.search('field-definition').each do |field|
|
109
|
-
name = field.attribute('name').value.sub(Regexp.new(table + '::'), '')
|
110
|
-
fields[name] = Field.new(self, field)
|
111
|
-
end
|
112
|
-
@portals[table] = fields
|
113
|
-
end
|
114
|
-
@portals.freeze
|
115
|
-
|
116
|
-
# build record rows
|
117
|
-
resultset.search('record').each do |record|
|
118
|
-
self << Record.new(record, self, @fields, @layout)
|
119
|
-
end
|
120
|
-
end
|
121
|
-
|
122
|
-
attr_reader :server, :fields, :portals, :date_format, :time_format, :timestamp_format, :total_count, :foundset_count, :layout
|
123
|
-
|
124
|
-
private
|
125
|
-
|
126
|
-
def convertFormatString(fm_format)
|
127
|
-
fm_format.gsub('MM', '%m').gsub('dd', '%d').gsub('yyyy', '%Y').gsub('HH', '%H').gsub('mm', '%M').gsub('ss', '%S')
|
128
|
-
end
|
129
|
-
|
130
|
-
end
|
131
|
-
|
132
|
-
# The Record object represents a single FileMaker record. You typically get them from ResultSet objects.
|
133
|
-
# For example, you might use a Layout object to find some records:
|
134
|
-
#
|
135
|
-
# results = myLayout.find({"First Name" => "Bill"})
|
136
|
-
#
|
137
|
-
# The +results+ variable in this example now contains a ResultSet object. ResultSets are really just arrays of
|
138
|
-
# Record objects (with a little extra added in). So you can get a record object just like you would access any
|
139
|
-
# typical array element:
|
140
|
-
#
|
141
|
-
# first_record = results[0]
|
142
|
-
#
|
143
|
-
# You can find out how many record were returned:
|
144
|
-
#
|
145
|
-
# record_count = results.size
|
146
|
-
#
|
147
|
-
# And you can of course iterate:
|
148
|
-
#
|
149
|
-
# results.each (|record|
|
150
|
-
# // you can work with the record here
|
151
|
-
# )
|
152
|
-
#
|
153
|
-
# =Accessing Field Data
|
154
|
-
#
|
155
|
-
# You can access field data in the Record object in two ways. Typically, you simply treat Record like a hash
|
156
|
-
# (because it _is_ a hash...I love OOP). Keys are field names:
|
157
|
-
#
|
158
|
-
# first = myRecord["First Name"]
|
159
|
-
# last = myRecord["Last Name"]
|
160
|
-
#
|
161
|
-
# If your field naming conventions mean that your field names are also valid Ruby symbol named (ie: they contain only
|
162
|
-
# letters, numbers, and underscores) then you can treat them like attributes of the record. For example, if your fields
|
163
|
-
# are called "first_name" and "last_name" you can do this:
|
164
|
-
#
|
165
|
-
# first = myRecord.first_name
|
166
|
-
# last = myRecord.last_name
|
167
|
-
#
|
168
|
-
# Note: This shortcut will fail (in a rather mysterious way) if your field name happens to match any real attribute
|
169
|
-
# name of a Record object. For instance, you may have a field called "server". If you try this:
|
170
|
-
#
|
171
|
-
# server_name = myRecord.server
|
172
|
-
#
|
173
|
-
# you'll actually set +server_name+ to the Rfm::Server object this Record came from. This won't fail until you try
|
174
|
-
# to treat it as a String somewhere else in your code. It is also possible a future version of Rfm will include
|
175
|
-
# new attributes on the Record class which may clash with your field names. This will cause perfectly valid code
|
176
|
-
# today to fail later when you upgrade. If you can't stomach this kind of insanity, stick with the hash-like
|
177
|
-
# method of field access, which has none of these limitations. Also note that the +myRecord[]+ method is probably
|
178
|
-
# somewhat faster since it doesn't go through +method_missing+.
|
179
|
-
#
|
180
|
-
# =Accessing Repeating Fields
|
181
|
-
#
|
182
|
-
# If you have a repeating field, RFM simply returns an array:
|
183
|
-
#
|
184
|
-
# val1 = myRecord["Price"][0]
|
185
|
-
# val2 = myRecord["Price"][1]
|
186
|
-
#
|
187
|
-
# In the above example, the Price field is a repeating field. The code puts the first repetition in a variable called
|
188
|
-
# +val1+ and the second in a variable called +val2+.
|
189
|
-
#
|
190
|
-
# =Accessing Portals
|
191
|
-
#
|
192
|
-
# If the ResultSet includes portals (because the layout it comes from has portals on it) you can access them
|
193
|
-
# using the Record::portals attribute. It is a hash with table occurrence names for keys, and arrays of Record
|
194
|
-
# objects for values. In other words, you can do this:
|
195
|
-
#
|
196
|
-
# myRecord.portals["Orders"].each {|record|
|
197
|
-
# puts record["Order Number"]
|
198
|
-
# }
|
199
|
-
#
|
200
|
-
# This code iterates through the rows of the _Orders_ portal.
|
201
|
-
#
|
202
|
-
# =Field Types and Ruby Types
|
203
|
-
#
|
204
|
-
# RFM automatically converts data from FileMaker into a Ruby object with the most reasonable type possible. The
|
205
|
-
# type are mapped thusly:
|
206
|
-
#
|
207
|
-
# * *Text* fields are converted to Ruby String objects
|
208
|
-
#
|
209
|
-
# * *Number* fields are converted to Ruby BigDecimal objects (the basic Ruby numeric types have
|
210
|
-
# much less precision and range than FileMaker number fields)
|
211
|
-
#
|
212
|
-
# * *Date* fields are converted to Ruby Date objects
|
213
|
-
#
|
214
|
-
# * *Time* fields are converted to Ruby DateTime objects (you can ignore the date component)
|
215
|
-
#
|
216
|
-
# * *Timestamp* fields are converted to Ruby DateTime objects
|
217
|
-
#
|
218
|
-
# * *Container* fields are converted to Ruby URI objects
|
219
|
-
#
|
220
|
-
# =Attributes
|
221
|
-
#
|
222
|
-
# In addition to +portals+, the Record object has these useful attributes:
|
223
|
-
#
|
224
|
-
# * *record_id* is FileMaker's internal identifier for this record (_not_ any ID field you might have
|
225
|
-
# in your table); you need a +record_id+ to edit or delete a record
|
226
|
-
#
|
227
|
-
# * *mod_id* is the modification identifier for the record; whenever a record is modified, its +mod_id+
|
228
|
-
# changes so you can tell if the Record object you're looking at is up-to-date as compared to another
|
229
|
-
# copy of the same record
|
230
|
-
class Record < Rfm::Utility::CaseInsensitiveHash
|
231
|
-
|
232
|
-
# Initializes a Record object. You really really never need to do this yourself. Instead, get your records
|
233
|
-
# from a ResultSet object.
|
234
|
-
def initialize(row_element, resultset, fields, layout, portal=nil)
|
235
|
-
@record_id = row_element['record-id']
|
236
|
-
@mod_id = row_element['mod-id']
|
237
|
-
@mods = {}
|
238
|
-
@resultset = resultset
|
239
|
-
@layout = layout
|
240
|
-
|
241
|
-
@loaded = false
|
242
|
-
related_sets = row_element.search('relatedset')
|
243
|
-
|
244
|
-
row_element.search('field').each do |field|
|
245
|
-
field_name = field['name']
|
246
|
-
field_name.sub!(Regexp.new(portal + '::'), '') if portal
|
247
|
-
datum = []
|
248
|
-
field.search('data').each do |x|
|
249
|
-
datum.push(fields[field_name].coerce(x.inner_text))
|
250
|
-
end
|
251
|
-
if datum.length == 1
|
252
|
-
self[field_name] = datum[0]
|
253
|
-
elsif datum.length == 0
|
254
|
-
self[field_name] = nil
|
255
|
-
else
|
256
|
-
self[field_name] = datum
|
257
|
-
end
|
258
|
-
end
|
259
|
-
|
260
|
-
unless related_sets.empty?
|
261
|
-
@portals = Rfm::Utility::CaseInsensitiveHash.new
|
262
|
-
related_sets.each do |relatedset|
|
263
|
-
table = relatedset['table']
|
264
|
-
records = []
|
265
|
-
relatedset.search('record').each do |record|
|
266
|
-
records << Record.new(record, @resultset, @resultset.portals[table], @layout, table)
|
267
|
-
end
|
268
|
-
@portals[table] = records
|
269
|
-
end
|
270
|
-
end
|
271
|
-
@loaded = true
|
272
|
-
end
|
273
|
-
|
274
|
-
attr_reader :record_id, :mod_id, :portals
|
275
|
-
|
276
|
-
# Saves local changes to the Record object back to Filemaker. For example:
|
277
|
-
#
|
278
|
-
# myLayout.find({"First Name" => "Bill"}).each(|record|
|
279
|
-
# record["First Name"] = "Steve"
|
280
|
-
# record.save
|
281
|
-
# )
|
282
|
-
#
|
283
|
-
# This code finds every record with _Bill_ in the First Name field, then changes the first name to
|
284
|
-
# Steve.
|
285
|
-
#
|
286
|
-
# Note: This method is smart enough to not bother saving if nothing has changed. So there's no need
|
287
|
-
# to optimize on your end. Just save, and if you've changed the record it will be saved. If not, no
|
288
|
-
# server hit is incurred.
|
289
|
-
def save
|
290
|
-
self.merge(@layout.edit(self.record_id, @mods)[0]) if @mods.size > 0
|
291
|
-
@mods.clear
|
292
|
-
end
|
293
|
-
|
294
|
-
# Like Record::save, except it fails (and raises an error) if the underlying record in FileMaker was
|
295
|
-
# modified after the record was fetched but before it was saved. In other words, prevents you from
|
296
|
-
# accidentally overwriting changes someone else made to the record.
|
297
|
-
def save_if_not_modified
|
298
|
-
self.merge(@layout.edit(@record_id, @mods, {:modification_id => @mod_id})[0]) if @mods.size > 0
|
299
|
-
@mods.clear
|
300
|
-
end
|
301
|
-
|
302
|
-
# Gets the value of a field from the record. For example:
|
303
|
-
#
|
304
|
-
# first = myRecord["First Name"]
|
305
|
-
# last = myRecord["Last Name"]
|
306
|
-
#
|
307
|
-
# This sample puts the first and last name from the record into Ruby variables.
|
308
|
-
#
|
309
|
-
# You can also update a field:
|
310
|
-
#
|
311
|
-
# myRecord["First Name"] = "Sophia"
|
312
|
-
#
|
313
|
-
# When you do, the change is noted, but *the data is not updated in FileMaker*. You must call
|
314
|
-
# Record::save or Record::save_if_not_modified to actually save the data.
|
315
|
-
def []=(pname, value)
|
316
|
-
return super unless @loaded # keeps us from getting mods during initialization
|
317
|
-
name = pname
|
318
|
-
if self[name] != nil
|
319
|
-
@mods[name] = val
|
320
|
-
else
|
321
|
-
raise Rfm::Error::ParameterError.new("You attempted to modify a field called '#{name}' on the Rfm::Record object, but that field does not exist.")
|
322
|
-
end
|
323
|
-
end
|
324
|
-
|
325
|
-
def method_missing (symbol, *attrs)
|
326
|
-
# check for simple getter
|
327
|
-
return self[symbol.to_s] if self.include?(symbol.to_s)
|
328
|
-
|
329
|
-
# check for setter
|
330
|
-
symbol_name = symbol.to_s
|
331
|
-
if symbol_name[-1..-1] == '=' && self.has_key?(symbol_name[0..-2])
|
332
|
-
return @mods[symbol_name[0..-2]] = attrs[0]
|
333
|
-
end
|
334
|
-
super
|
335
|
-
end
|
336
|
-
|
337
|
-
def respond_to?(symbol, include_private = false)
|
338
|
-
return true if self[symbol.to_s] != nil
|
339
|
-
super
|
340
|
-
end
|
341
|
-
end
|
342
|
-
|
343
|
-
# The Field object represents a single FileMaker field. It *does not hold the data* in the field. Instead,
|
344
|
-
# it serves as a source of metadata about the field. For example, if you're script is trying to be highly
|
345
|
-
# dynamic about its field access, it may need to determine the data type of a field at run time. Here's
|
346
|
-
# how:
|
347
|
-
#
|
348
|
-
# field_name = "Some Field Name"
|
349
|
-
# case myRecord.fields[field_name].result
|
350
|
-
# when "text"
|
351
|
-
# # it is a text field, so handle appropriately
|
352
|
-
# when "number"
|
353
|
-
# # it is a number field, so handle appropriately
|
354
|
-
# end
|
355
|
-
#
|
356
|
-
# =Attributes
|
357
|
-
#
|
358
|
-
# The Field object has the following attributes useful attributes:
|
359
|
-
#
|
360
|
-
# * *name* is the name of the field
|
361
|
-
#
|
362
|
-
# * *result* is the data type of the field; possible values include:
|
363
|
-
# * text
|
364
|
-
# * number
|
365
|
-
# * date
|
366
|
-
# * time
|
367
|
-
# * timestamp
|
368
|
-
# * container
|
369
|
-
#
|
370
|
-
# * *type* any of these:
|
371
|
-
# * normal (a normal data field)
|
372
|
-
# * calculation
|
373
|
-
# * summary
|
374
|
-
#
|
375
|
-
# * *max_repeats* is the number of repetitions (1 for a normal field, more for a repeating field)
|
376
|
-
#
|
377
|
-
# * *global* is +true+ is this is a global field, *false* otherwise
|
378
|
-
#
|
379
|
-
# Note: Field types match FileMaker's own values, but the terminology differs. The +result+ attribute
|
380
|
-
# tells you the data type of the field, regardless of whether it is a calculation, summary, or normal
|
381
|
-
# field. So a calculation field whose result type is _timestamp_ would have these attributes:
|
382
|
-
#
|
383
|
-
# * result: timestamp
|
384
|
-
# * type: calculation
|
385
|
-
#
|
386
|
-
# * *control& is a FieldControl object representing the sytle and value list information associated
|
387
|
-
# with this field on the layout.
|
388
|
-
#
|
389
|
-
# Note: Since a field can sometimes appear on a layout more than once, +control+ may be an Array.
|
390
|
-
# If you don't know ahead of time, you'll need to deal with this. One easy way is:
|
391
|
-
#
|
392
|
-
# controls = [myField.control].flatten
|
393
|
-
# controls.each {|control|
|
394
|
-
# # do something with the control here
|
395
|
-
# }
|
396
|
-
#
|
397
|
-
# The code above makes sure the control is always an array. Typically, though, you'll know up front
|
398
|
-
# if the control is an array or not, and you can code accordingly.
|
399
|
-
|
400
|
-
class Field
|
401
|
-
|
402
|
-
# Initializes a field object. You'll never need to do this. Instead, get your Field objects from
|
403
|
-
# ResultSet::fields
|
404
|
-
def initialize(result_set, field)
|
405
|
-
@result_set = result_set
|
406
|
-
@name = field['name']
|
407
|
-
@result = field['result']
|
408
|
-
@type = field['type']
|
409
|
-
@max_repeats = field['max-repeats']
|
410
|
-
@global = field['global']
|
411
|
-
|
412
|
-
@loaded = false
|
413
|
-
end
|
414
|
-
|
415
|
-
attr_reader :name, :result, :type, :max_repeats, :global
|
416
|
-
|
417
|
-
def control
|
418
|
-
@result_set.layout.field_controls[@name]
|
419
|
-
end
|
420
|
-
|
421
|
-
# Coerces the text value from an +fmresultset+ document into proper Ruby types based on the
|
422
|
-
# type of the field. You'll never need to do this: Rfm does it automatically for you when you
|
423
|
-
# access field data through the Record object.
|
424
|
-
def coerce(value)
|
425
|
-
return nil if (value == nil || value == '') && @result != "text"
|
426
|
-
case @result
|
427
|
-
when "text"
|
428
|
-
return value
|
429
|
-
when "number"
|
430
|
-
return BigDecimal.new(value)
|
431
|
-
when "date"
|
432
|
-
return Date.strptime(value, @result_set.date_format)
|
433
|
-
when "time"
|
434
|
-
return DateTime.strptime("1/1/-4712 " + value, "%m/%d/%Y #{@result_set.time_format}")
|
435
|
-
when "timestamp"
|
436
|
-
return DateTime.strptime(value, @result_set.timestamp_format)
|
437
|
-
when "container"
|
438
|
-
return URI.parse("#{@result_set.server.scheme}://#{@result_set.server.host_name}:#{@result_set.server.port}#{value}")
|
439
|
-
else
|
440
|
-
return nil
|
441
|
-
end
|
442
|
-
end
|
443
|
-
end
|
444
|
-
|
445
|
-
end
|
446
|
-
end
|
data/lib/rfm/utility.rb
DELETED
data/test/errors_test.rb
DELETED
@@ -1,53 +0,0 @@
|
|
1
|
-
require 'test/unit'
|
2
|
-
require 'rubygems'
|
3
|
-
require 'rfm'
|
4
|
-
|
5
|
-
# Test cases for testing the FileMakerError classes
|
6
|
-
#
|
7
|
-
# Author:: Mufaddal Khumri
|
8
|
-
# Copyright:: Copyright (c) 2007 Six Fried Rice, LLC and Mufaddal Khumri
|
9
|
-
# License:: See MIT-LICENSE for details
|
10
|
-
class TC_TestErrors < Test::Unit::TestCase
|
11
|
-
|
12
|
-
def test_default_message_system_errors
|
13
|
-
begin
|
14
|
-
raise Rfm::Error::FileMakerError.getError(0)
|
15
|
-
rescue Rfm::Error::SystemError => ex
|
16
|
-
assert_equal(ex.message, 'SystemError occurred. (FileMaker Error #0)')
|
17
|
-
assert_equal(ex.code, 0)
|
18
|
-
end
|
19
|
-
end
|
20
|
-
|
21
|
-
def test_scriptmissing_errors
|
22
|
-
begin
|
23
|
-
raise Rfm::Error::FileMakerError.getError(104, 'ScriptMissingError occurred.')
|
24
|
-
rescue Rfm::Error::MissingError => ex
|
25
|
-
assert_equal(ex.code, 104)
|
26
|
-
end
|
27
|
-
end
|
28
|
-
|
29
|
-
def test_rangevalidation_errors
|
30
|
-
begin
|
31
|
-
raise Rfm::Error::FileMakerError.getError(503, 'RangeValidationError occurred.')
|
32
|
-
rescue Rfm::Error::ValidationError => ex
|
33
|
-
assert_equal(ex.code, 503)
|
34
|
-
end
|
35
|
-
end
|
36
|
-
|
37
|
-
def test_one_unknown_errors
|
38
|
-
begin
|
39
|
-
raise Rfm::Error::FileMakerError.getError(-1, 'UnknownError occurred.')
|
40
|
-
rescue Rfm::Error::UnknownError => ex
|
41
|
-
assert_equal(ex.code, -1)
|
42
|
-
end
|
43
|
-
end
|
44
|
-
|
45
|
-
def test_two_unknown_errors
|
46
|
-
begin
|
47
|
-
raise Rfm::Error::FileMakerError.getError(99999, 'UnknownError occurred.')
|
48
|
-
rescue Rfm::Error::UnknownError => ex
|
49
|
-
assert_equal(ex.code, 99999)
|
50
|
-
end
|
51
|
-
end
|
52
|
-
|
53
|
-
end
|