mongoose and lazy initialize attributes not executing in correct scope - attributes

I'm using mongoose for my data access layer, and I really like the different
features it offers to create document models (Attributes, Methods, Static Methods..)
I use the virtual attribute feature of mongoose to create attributes that will not be persisted to MongoDB. However, these attributes are computationaly expensive (and using them many times is not helping me).
Lets take for example the same example on mongoose virtual
it persists person.name.first and person.name.last, and uses virtual attribute for person.name.full
Let's say I want to compute person.name.full only one time per the lifetime of the document
(and if I allow to set the attribute or its dependent fields like in the example, then also for every get after a dirty set).
I need an extra variable in the document scope, so naturally I used closures for this
but the 'this' scope in the function that computes the attribute, is of the global object, and not of the document I'm working on.
Code:
var makeLazyAttribute = function(computeAttribute) {
var attribute = null;
return function() {
if(!attribute) {
attribute = computeAttribute();
}
return attribute;
}
};
MySchema.virtual('myAttribute').get(makeLazyAttribute(function () {
// some code that uses this, this should be the document I'm working on
// error: first is not defined, inspecting what is this gives me the global object
return this.first + this.last
}));
Please help!

Well, ok, I've made some progress makeLazyAttribute does execute in the document scope
so I only needed to change attribute = computeAttribute(); to
attribute = computeAttribute.call(this); .
However, now Im only remembering the first ever computeAttribute() invocation instead of remembering
the first function invocation per each document.
Must have a way to mitigate this.

Related

Best practice core data same view for creating and editing [duplicate]

This question already has answers here:
swiftui how to fetch core data values from Detail to Edit views
(2 answers)
Closed 11 months ago.
I try to use core data to store persistent data on an iOS device. I've got user flows to create and edit domain objects with a few related and deeply nested objects.
Those user flows are very similar, so I would like to use the same views for those tasks, just deciding on appear if the view got an existing domain object passed or it needs to create a new one.
After testing different approaches, nothing seems to fit this context so I wonder if there are recommended ways for this situation?
The following options got tested:
initializing the core data object in init() results in an Modifying state during view update, this will cause undefined behavior. warning
initializing the core data object in .onAppear requires the #ObservedObject var domainObjectPassed: DomainObject to be optional, not quite what I'm looking for as well
Any suggestions?
Already did that. I extracted the same logic into one view and have two distinct wrapper views that should handle this problem. But I've got the same situation one level higher.
struct CreateView: View {
#ObservedObject private var domainObject: DomainObject
init(moc: NSManagedObjectContext) {
domainObject = DomainObject(context: moc)
domainObject.id = UUID()
try? moc.save()
}
var body: some View {
CustomizeView(domainObject: domainObject)
}
}
-> results in warning from the first option
struct CreateView: View {
#Environment(\.managedObjectContext) var moc
#ObservedObject private var domainObject: DomainObject? = nil
var body: some View {
CustomizeView(domainObject: domainObject)
.onAppear {
...
}
}
}
-> requires domainObject in CustomizeView to be optional, not what I'm looking for
I am using the same concept (one view for editing and creating), but in my case I find myself comfortable using an optional to get the core data object. If you can live with an optional, this could work.
In this way, you just need to check if the object passed is nil: if it is, create the object, otherwise use the object passed.
In a very schematic way, the view could be:
struct EditOrCreate: View {
var coreDataObject: MyCoreDataEntity
// Optional object at initializer
init(objectPassed: MyCoreDataEntity? = nil) {
if objectPassed == nil {
coreDataObject = MyCoreDataEntity(context: thePersistentContainerContext)
} else {
coreDataObject = objectPassed!
}
}
var body: some View {
// All the text fields and save
}
}
When creating, just call EditOrCreate().
When editing, just pass the object: EditOrCreate(objectPassed: theObjectBeingShown).
You can also make coreDataObject an optional variable (which is what I did in my code), depending on how you want to handle your logic - for example, to cancel the creation before saving: in that case, you need to check for nil after the user has confirmed the creation of the new object.
Some programmers believe that "Premature Optimization Is the Root of All Evil". What I've seen happens when creating generic view code with only a small number of cases that have not yet been thought through is that after creating the generic version, you realise that you need to customise one of them, so end up trying to override the default behaviour in certain cases, which gets real messy and you would have been better off just with separate versions in the first place.
In SwiftUI, the View structs are lightweight and there is no issue with creating lots of them. Try to break your View structs up to be as small as possible then you can compose them together to form your different use cases.
The time you save could be spent on learning more about how SwiftUI works and fixing the issues in the code you posted. E.g. we don't init objects in the View struct init, or in body. Those need to run fast because that code runs quite frequently and creating objects is a comparably heavy task, also those objects that are created are immediately discarded after SwiftUI has finished building the View struct hierarchy, diffed it from last time, and updated the actual UIKit Views on screen. I highly recommend watching every WWDC SwiftUI video, there is a lot to learn and there is a lot of magic going on under the hood.
Another thing you could spend time learning is Swift generics and protocols. These are powerful ways to build reusable code using value types instead of class inheritance that we would typically use as ObjC/UIKit developers which tends to be buggy. You can read more about here: Choosing Between Structures and Classes (Apple Developer)

How can I get model reference on the fly nestjs mongoose

So my problem is I have models that is separated by one of our domain's types, and it has a lot of types which each one of em has a dedicated collection. As I know, we can inject the model in the service constructor like this way:
#InjectModel(ModelName.Job) private readonly jobModel: JobModel,
It is a bit messy to me to inject all of those collections in the constructor, and also they are not useful at the same time. So I wonder if I could load mongoose model dynamically inside the service's method using the our domain type as the key, more or less same as the module reference like this:
private getModelReference(reference: any) {
return this.moduleReference.get(ModelName[reference]);
}
But, any other workarounds to load the model dynamically on the fly are appreciated.
It is technically possible to do. Using your code above you can do
private getModelReference(reference: any) {
return this.moduleReference.get(getModelToken(ModelName[reference]));
}
Assuming that ModelName[reference] refers back to a mongoose model name (i.e. Cat.name or just 'Cat')

Haxe Property - getters and setters versus #:isVar

My question is regarding properties in haxe.
If I understand it correctly, if I make property like this
var propertyInt(get, set):Int; according to haxe documentation it's not really a variable. But I can make it a variable by modifying it this way
#:isVar var propertyInt(get, set):Int;. Otherwise I need to make two methods:
function get_propertyInt()
return propertyInt;
function set_properyInt(i)
return propertyInt = i;
So my question is: does it matter if I'm using exclusively #:isVar var propertyInt(get, set):Int; ? For example I have more than 5 properties in my class and as you can imagine making this methods for every property could be huge pain in the rear. So what is the best approach?
Here's what the documentation has to say about physical properties (also known as backing fields):
A field is considered to be physical if it is either
variable
a property with the read-access or write-access identifier being default or null
a property with :isVar metadata
So you can set up a property that fully consists of calculated values. Think a read-only property giving you the area of a rectangle as a function of width and height, or think of a property that is backed by some other property and just returns/sets width and height in a different unit. Or maybe you just want to name your backing fields differently, say m_width and m_height.
The :isVar is helpful in situations where the property access rules etc. laid out above would let the compiler think that there is no backing field needed. In that case, the code would fail (from the docs again):
// This field cannot be accessed because it
// is not a real variable
public var x(get, set):Int;
function get_x() {
return x;
}
function set_x(x) {
return this.x = x;
}
By adding :isVar you basically tell the compiler that you absolutely want the backing field. The other option for your particular case would be to use default,default, in which case the compiler knows there is an automatic backing field required and access should be restricted according to the access level of the property (public or private):
public var propertyInt(default, default):Int;
In that case you might also use a variable directly, because the net effect is in essence the same:
public var propertyInt : Int;

How to avoid creating objects to check or get content from Maps in Java

I am implementing my own Map in Java, using a custom class I made.
I already implemented the hashCode and equals without any problem.
I just have a question more related into performance and stuff like that.
So I will check many times in my application if a specific value is inside the map, for that, for that I have to create a object and then use the methods containsKey of Map.
My question is...
Is there any other way? without being always creating the object???
I cant have all the objects in my context universe, so that isn't a way...
I know I can just point the object to 'null' after using it, but still, it's not so elegant, creating objects just to check if there is the same object inside =S
Are there any other conventions?
Thank you very much in advance!
EDIT:
Stuff typed = new Stuff(stuff1, stuff2, (char) stuff3);
if(StuffWarehouse.containsKey(typed))
{
//do stuff
}
//after this I won't want to use that object again so...
typed = null;

SSJS global variable seems not working

I had declared and used a global variable in ssjs library as below:
var backendDoc:NotesDocument = null;
function savedata () {
print (backendDoc.getItemValueString("fieldname")); // crash here
}
I assigned a document object to it in the Edit button just after changing docuemnt mode from read to edit:
backendDoc = document1.getDocument(); // get backend document from datasource called document1
The code in above function return error NotesDocument.getItemValueString("string")) null. Apparently, the backendDoc is null.
Any ideas how to assign value and use global variable in ssjs library? Thanks in advance
There are 2 problems with your code:
as Michael pointed out: you should use a scoped variable. Global variables in script libraries are actually application global (think applicationScope) and might be unloaded any time if memory gets tight (behavior of them depends on the XPages version)
You can't use NotesObjects here. Between the calls the C Object that backs the JS object is released and your object becomes invalid.
You can either store the NoteId in a scoped variable and retrieve the NotesDocument every time or actually use a JSON structure to keep the values you are interested in and only read/write when actually needed (load/save event). Hope this helps
I think you have to use a scoped variable in which you store the universalid of the document. This can then be used at any script to initialize the backend document.
From a ssjs you can set a scoped variable using the put method and the get method to read the variable. Example to set and read a scoped variable in session scope :
sessionScope.put(“myvar“,“myvalue“)
sessionScope.get(“myvar“)
To learn more about scoped variables watch this
http://notesin9.com/index.php/2009/11/07/episode-4-intro-to-scoped-variables/

Resources