Best way to check FileMaker “Context”?

What is the best way to check FileMaker “Context”?

In FileMaker, Context is determined by the "Layout" > "Table Occurrence" > "Source Table" that you are “on”.

When scripting, there is more than one way to check “Context”…

This first image uses a string returned from the Get ( LayoutTableName ) function.

  • Pro?: Might be faster?
  • Con: Breaks if you rename the Table Occurrence that Get ( LayoutTableName ) returns
    image

The second uses a reference.

  • Pro: Does NOT break if you rename the Table Occurrence that Get ( LayoutTableName ) returns
  • Con?: Might (or might not) be slower (if you have many 'Else If' branches)?
    image

Thoughts?

GetFieldName( field) will return the Table::Field name, so you could do something like this:

if [ Get(LayoutTableName) = LeftValues ( Substitute ( GetFieldName ( Location ); "::" ; "¶") ;1 ) ]

this will tell you which Table you are on, and is resistent to fields or tables being renamed.

But I think I like your IsValid() solution better.

I use a custom function named "cf CorrectContext." It has one parameter, getFieldNameX.

Internally it contains this code:

/*
Given a fully qualified field name, return true if the field matches the current layout table name 
*/

Let (
	parts = Substitute ( getFieldNamex ; "::" ; ¶ ) ; 
	GetValue ( parts ; 1 ) = Get(LayoutTableName)
)

This allows me to use the function in script steps and other calculations:

If [   cf correctContext ( GetFieldName ( field-ref ) ) ] 
 // code here
End if
4 Likes

I use the same method as @xochi exclusively in my solutions. I see an issue with the IsValid approach: It could return true whether it is the context or a record of the table is reachable by the context.

1 Like

Similar to @Malcolm, I use a CF.

Like Malcolm's CF, it is based on comparing Get( LayoutTableName ) with the TableOccurrence name parsed from the result of GetFieldName.

Function is named something like: CurrentContextMatches( fieldRef )

It's a small convenience, but one that I appreciate having a lot, mostly for readability.

5 Likes

@steve_ssh, I used the parameter name getFieldNameX to remind me which function to pass. In the early days it was also handy because it meant less typing. Nowadays, type-ahead will recognise "gfn", which I find easiest.

If you go down that road, this might be better...

Get ( LayoutTableName ) = GetValue ( Substitute ( GetFieldName ( TO::FN ) ; "::" ; "¶" ) ; 1 )

...as LeftValues produces a trailing return.

See below for IsValid() comment.

Thanks.

Good point. I use Anchor-Buoy where, as far as I can tell, that should not come up. That said, an approach that works on all types of Relationship Graphs offers advantages.

Below is a riff on your approach....

This would be more readable if I used the Let function. I wonder if there is a performance difference?

1 Like

Comments on these two methods

method one:
Using a hard-coded string in the comparison will come back to bite you. Use a dynamic method to obtain the layout table name.
As for speed, knowing that your code will not break is better.

method two:
IsValid() will not tell you that you are on the correct layout. It will only tell you that you are on a layout that is within the same Table Occurrence Group as the target field being tested.

IsValid() will return true for a field reference whenever that field can be found through the chain of relationships. If you are on a layout based on "Invoices" and you ask test Invoice_Items::id using IsValid() it will return true.

The custom function that I use checks the name of a referenced field against the current layout table name. The object names are obtained dynamically, the field names can change, the layout table occurrence names can change, and it keeps working.

When I think about performance I will address efficiency, simplicity, and stability. If I can obtain a speed bump by addressing those three criteria then I'm happy. If I have a solution that is simple, stable and reasonably efficient, then I'm not going to look for tweaks unless it has become a bottleneck that is causing problems.

However, a custom function is the sort of thing that could be optimised ( because you don't have to interact with the internals) and your variation may use less overhead than mine. In this case, a single sentence comment would be enough to explain the workings of your variation of the function to any future developer.

For anyone who is not familiar with the concept of context and its representations beyond the table occurrence, there is a post here about it: Context

3 Likes

Lines 16 & 19 are more portable

Line 22 is more readable.

Which of the 4 do you like?

I'm sure my answer is predictable, but I like line 22 the best.

2 Likes

Line 16 is perfectly readable to me. Then again, I use that construct all the time. I suggest comments are missing in all cases. They can reduce the shortcomings of readability and add intent to what the code is trying to do. They allow you to understand what a line of code is suppose to do when you see something like "Missing XYZ" (custom function, in this case). Also useful to troubleshoot code portability issues.

line 22 wins for clarity. It's an unambiguous description.

If portability must win, I often use a short comment on the first line of the calc to provide a description of purpose.

A riff on the script step level comment that you are using is that you might make the comment the same as a custom function name. Then you could easily refactor to a CF after adding the custom function (or renaming an existing custom function that does the same thing).

On the topic of script comments…in recent times, I have been exploring how many comments I can avoid and still maintain readability.

In deciding what to comment and where, it is worth considering that for any given scripting pattern, you could comment at one of the following levels

  • In the code itself // sufficiently well named code objects
  • Script step // as you have done
  • Block // in this example there is a repeating Else If…perhaps a comment only on the first, or at the top of the block?
  • Script // sometime I will even add function signatures at the top of the script…not for myself of course…for my friends :wink:
  • File // for completeness
  • System // for completeness
  • Separate coding standard document for an organization // very DRY.
  • Community // get all FileMaker developers worldwide to agree on a standard…just kidding

Lots of different coding styles to chose from!

Always add ‘sort by’ or ‘find by’ comment if a stored find, above the script step to allow easy reading through the script.

Are we going off topic? Maybe a good subject for a new post?

3 Likes