Class: Rfm::Layout
Overview
The Layout object represents a single FileMaker Pro layout. You use it to interact with records in FileMaker. All access to FileMaker data is done through a layout, and this layout determines which table you actually hit (since every layout is explicitly associated with a particular table – see FileMakers Layout->Layout Setup dialog box). You never specify table information directly in RFM.
Also, the layout determines which fields will be returned. If a layout contains only three fields from a large table, only those three fields are returned. If a layout includes related fields from another table, they are returned as well. And if the layout includes portals, all data in the portals is returned (see Record::portal for details).
As such, you can significantly improve performance by limiting what you put on the layout.
Using Layouts
The Layout object is where you get most of your work done. It includes methods for all FileMaker actions:
-
Layout::all
-
Layout::any
-
Layout::find
-
Layout::edit
-
Layout::create
-
Layout::delete
Running Scripts
In FileMaker, execution of a script must accompany another action. For example, to run a script called _Remove Duplicates_ with a found set that includes everybody named Bill, do this:
myLayout.find({"First Name" => "Bill"}, :post_script => "Remove Duplicates")
Controlling When the Script Runs
When you perform an action in FileMaker, it always executes in this order:
-
Perform any find
-
Sort the records
-
Return the results
You can control when in the process the script runs. Each of these options is available:
-
post_script tells FileMaker to run the script after finding and sorting
-
pre_find_script tells FileMaker to run the script before finding
-
pre_sort_script tells FileMaker to run the script before sorting, but after finding
Passing Parameters to a Script
If you want to pass a parameter to the script, use the options above, but supply an array value instead of a single string. For example:
myLayout.find({"First Name" => "Bill"}, :post_script => ["Remove Duplicates", 10])
This sample runs the script called “Remove Duplicates” and passes it the value 10
as its script parameter.
Common Options
Most of the methods on the Layout object accept an optional hash of options
to manipulate the action. For example, when you perform a find, you will typiclaly get back all matching records. If you want to limit the number of records returned, you can do this:
myLayout.find({"First Name" => "Bill"}, :max_records => 100)
The :max_records
option tells FileMaker to limit the number of records returned.
This is the complete list of available options:
-
max_records tells FileMaker how many records to return
-
skip_records tells FileMaker how many records in the found set to skip, before returning results; this is typically combined with
max_records
to “page” through records -
sort_field tells FileMaker to sort the records by the specified field
-
sort_order can be
descend
orascend
and determines the order of the sort whensort_field
is specified -
post_script tells FileMaker to perform a script after carrying out the action; you can pass the script name, or a two-element array, with the script name first, then the script parameter
-
pre_find_script is like
post_script
except the script runs before any find is performed -
pre_sort_script is like
pre_find_script
except the script runs after any find and before any sort -
response_layout tells FileMaker to switch layouts before producing the response; this is useful when you need a field on a layout to perform a find, edit, or create, but you want to improve performance by not including the field in the result
-
logical_operator can be
and
oror
and tells FileMaker how to process multiple fields in a find request -
modification_id lets you pass in the modification id from a Record object with the request; when you do, the action will fail if the record was modified in FileMaker after it was retrieved by RFM but before the action was run
Attributes
The Layout object has a few useful attributes:
-
name
is the name of the layout -
field_controls
is a hash of FieldControl objects, with the field names as keys. FieldControl’s tell you about the field on the layout: how is it formatted and what value list is assigned
Note: It is possible to put the same field on a layout more than once. When this is the case, the value in field_controls
for that field is an array with one element representing each instance of the field.
-
value_lists
is a hash of arrays. The keys are value list names, and the values in the hash are arrays containing the actual value list items.value_lists
will include every value list that is attached to any field on the layout
Constant Summary
Constants included from Config
Config::CONFIG_DONT_STORE, Config::CONFIG_KEYS
Instance Attribute Summary collapse
-
#field_mapping ⇒ Object
readonly
Returns the value of attribute field_mapping.
-
#model ⇒ Object
, :parent_layout, :subs.
-
#resultset_meta ⇒ Object
Metadata from Resultset ###.
Instance Method Summary collapse
-
#all(options = {}) ⇒ Object
Returns a ResultSet object containing _every record_ in the table associated with this layout.
-
#any(options = {}) ⇒ Object
Returns a ResultSet containing a single random record from the table associated with this layout.
- #capture_resultset_meta(resultset) ⇒ Object
- #config(*args) ⇒ Object
-
#count(find_criteria, options = {}) ⇒ Object
Get the foundset_count only given criteria & options.
-
#create(values, options = {}) ⇒ Object
Creates a new record in the table associated with this layout.
-
#database ⇒ Object
alias_method :database, :db # This fails if db object hasn’t been set yet with meta_attr_accessor.
- #db ⇒ Object
- #db_orig ⇒ Object
-
#delete(recid, options = {}) ⇒ Object
Deletes the record with the specified internal recid.
-
#edit(recid, values, options = {}) ⇒ Object
Updates the contents of the record whose internal
recid
is specified. - #field_keys ⇒ Object
- #field_names ⇒ Object
-
#find(find_criteria, options = {}) ⇒ Object
If you pass anything other than a hash or an array as the first parameter, it is converted to a string and assumed to be FileMaker’s internal id for a record (the recid).
-
#initialize(*args) ⇒ Layout
constructor
Initialize a layout object.
- #load_field_mapping(mapping = {}) ⇒ Object
-
#meta ⇒ Object
Metadata from Layout ###.
-
#modelize ⇒ Object
Creates new class with layout name.
- #models ⇒ Object
- #name ⇒ Object
- #portal_names ⇒ Object
-
#query(query_hash, options = {}) ⇒ Object
Access to raw -findquery command.
-
#total_count ⇒ Object
Should always refresh.
-
#view(options = {}) ⇒ Object
Retrieves metadata only, with an empty resultset.
Methods included from Config
#config_clear, #get_config, #log, #state
Constructor Details
#initialize(*args) ⇒ Layout
Initialize a layout object. You never really need to do this. Instead, just do this:
myServer = Rfm::Server.new(...)
myDatabase = myServer["Customers"]
myLayout = myDatabase["Details"]
This sample code gets a layout object representing the Details layout in the Customers database on the FileMaker server.
In case it isn’t obvious, this is more easily expressed this way:
myServer = Rfm::Server.new(...)
myLayout = myServer["Customers"]["Details"]
173 174 175 176 177 178 179 180 |
# File 'lib/rfm/layout.rb', line 173 def initialize(*args) #name, db_obj # self.subs ||= [] config(*args) raise Rfm::Error::RfmError.new(0, "New instance of Rfm::Layout has no name. Attempted name '#{state[:layout]}'.") if state[:layout].to_s == '' @loaded = false @meta = Metadata::LayoutMeta.new(self) self end |
Instance Attribute Details
#field_mapping ⇒ Object (readonly)
Returns the value of attribute field_mapping.
126 127 128 |
# File 'lib/rfm/layout.rb', line 126 def field_mapping @field_mapping end |
#model ⇒ Object
, :parent_layout, :subs
131 132 133 |
# File 'lib/rfm/layout.rb', line 131 def model @model end |
#resultset_meta ⇒ Object
Metadata from Resultset ###
365 366 367 |
# File 'lib/rfm/layout.rb', line 365 def @resultset_meta || view. end |
Instance Method Details
#all(options = {}) ⇒ Object
Returns a ResultSet object containing _every record_ in the table associated with this layout.
196 197 198 |
# File 'lib/rfm/layout.rb', line 196 def all( = {}) get_records('-findall', {}, ) end |
#any(options = {}) ⇒ Object
Returns a ResultSet containing a single random record from the table associated with this layout.
201 202 203 |
# File 'lib/rfm/layout.rb', line 201 def any( = {}) get_records('-findany', {}, ) end |
#capture_resultset_meta(resultset) ⇒ Object
374 375 376 377 |
# File 'lib/rfm/layout.rb', line 374 def (resultset) (@resultset_meta = resultset.clone.replace([])) #unless @resultset_meta @resultset_meta = resultset. end |
#config(*args) ⇒ Object
182 183 184 185 186 187 188 |
# File 'lib/rfm/layout.rb', line 182 def config(*args) super(:capture_strings_with=>[:layout]) super(*args) do |params| (self.name = params[:strings][0]) if params && params[:strings] && params[:strings].any? (self.db = params[:objects][0]) if params && params[:objects] && params[:objects][0] && params[:objects][0].is_a?(Rfm::Database) end end |
#count(find_criteria, options = {}) ⇒ Object
Get the foundset_count only given criteria & options.
287 288 289 |
# File 'lib/rfm/layout.rb', line 287 def count(find_criteria, ={}) find(find_criteria, .merge({:max_records => 0})).foundset_count end |
#create(values, options = {}) ⇒ Object
Creates a new record in the table associated with this layout. Pass field data as a hash in the values
parameter. Returns the newly created record in a RecordSet. You can use the returned record to, ie, discover the values in auto-enter fields (like serial numbers).
For example:
result = myLayout.create({"First Name" => "Jerry", "Last Name" => "Robin"})
id = result[0]["ID"]
The above code adds a new record with first name Jerry and last name Robin. It then puts the value from the ID field (a serial number) into a ruby variable called id
.
264 265 266 |
# File 'lib/rfm/layout.rb', line 264 def create(values, = {}) get_records('-new', values, ) end |
#database ⇒ Object
alias_method :database, :db # This fails if db object hasn’t been set yet with meta_attr_accessor
130 |
# File 'lib/rfm/layout.rb', line 130 def database; db; end |
#db ⇒ Object
191 192 193 |
# File 'lib/rfm/layout.rb', line 191 def db db_orig || (self.db = Rfm::Database.new(state[:database], state[:account_name], state[:password], self)) end |
#db_orig ⇒ Object
190 |
# File 'lib/rfm/layout.rb', line 190 alias_method :db_orig, :db |
#delete(recid, options = {}) ⇒ Object
Deletes the record with the specified internal recid. Returns a ResultSet with the deleted record.
For example:
recid = myLayout.find({"First Name" => "Bill"})[0].record_id
myLayout.delete(recid)
The above code finds every record with Bill in the First Name field, then deletes the first one.
276 277 278 279 |
# File 'lib/rfm/layout.rb', line 276 def delete(recid, = {}) get_records('-delete', {'-recid' => recid}, ) return nil end |
#edit(recid, values, options = {}) ⇒ Object
Updates the contents of the record whose internal recid
is specified. Send in a hash of new data in the values
parameter. Returns a RecordSet containing the modified record. For example:
recid = myLayout.find({"First Name" => "Bill"})[0].record_id
myLayout.edit(recid, {"First Name" => "Steve"})
The above code would find the first record with Bill in the First Name field and change the first name to Steve.
248 249 250 251 |
# File 'lib/rfm/layout.rb', line 248 def edit(recid, values, = {}) get_records('-edit', {'-recid' => recid}.merge(values), ) #get_records('-edit', {'-recid' => recid}.merge(expand_repeats(values)), options) # attempt to set repeating fields. end |
#field_keys ⇒ Object
352 353 354 355 356 357 358 |
# File 'lib/rfm/layout.rb', line 352 def field_keys case when @loaded; @meta.field_keys when @resultset_meta; @resultset_meta.field_keys else .field_keys end end |
#field_names ⇒ Object
344 345 346 347 348 349 350 |
# File 'lib/rfm/layout.rb', line 344 def field_names case when @loaded; .field_names when @resultset_meta; .field_names else .field_names end end |
#find(find_criteria, options = {}) ⇒ Object
If you pass anything other than a hash or an array as the first parameter, it is converted to a string and assumed to be FileMaker’s internal id for a record (the recid).
myLayout.find 54321
229 230 231 232 233 |
# File 'lib/rfm/layout.rb', line 229 def find(find_criteria, = {}) #puts "layout.find-#{self.object_id}" .merge!({:field_mapping => field_mapping.invert}) if field_mapping get_records(*Rfm::CompoundQuery.new(find_criteria, )) end |
#load_field_mapping(mapping = {}) ⇒ Object
411 412 413 414 415 416 417 |
# File 'lib/rfm/layout.rb', line 411 def load_field_mapping(mapping={}) mapping = (mapping || {}).to_cih def mapping.invert super.to_cih end mapping end |
#meta ⇒ Object
Metadata from Layout ###
340 341 342 |
# File 'lib/rfm/layout.rb', line 340 def @loaded ? @meta : load_layout end |
#modelize ⇒ Object
Creates new class with layout name.
420 421 422 423 424 425 426 427 428 429 430 431 432 433 434 |
# File 'lib/rfm/layout.rb', line 420 def modelize @model ||= ( model_name = name.to_s.gsub(/\W|_/, ' ').title_case.gsub(/\s/,'') #model_class = eval("::" + model_name + "= Class.new(Rfm::Base)") model_class = Rfm.const_defined?(model_name) ? Rfm.const_get(model_name) : Rfm.const_set(model_name, Class.new(Rfm::Base)) model_class.class_exec(self) do |layout_obj| @layout = layout_obj end model_class.config :parent=>'@layout' model_class ) # rescue StandardError, SyntaxError # puts "Error in layout#modelize: #{$!}" # nil end |
#models ⇒ Object
436 437 438 439 |
# File 'lib/rfm/layout.rb', line 436 def models #subs.collect{|s| s.model} [@model] end |
#name ⇒ Object
333 |
# File 'lib/rfm/layout.rb', line 333 def name; state[:layout].to_s; end |
#portal_names ⇒ Object
379 380 381 |
# File 'lib/rfm/layout.rb', line 379 def portal_names return 'UNDER-CONTSTRUCTION' end |
#query(query_hash, options = {}) ⇒ Object
Access to raw -findquery command.
236 237 238 |
# File 'lib/rfm/layout.rb', line 236 def query(query_hash, = {}) get_records('-findquery', query_hash, ) end |
#total_count ⇒ Object
Should always refresh
370 371 372 |
# File 'lib/rfm/layout.rb', line 370 def total_count view.total_count end |
#view(options = {}) ⇒ Object
Retrieves metadata only, with an empty resultset.
282 283 284 |
# File 'lib/rfm/layout.rb', line 282 def view( = {}) get_records('-view', {}, ) end |