Page 1 of 1

Using stack files as templates

Posted: Thu Dec 28, 2017 5:34 am
by jmk_phd
I’m so sorry to bother everyone again, but I’m stymied by a problem involving the use of a free-standing stack file (located in the app folder) intended as a template for the datafiles created by the app.

Upon first launch the app creates a subfolder in the user’s Documents folder. When the user chooses to create a new datafile, this “template” stack file is copied to the Documents folder, renamed, then populated with client-entered data and saved there.

As messy as this sounds, it works flawlessly in the IDE on my Mac and also in the Windows standalone. However, in the Mac standalone, the datafile is created and renamed properly, but does not accept any data (i.e., file size = 0).

From what I’ve read in the forums, my use of revCopyFile in the code might be responsible for this Mac-only problem.

Rather than burden anyone to troubleshoot my actual code, I’d appreciate just being pointed to a source (on this forum or elsewhere) to any reliable code snippets that illustrate a more efficient method of how a stack file in the app folder can be copied to Documents and saved with the user’s new input.

Thanks so much!

jeff k

Re: Using stack files as templates

Posted: Thu Dec 28, 2017 8:00 am
by FourthWorld
It may be simpler to include the template stack as a substack within you're app's stack file, using the clone command to produce a document from it, e.g.:

Code: Select all

on CreateDoc
   put ("s"&the millisecs) into tNuName -- arbitrary reasonably-unique name; could use UUID
   clone invisible stack "MyTemplate"
   set the title of it to "Untitled"
   set the uIsDoc of it to true -- arbitrary flag to distinguish it from non-document stacks
   set the name of it to tNuName
   show stack tNuName
end CreateDoc
That will create a new document in memory for the user. To save:

Code: Select all

on SaveDoc
   put TopDoc() into tDocStackName
   if the filename of stack tDocStackName is empty then -- not saved yet
      ask file "Save document as:"
      if it is empty then exit to top
      set the filename of stack tDocStackName to it
   end if 
   save stack tDocStackName
 end SaveDoc
function TopDoc
   repeat for each line tWd in the windows
     if the uIsDoc of stack tWd is true then
        return tWd
     end if
   end repeat
end TopDoc
Thtat's off the top of my head, so forgive any errors and the lack of error-checking that should be there. But hopefully it'll give you some ideas for using cloned substacks as templates.

One thing to consider, though:

There's a reason most app devs store their data separately from the UI they display to data in. You'll discover this yourself when your app goes to version 2.0: if the data is bound to the UI, you can't update your UI, since older documents will still have their own UI.

If your app lends itself to storing data separately and populating a stack for display and editing only, you'll be able to change the UI without affecting user data files.

I once made a nice app with data bound to the UI. And sure enough, when it came time for v2.0 we had to write a complicated importer to worm its way through old document stacks and pull the data into the new UI. I wished back then someone would have come along and told me about factoring data from UI.... :) It was a lot of extra work, for us and for the users.

Re: Using stack files as templates

Posted: Thu Dec 28, 2017 8:07 am
by FourthWorld
Two things I overlooked in my first reply:
jmk_phd wrote:
Thu Dec 28, 2017 5:34 am
I’m so sorry to bother everyone again...
You're asking questions about learning LiveCode. That's what we're here for. Extra bonus points that they're also good questions. :) No bother at all. On the contrary, for every post you write there's another dozen or so who have the same question but didn't ask it. Since you asked, many others will benefit. Your questions are a public service.
As messy as this sounds, it works flawlessly in the IDE on my Mac and also in the Windows standalone. However, in the Mac standalone, the datafile is created and renamed properly, but does not accept any data (i.e., file size = 0).
That suggests to me you made the same mistake I made in my sample code above: no error-checking.

Tedious as it is, error-checking is about a third of anything we write. It's so easy to discover ways things can go wrong. :)

Here's a few lines to add after the save command above; you can adapt this for nearly anything that involves file I/O:

Code: Select all

   save stack tDocStackName
   if the result is not empty then
      answer "Couldn't save document: "& the result &" ("& sysError() &")"
      exit to top
   end if
In LC error notifications are often provided in "the result" when called immediately after a command. The sysError function gives us more specifics, the exact error number the OS provided to LC when the error occurred.

Re: Using stack files as templates

Posted: Fri Dec 29, 2017 12:05 am
by jmk_phd
Richard –

Thank you for the tips and code snippets. I definitely will give a try including the datafile template as a substack, then using the cloning strategy you’ve described. I can see that this might be much simpler and less error prone than trying to copy a free-standing stack file from the app’s folder to a Documents subfolder.

As regards error-checking, although I’ve been pretty scrupulous in checking for input errors that the user might make, I acknowledge having been rather lax in checking for errors that might be my own fault – usually inserting checks only for troubleshooting when something doesn’t work as expected when the app is run in the IDE. I’ll try to clean up my act in that regard.

It simply came as a rude surprise that a LC app might run just fine from the IDE on my Mac, yet fail when saved as a Mac standalone. I’d feared instead having to grapple with problems with the Windows standalone -- simply because I lack experience with that platform – but that worked fine. Apparently life is full of surprises.

I will report back, hopefully with a successful outcome.

jeff k

P.S. Sorry I've been remiss in not mentioning that I'm using LC Indy 8.1.8 on macOS 10.6.8.

Re: Using stack files as templates

Posted: Sat Dec 30, 2017 5:34 am
by jmk_phd
Thanks again, Richard!

Your suggestion to treat the template as a substack and to employ the clone command is an incredibly simple alternative to the code I employed previously.

So far this has passed the first crucial test: Unlike my previous approach, the Mac standalone using this strategy does in fact save a copy of the template (including newly-inputted information) to disk and does allow for changes to the template fields. (I’ve not yet tested this with a Windows standalone, but at worst I can do a platform-based switch, using for Windows the code that I know already works.)

BTW, the cloned template substack saved to disk remains invisible in my app, just serving to save the user’s input into the main screen. Admittedly a quick-and-dirty substitute for my learning how to master LC’s database features. I’m treating each card in the substack as a record, so I can navigate among these and modify changes to individual fields.

Obviously, I cannot vouch that this bare-bones code will work for everyone who employs this strategy – and (apart from error-checking) please correct me if I’m wrong:

Code: Select all

on mouseup
   -- declare local variables
   local tPathToDataFolder -- path to DataFiles folder in Documents folder
   -- this path was verified/created when the main stack opens
   put the cDataPathFolder of stack "Hermann" into tPathToDataFolder
   local tClientFileName -- name constructed for the client datafile
   -- for now I've just employed an arbitrary filename
   put "Smith, John_17-12-29.hrm10" into tClientFileName
   local tPathToDataFile -- constructed path to the client datafile
   put tPathToDataFolder & tClientFileName into tPathToDataFile
   -- clone the template substack
   clone invisible stack "ClientTemplate" as "NewClient"
   -- save cloned stack as a file in the Documents subfolder
   save stack "NewClient" as tPathToDataFile
   -- try filling in a field in the new clientdata file (here using dummy data)
   put "John Smith" into field "ClientName" of stack tPathToDataFile
   -- then save the modified stack file
   save stack tPathToDataFile
   -- presumably the original substack needs to be removed from memory
   set the destroystack of stack "NewClient" to true
   close stack "NewClient"
   -- henceforth, updates to the client datafile created in the Documents subfolder 
   -- should be saved  each time by calling "save stack tPathToDataFile" 
end mouseup
Thanks for your help. The code may or may not be helpful to other LiveCoders.

jeff k