4 Replies Latest reply on Apr 24, 2009 9:50 AM by philmodjunk

    OnRecordLoad can trigger unexpected results

    philmodjunk

      Title

      OnRecordLoad can trigger unexpected results

      Post

      This is not a complaint, nor is it a request for a new feature. Instead it is a cautionary tale that I am posting to this site to help other developers avoid falling into the same trap and to provide a work around for dealing with this situation.

       

      I needed a script to do some housekeeping on the current record whenever the user used a specific layout to view/edit a record. Filemaker 10's new script trigger features seemed made to order for this.

       

      So I created my script, entered layout mode and set the "OnRecordLoad" trigger for the layout. Then I tested my script by navigating to the layout. The script ran and ran and ran until I interrupted the script. I examined my script. There was a loop in the script, but the exit loop statement's logic was clearly correct. I couldn't see why the script never halted.

       

      Fortunately, I am an FMP 10 adv user, so I enabled the debugger and data viewer and stepped through the script one step at a time. Everything seemed to work correctly until...

       

      ...I spotted the problem. In my script I switched to a different layout in order to process some related records and then switched back to my original layout. Switching back to the original layout triggers the OnRecordLoad script I had created to start performing all over again.

       

      You may not realize this, but Filemaker scripts support recursive execution. That's programmer terminology for scripts that call themselves either directly or indirectly. Consider the following script named "Infinite Loop":

       

      Set Field [Table::fieldA, Table::fieldA + 1]

      Perform Script [Infinite Loop]

       

      Even though there are no loop/end loop instructions, this script will add one to fieldA without stopping until you interrupt execution by pressing the appropriate key. You can halt your loop by adding steps that prevent the Perform Script step from making any more calls to perform the script:

       

      Set Field [Table::fieldA, Table::fieldA + 1]

      If [table::fieldA > 5]

          Exit Script []

      End If

      Perform Script [Infinite Loop]

       

      The new tricky "Gotcha" to guard against with Script Triggers is now "Go To Layout" can act like a recursive Perform Script step to trigger additional calls of the same script.

       

      This left me with a problem. Either I had to figure out a way for my script to do its job without changing layouts or I had to find a way to change layouts without getting trapped in this infinite recursion.

       

      The above script example gave me the idea in how to modify my script and avoid the infinite loop. I added the following code to the beginning of my script:

       

      If [$$RecordLoadCalled = "True" /* Avoid endless recursion */]

          Exit Script []

      Else

           Set Variable [$$RecordLoadCalled, "True"]

      End If

       

      Then I added

       

      Set Variable [$$RecordLoadCalled, ""]

       

      to the end of my script and at any other points where I used Exit Script.

       

      Now my script works.

        • 1. Re: OnRecordLoad can trigger unexpected results
          davidhead
            

          PhilModJunk wrote:

          ...So I created my script, entered layout mode and set the "OnRecordLoad" trigger for the layout. Then I tested my script by navigating to the layout. The script ran and ran and ran until I interrupted the script...

           

          ...I spotted the problem. In my script I switched to a different layout in order to process some related records and then switched back to my original layout. Switching back to the original layout triggers the OnRecordLoad script I had created to start performing all over again.


          Hi Phil
          Good post. This is another example of how you can potentially hang yourself with script triggers. FileMaker gave us a little rope there! I think in time there will be some best practice that comes out of this but it is a bit too early yet.
          Another possible solution to your problem - what about processing those related records in a new window? You can GTRR with a new window and then close it. This will no re-trigger the OnRecordLoad script for the original record. 
          As far as best practice goes, we must understand that OnRecordLoad triggers EVERY time a record loads. Seems a bit trite to say that but it means that we have to think more carefully about ALL the times that a record loads. Because we have not had to consider this in the past, we tend not to 'see' when a record loads and then the implications that might have. Try triggering a script that opens a new window OnRecordLoad or OnLayoutLoad and see what happens. ;-)
          Anyway, it is a good cautionary tale. Thanks for sharing. 

           


          • 2. Re: OnRecordLoad can trigger unexpected results
            philmodjunk
              

            Thanks for contributing David,

             

            Your response is why I copied this post over from the feed back forum to here.

             

            "Another possible solution to your problem - what about processing those related records in a new window? You can GTRR with a new window and then close it. This will no re-trigger the OnRecordLoad script for the original record."

             

            That sound's like a good idea for many situations. In my case, my approach seems a simpler way to do that especially since using GTRR (Go to related record), often requires some extra code in order to correctly handle the case when there are no matching records to process.

            • 3. Re: OnRecordLoad can trigger unexpected results
              davidhead
                

              PhilModJunk wrote:

              ... my approach seems a simpler way to do that especially since using GTRR (Go to related record), often requires some extra code in order to correctly handle the case when there are no matching records to process.


              But your method also requires 'extra code' in two places, and relies the correct and consistent management of an evil global variable ;) I would suggest that it requires some commenting to remember why it is there.

               


              • 4. Re: OnRecordLoad can trigger unexpected results
                philmodjunk
                  

                uLearnIT wrote:
                But your method also requires 'extra code' in two places, and relies the correct and consistent management of an evil global variable ;) I would suggest that it requires some commenting to remember why it is there.

                 

                Good point again. If you check my original post, you'll find I put a comment into the If expression for exactly that reason. Adding a comment next to the other code is a very good idea.

                 

                Have you tried the new window script step on a windows system? I find my "windows" windows resize in unwelcome ways when I use the new window script step. I can minimize the effect but can't eliminate it. If I understand the posts in the "report a bug forum" correctly, this is a known issue.

                 

                I like the "evil global variable" terminology. This is the only situation, so far, where I've chosen to use a global variable instead of passing a parameter or using a global field (what used to be the only way to do this kind of thing back in the old days!). With global fields, at least you can list them in a table with a comment to document what it's being used for.