I’ve written a new CLASS - as declared in attached .INC/.CLW files:
jmExtNAME.CLW (1.2 KB) jmExtNAME.INC (725 Bytes)
Why, when I attempt to instantiate this Class, like this …
… do I get this error message: ??
TiA - John M
I’ve written a new CLASS - as declared in attached .INC/.CLW files:
jmExtNAME.CLW (1.2 KB) jmExtNAME.INC (725 Bytes)
Why, when I attempt to instantiate this Class, like this …
… do I get this error message: ??
TiA - John M
Did you remember the INCLUDE(‘jmExtName.inc’)
Note: make certain you have that include line at a global (or module) scope
but it CANNOT be inside of a procedure
PROGRAM
MAP
END
! add code to declare SomeFile
INCLUDE('jmExtName.inc'),ONCE
jmGet jm::GetExtName
CODE
jmGet( SomeFile )
Once you get this working then we can circle back to disuss the class itself.
Many thanks for your quick response, Mark.
Yes, I believe I did. See attached INC/CLW files (above) … Snippet here;
Regards, John M
Look at my example closer
you need the INCLUDE in your PROGRAM
as well as in the jmExtName.clw
@MarkGoldberg If it is setup as an ABC compliant class it automatically gets added to the APP global module.
@JohnM What folder is your class files saved in? It has to be one of the automatically scanned Libsrc folder.
\LibSrc\Win and \Accessory\Libsrc\Win are the two default folders.
Ahh - Doh !
… I was assuming that was being handled by virtue of it being ABC compliant.
Thank you (again), Mark.
Yes, it is, Rick ;
…
That’s what I was assuming too - - Doesn’t seem to be the case, tho (?)
John
I wonder if the INCLUDE is handled via a template
I recall Russ had a template skeleton for abc compliant classes
IIRC this is needed if you wish to have embed points into the class
Do you have a “data” dll or is this a single APP solution?
If you have a data dll that exports all the classes and tables from your dictionary, the ABC compliant classes are automatically included.
If I know what you’re talking about :), that is a template to generate a instance of the class into a procedure and include Embed points for each method’s data and code sections. Similar to what an ABC Browse class looks like in a procedure.
I thought that was only with the global DLL, or the EXE without EXTERNAL.
Thanks for all the input, @MarkGoldberg, @Rick_UpperPark and @jslarve … I’m back again (I’m in a different time-zone here; Australia being many hours ahead of the US of A)
Yes, that’s it - - and because it “simply works” I assumed it was part of the magic of an ABC compliant class … but, actually, it’s template-implemented.
To confirm this, I dug into the example of Mike Hanson’s TabPopup template (from a very early version of the SuperStuff template set) … and I found this;
…
… which adds an INCLUDE statement for each PROCEDURE containing a Sheet control
… - Revealed only via Module mode !
ABC compliance is playing a part - - as that must be how the reference to ‘MH::TapPopup’ is able to be translated to a reference to the MHABTABP.INC container for the Class declaration
John M
Yep, all sorted, Mark … and now ready to “circle back”.
Regards, John M
Hi John
just an aside, I think that these days as you can use “ONCE” on your include:
INCLUDE('jmExtName.inc'),ONCE
it is no longer necessary to have the boiler plate omit:
OMIT('_EndOfInclude_',_jmExtName_) ! Omit if already compiled
_jmExtName_ EQUATE(1)
although I guess it doesn’t do much harm… just unnecessary
cheers for now
Geoff R
Thanks, Geoff - I wasn’t aware of that refinement.
Note: There was a small bug in the .INC/CLW files I posted at top of this thread (with big implications; I had the wrong INC file referenced from within the CLW !!). New copies posted here;
… jmExtNAME.CLW (1.2 KB) jmExtNAME.INC (1.1 KB)
… with an accompanying template for implementation … jmExtName.TPW (1.7 KB)
John
Some new enhancements;
Filename (1st parameter) can now be OMITTED after first usage … Retained via a STATIC variable.
jmExtNAME.CLW (1.6 KB) jmExtNAME.INC (732 Bytes)
Usage examples included as comments, via the implementation template.
jmExtName.TPW (2.8 KB)
Observations and/or suggestions welcomed …
John
I Agree about using ,ONCE instead of relying the OMIT and EQUATE(1)
especially if you’re using the SV.IDE, IIRC using ONCE results in faster code completion
For other feed back.
IMO Ideally the name of the file for the .inc/.clw should match your class name
that said, ‘:’ isn’t valid in a filename
The class name and methods talk about ExternalName
but the method is returning the result of WHO()
Do you want to change the result of the method to use
pFile{PROP:Name, N} where N= WHERE( TheGroup, pField )
or do you want to rename the class and methods ?
Have you considered gettting rid of ExternalName property?
While it is set, it’s never read, and it’s private
While it is use as a return value,
you could instead use a variable inside of each of the methods
in your first method .ExtName(FILE pFile)
the call to SELF.ExtName(pFile, SELF.ExternalName) looks wrong to me
the 2nd parameter should be a field in a file buffer, not SELF.ExternalName
note: I haven’t compiled, much less tested any of this
the use of ,STATIC on the method variable RecordStructureRef
allows you to omit the pFile on additional calls
yes, that will work – but it’s not thread safe
if you really want to make calls like
oGetExtName.ExtName( myFile, myFile.ID )
oGetExtName.ExtName( , myFile.Description)
then I would move the &GROUP (and/or &FILE) to class properties
in truth, i’d probably split some logic out.
yada.Current( MyFile ) ! set SELF.TheGroup &= pFile{PROP:Record}
and / or
yada.Current( MyFile.Record ) ! set the SELF.Group &= pGroup
TheName = yada.GetExtName( MyFile.ID )
Many thanks for your detailed critique, Mark … I appreciate the time/effort you’ve made
As for any new class, I guess, this has been an iterative process - the latest (renamed) version follows;
jmSQLName.CLW (2.4 KB) jmSQLName.INC (867 Bytes) jmSQLName.TPW (3.3 KB)
Some background;
I’ve always addressed SQL tables via Clarion’s View paradigm - with the “key” to successfully doing so being specification of the SQL server-side labelling of table & column names via the Clarion dct’s External Name attribute = Prop:Name.
All the same, I’ve come across some occasional cases where it’s been necessary to cast some “raw” SQL code (such as for GROUP BY & HAVING statements, specified via the SQL Advanced tab) - - BUT, doing so with server-side syntax within STRING variables means that it’s hidden from the Clarion compiler … and I’d rather have the compiler validate ALL my code, rather than deal with strange bugs after the fact.
So, this class enables me to build compiler-validated SQL statements, using Clarion syntax.
For example, this:
SELECT AppUsage.AppUsageRID,AppUsage.AppUserRID,AppUsage.Date,AppUsage.Time FROM AppUsage WHERE AppUsage.AppUsageRID = 99 ORDER BY AppUsage.AppUserRID
Done - Thanks to Geoff @vitesse for this one; I was naively copying other class definitions.
I use Mike Hanson & Vince Sorensen’s classes & templates as guide/inspiration for my own dabbling; I’m copying their conventions in this case. All the same, I concur with your point on consistency - and I’ve renamed the methods and INC/CLWs accordingly.
WHO returns the field name … that’s what I intend the class to do. The WHERE provides a reference to the specific field. Since I need the WHERE, it just seemed consistent to me to use WHO (instead of PROP:Name) … I “borrowed” the concept from ViewManager.GetFieldName - - ABFILE.CLW
Point taken. Fixed.
Yes, I admit that is a bit of a fudge ! … but I needed (any old) variable to pass as the 2nd parameter - and SELF.ExternalName was handy
Oops ! - Whilst I had not considered the complications/implications of thread safety, I originally tried declaring the &GROUP reference variable as a class property - but the complier did not like the STATIC attribute in there, which is why I moved it to the method.
Mmm - pondering (I’m writing this in real-time !);
Why would thread safety be an issue here ? - - The Class is derived/declared within a Procedure - so, presumably(?), the scope of all its variables is limited to the specific Procedure - and separate from any other Procedures that may have their own instance. What am I not appreciating ?
Ahhh !! … The penny drops (with regard to the STATIC issue); I don’t need the STATIC attribute if the &GROUP reference variable is declared at the class level - 'cos it’s then in-scope for all locally instantiated class methods. Oh, der !
I’m still not clear/sure about the thread safety issue - Is it OK now (and why was it not before) ? - and, do I need a THREAD attribute on the class (and if so, why) ??
Thanks once again for your help with this, Mark - it’s now a much better design, as a result.
I’ve included all fixes/enhancements in the files attached above.
Regards, John M
While Bruce might suggest otherwise, I am firmly of the belief to avoid the SQL Advanced tab, simply create this type of view on the backend, and define the view in the Dct as a table. In addition to having the compiler validate the code, this approach is not Clarion-centric, allows one to later optimize sub-queries on the backend without changing your program, and can permit multi-table updates using an trigger on the view.
GetSQLName.clw (2.6 KB) GetSQLName.inc (1.1 KB)
Please look carefully at the attached files.
Bug found: replace xWho with pWho in the .StripPrefix method