Using ngrx, I store an observable inside a store, and I get the following error.
this is because I try to store an object of classA with an observable, and that some other class subscribed to it.
My question is, is there a way to avoid circular reference in an observable? or in ngrx to ignore this property ?
Don't store an observable in the store. Your actions and store should be serializable. https://ngrx.io/guide/store#key-concepts
Related
I read these blog posts written by Doug Stevenson Part 1, Part 2, Part 3. On part 2 he says that
The Realtime Database SDK makes it really easy to convert a DataSnapshot into a JavaBean style object
And mentions that we can use this line of code to get the DataSnapshot deserialized into a HotStock object (a JavaBean class)
HotStock stock = dataSnapshot.getValue(HotStock.class)
I´m confused because he first uses Transformation.map and then he says that if a LiveData transformation is expensive we can create a MediatorLiveData object from the ViewModel to get the DataSnapshot converted into a HotStock object.
My question is: Why can´t we just call the
HotStock stock = dataSnapshot.getValue(HotStock.class)
from the onDataChange() method on the ValueEventListener which resides in the class extending the LiveData super class and then simply use the setValue() method to pass the HotStock object directly to the ViewModel and then to the Activity or Fragment observing for changes to the LiveData?
You can do that, but getValue() passing a class object is actually kind of slow (especially the first time, for a particular class) because the SDK has to use reflection to figure out how to map all the fields into the object it creates. Java reflection known to be fairly slow. But it's up to you what you want to use.
My question relates to dispatching & selecting from the ngrx store.
Let's look at the following code from the official example app:
export class CollectionPageComponent implements OnInit {
books$: Observable<Book[]>;
constructor(private store: Store<fromBooks.State>) {
this.books$ = store.select(fromBooks.getBookCollection);
}
ngOnInit() {
this.store.dispatch(new collection.Load());
}
}
I would like to understand what motivated the choice of dispatching from ngOnInit and selecting from the constructor.
Can anyone please provide an explanation?
P.S. By the way, the above is sample code from the ngrx example app that can be found here: https://github.com/ngrx/platform/blob/master/example-app/app/books/containers/collection-page.ts
The constructor is executed when the class is instantiated and ensures proper initialization of the class´ fields.
This is where Angular resolves providers you may pass as arguments in your constructor.
The ngOnInit lifecycle hook is called after the data-bound properties have been checked for the first time (inputs & outputs of the component).
For a more detailed explanation see this question.
The motivation for selecting from ngrx store in the constructor and dispatching from ngOnInit as far as I understand it, is that selecting is part of initializing you component class. Since this.books$ is an Observable, it makes sense initialize it in the constructor so it is ready for use immediately after creation. Assuming the bookCollection.Load() emits a value to this.books$ you want this.books$ to be an observable of those books before an eventual value is emitted.
Since you want those values emitted to this.books$ it makes sense to dispatch the action in ngOnInit. This way you can ne certain that this.books$ is initialized.
This answer to a similar question might also be of help.
The main reason in my opinion is separation of concerns.
The constructor is the place were you define all dependencies. So in this case getting the store and than selecting a slice of it.
Dispatching an actions though is part of logic that can be separated from the dependencies (if possible).
Think of a class with lots of dependencies and lots of actions. This helps to keep things separated.
Everyone who will read the class can always look at the constructor to see what the dependencies are and is not obfuscated with any other logic.
In Short
I seem to have landed on a MAJOR anti-pattern of saving objects WAY too many times. I've read through the limited Objectify docs and can't seem to find the right pattern to use.
Details
I have multiple objects I want to store. They are all transient (they don't exist in the database yet) and they have a one-to-many relationship. I don't want to sit and call ofy().save() on every last object in my hierarchy.
In the following example, a Player has a List of Cards.
My Model:
#Entity
public class Player {
#Id private Long id = null;//will be generated
private List<Ref<Card>> cards = new ArrayList<Ref<Card>>();
//getters and setters here
}
public class Card{
#Id private Long id = null;//will be generated
//lots of other fields and getters and setters here
}
My Operation:
I need to create a new player and new card, with the player having a reference to the card in his List "cards."
IDEAL SOLUTION:
I would like to just create the player and card java objects, set their relationships, and pass them to Objectify to be saved. Like this:
Player player = new Player();
Card card = new Card();
player.setPlayer(Ref.create(card));
ofy.save().entity(player).now();
That will fail. The 3rd line attempts to create a new Ref for Card, which cannot be done because Card doesn't have an Id yet, which will be assigned to it once it's already persisted. It seems I must never associate an object with another until one has already been saved.
Current Crappy Solution
So, my solution must be to save the Card first, and then relate it to the Player, then save the player.
Player player = new Player();
Card card = new Card();
ofy().save().entity(card).now();
player.setPlayer(Ref.create(card));
ofy().save().entity(card).now();
This is insane. It seems reasonable at first, but my app is dealing with many more relationships than just this, and with this pattern my algorithm will be a spiderweb of checking for transient objects inside collections before saving the entity I'm actually concerned with.
There MUST be some way to tell Objectify to just SAVE all child/related entities along with the entity I've requested, and furthermore generate the Ids necessary instead of throwing an Exception at me.
Furthermore, I'll also need this sort of "recursive save" solution even when none of my objects are transient (ie they all have IDs already). I can't waste my time iterating through collections and then all the collections WITHIN those collections and saving them all. I'm going to need some way of telling Objectify to just SAVE THIS WHOLE HEIRARCHY OF OBJECTS I just passed you.
I've been reading around this #Load annotation and I feel like maybe there's something in there I'm missing... I don't know. Need help. Documentation is slim.
UPDATED SOLUTION
For posterity -
Using the allocateId() method decouples the entire ID generation constraint away from the database and you get a VERY clean pattern, particularly if you do as I did:
All database #Entity classes get a private constructor and a static public factory for creating transient objects. This static factory method ( createTransient() ) will always allocate a new ID. So then, all client code can use this method for acquiring new transient objects, or the obvious objectify load for acquiring existing persisted instances. Simple. Done. Lovely.
I recommend two things:
Allocate ids manually when you construct your objects using ObjectifyFactory.allocateId(). Do not use the "save with null autogenerates" feature. As you've noticed, it's a PITA to deal with entity objects that have null ids, so don't allow them to exist.
Use deferred saves. ofy().defer().save().entity(blah); You can save almost any number of things this way and they'll only get saved once on commit (or closing of the objectify session). Deferring save on the same entity multiple times produces only a single save.
This pattern of leaving ids null and filling it in on save is a holdover from the JPA days. It didn't work very well with JPA either; there were plenty of frustrating edge cases dealing with entities missing ids (especially when you wanted to put the in maps or sets). The best solution is to simply guarantee that no entity is ever missing an id in the first place.
Note that you'll want to allocate the id in a custom constructor, not the no-args constructor that Objectify uses to build your entity on load. Allocating an id is cheap but still a call to the GAE service layer and you don't want to do this on every load.
If I call write and update an object with a list of newly created other objects, will those objects automatically be written into Realm as well?
If I understand your question correctly, you will update a Realm Object inside a write transaction and that object has a one-to-many relationship to another Realm Object. Your class may look like this for example:
public class Owner: Object {
let listOfObjects: List<SomeObject> = List<SomeObject>()
}
Then if you create a list of type SomeObject in a write block and set your class' listOfObjects to the newly created list, the new list of objects will be persisted in Realm when the write block ends. (Assuming your SomeObject class is a subclass of Object ofcourse)
From my understanding (in Realm Objective-C and Realm Swift at least), no. If you create a new list of objects that aren't persisted in Realm yet and assign them as child objects of an object that is, they still won't be guaranteed to be added to Realm that way.
For best practice, I recommend that in your write transaction, you both explicitly add the new objects to Realm and then add them to the child object list of that object.
Basically I want to make my script service only serialise properties that are not null on an array of object I am returning... So this..
{"k":"9wjH38dKw823","s":10,"f":null,"l":null,"j":null,"p":null,"z":null,"i":null,"c":null,"m":0,"t":-1,"u":2}
would be
{"k":"9wjH38dKw823","s":10,"m":0,"t":-1,"u":2}
Does anyone know if this is possible?
Basically the reason for this is because null values are for unchanged properties. A local copy is kept in the javascript that is just updated to reduce traffic to the server. Change values are then merged.
You can create a custom JavaScriptConverter class for the JSON serialization process to use to handle your object, and then put the necessary logic in the Serialize method of that class to exclude the properties that are null.
This article has a clear step-by-step discussion of the process involved in creating it.
You probably would not need to actually implement the Deserialize method (can throw a NotImplementedException) if you are not passing that type of object in as an input parameter to your web services.