go to post Eduard Lebedyuk · Feb 4, 2017 I'd like to add some commentary to Angular 1/2 comparison.Angular 1:- easier to hook to cache (can be used by calling the library from a csp and calling services cache rest)That's same as with Angular 2.- flatter learning curve if jquery is already known- being so similar to jquery jQuery has little in common with Angular. Angular (1 or 2) is an MVC framework and jQuery is the utilities library.- not needed for really small projectsYes, for both Angular 1 and 2.- easier to maintain, perhaps, for someone who knows web, html and jqueryHighly debatable. Learning curve for Angular 1 is fairly steep.Angular 2.- does not work in browsers older than IE9Angular 1 also does not work in browsers older than IE9- keeps changing, it is not completely stable yet?It has a stable version for a few months already. Now, with that said, I'd like to recommend Angular 2. The main advantage in my opinion is that many fundamental problems present in Angular 1 were solved in Angular 2. Here's some links elaborating on differences between Angular 1 and 2:Short comparison of differences between Angular 1 and 2 is available here.More detailed comparison is available here.
go to post Eduard Lebedyuk · Feb 2, 2017 That is almost what I started this topic with. I get a compilation error with this code. And fields data_Year and data_Month are not getting created it seems.
go to post Eduard Lebedyuk · Feb 2, 2017 Thank you!I copied your example, but SQL returns results saved on disk, which is expected as the data property is triggered computed Class CS.Persistent Extends %Persistent { Property data As CS.Serial [ SqlComputeCode = {set {*} = ##class(CS.Persistent).dataGetStatic()}, SqlComputed ]; /// data getter method in SQL context ClassMethod dataGetStatic() As %List { quit $lb(2017,1) } /// do ##class(CS.Persistent).test() ClassMethod test() { do ..%KillExtent() do $system.SQL.PurgeForTable($classname()) set obj = ##class(CS.Persistent).%New() set obj.data.Month=-1 set obj.data.Year=0 set sc = obj.%Save() write !,"Save: ",$s($$$ISOK(sc):"OK", 1:$System.Status.GetErrorText(sc)),! zw ^CS.PersistentD do ##class(%SQL.Statement).%ExecDirect(,"select * from "_$classname()).%Display() } } I execute in a terminal: do ##class(CS.Persistent).test() And I receive the following output: Save: OK ^CS.PersistentD=1 ^CS.PersistentD(1)=$lb("",$lb(0,-1)) ID data_Month data_Year 1 -1 0 Can I make a serial class always computed? I want to receive the following output: Save: OK ^CS.PersistentD=1 ^CS.PersistentD(1)=$lb("",$lb(0,-1)) ID data_Month data_Year 1 1 2017
go to post Eduard Lebedyuk · Jan 27, 2017 There should not be a problem with underscores: set obj = ##class(%DynamicObject).%FromJSON("{""a_b"":1}") w obj."a_b" >1
go to post Eduard Lebedyuk · Jan 25, 2017 Macros can eliminate using $method/dynamic dispatch here altogether.
go to post Eduard Lebedyuk · Jan 25, 2017 Macros for method names which compile into AmethodName or methodName depending on global var set for compilation then. Dynamic dispatch is a hit on speed anyway.
go to post Eduard Lebedyuk · Jan 25, 2017 Always call do a.AmethodName() And inside dynamic dispatch check global variable %debug (or global, or some IsDebug method etc.). If it exists call both annotation methods and target method, If it does not exist only call target method.
go to post Eduard Lebedyuk · Jan 25, 2017 Another approach would be using dynamic dispatch: Let's say you have this method: /// @NiceTest1 ClassMethod Test() { Write 1 } Using Class Generators you generate 2 additional methods: /// @NiceTest1 ClassMethod OnBeforeTest() { Write "Before NiceTest1" } /// @NiceTest1 ClassMethod OnAfterTest() { Write "After NiceTest1" } and you add dynamic dispatch method (and dynamic dispatch classmethod) to the class: /// Is used to implement an unknown method call. It is also used /// to resolve an unknown multidimensional property reference (to get the value /// of a property) because that syntax is identical to a method call. Method %DispatchMethod(Method As %String, Args...) [ ServerOnly = 1 ] { // Amethod -> method set Method = $e(Method, 2, *) do $method(, "OnBefore" _ Method, Args...) do $method(, Method, Args...) do $method(,"OnAfter" _ Method,Args...) } So, as a whole it can look like this: Class Utils.Annotations1 Extends %RegisteredObject { Method OnBeforeTest() { Write "Init NiceTest1",! } /// @NiceTest1 Method Test() { Write 1,! } Method OnAfterTest() { Write "End NiceTest1",! } /// Is used to implement an unknown method call. Method %DispatchMethod(Method As %String, Args...) [ ServerOnly = 1 ] { set Method = ..getMethodName(Method) do $method(, "OnBefore" _ Method, Args...) do $method(, Method, Args...) do $method(,"OnAfter" _ Method,Args...) } /// Is used to implement an unknown class method call ClassMethod %DispatchClassMethod(Class As %String, Method As %String, Args...) [ ServerOnly = 1 ] { set Method = ..getMethodName(Method) do $classmethod(, "OnBefore" _ Method, Args...) do $classmethod(, Method, Args...) do $classmethod(,"OnAfter" _ Method,Args...) } ClassMethod getMethodName(method As %String) As %String { // Amethod -> method set method = $e(method, 2, *) return method } } Works like this: USER>do a.ATest() Init NiceTest1 1 End NiceTest1 USER>do a.Test() 1
go to post Eduard Lebedyuk · Jan 24, 2017 You can modify method code during compilation (obviously dangerous) using generators. Here's the sample that annotates all methods, containing @ in description: Class Utils.Annotations { /// @NiceTest1 ClassMethod Test() { Write 1 } ClassMethod OnCompile() As %Status [ CodeMode = objectgenerator ] { #dim sc As %Status = $$$OK for i=1:1:%class.Methods.Count() { #dim method As %Dictionary.MethodDefinition = %class.Methods.GetAt(i) if method.Description [ "@" { set sc = ..annotate(method) quit:$$$ISERR(sc) } } quit:$$$ISERR(sc) sc set sc = %class.%Save() quit sc } ClassMethod annotate(method As %Dictionary.MethodDefinition) As %Status { #dim sc As %Status = $$$OK set code = method.Implementation.Read($$$MaxCacheInt) set code = ..cleadOldAnnotation(code) set code = ..addNewAnnotation(code, $e(method.Description, 2,*)) do method.Implementation.Clear() do method.Implementation.Write(code) quit sc } ClassMethod cleadOldAnnotation(code As %String) As %String { if $find(code, "//init annotation end") { set code = $e(code, $find(code, "//init annotation end") + 2, $find(code, "//complete annotation start") - $l("//complete annotation start") - 2) } return code } ClassMethod addNewAnnotation(code As %String, annotation As %String) As %String { #define Tab $c(9) set code = $$$Tab _ "Write ""Init " _ annotation _ """" _ $$$NL _ $$$Tab _ "//init annotation end" _ $$$NL _ code _ $$$Tab _ "//complete annotation start"_ $$$NL _ $$$Tab _ "Write ""End " _ annotation _ """" return code } } Compiles into: /// @NiceTest1 ClassMethod Test() { Write "Init NiceTest1" //init annotation end Write 1 //complete annotation start Write "End NiceTest1" } GitHub
go to post Eduard Lebedyuk · Jan 20, 2017 Yes, you can query everything you see in Message Viewer and Event Viewer. Their code is defined in EnsPortal.MessageViewer.zen and EnsPortal.EventLog.zen respectively. You can see the queries these pages use and adapt them, or inherit from them and publish it as another separate web application.Also, here's modification example - Ensemble Log Viewer with namespace support.
go to post Eduard Lebedyuk · Jan 19, 2017 You can specify Logfile setting for logging and these settings for debug:JavaDebug: Allow a Java debugger (such as Eclipse or JSwat) to attach. If True, enables Java debugging via TCP. The default is False.JavaDebugPort: Specify the port on which to listen. The default is 8000.JavaDebugSuspend: If Yes, suspend the JVM on start to wait for the debugger to attach. The default is No.Documentation.
go to post Eduard Lebedyuk · Jan 17, 2017 %DB_CACHESYS may also be required, because data for this table is stored in CACHESYS database.
go to post Eduard Lebedyuk · Jan 15, 2017 Are there any hardware differences?Are there differences in memory allocation?
go to post Eduard Lebedyuk · Jan 13, 2017 Thank you!Do you import code from GitHub repository into Ensemble instance automatically?
go to post Eduard Lebedyuk · Jan 9, 2017 you are entirely correct. Good to hear.$$$SIMSRCDOMENTIf I change algorithm to $$$SIMSRCDOMENT I don't receive any results (Results local is undefined).If I choose $$$SIMSRCEQUIVS or $$$SIMSRCSIMPLE I get Results local as expected.What may be the reason? I didn't modify the domain between runs.Method returns $$$OK and %objlasterror is empty using any algorithm.