Smart way to push object to firebase - javascript

I have an object that I want to push to the firebase realtime database, looking like this:
userProfile = { name: "Jon", age: 25, gender: "male", ...plenty more attributes}
If I want it in firebase, I could write it like this:
return firebase.database().ref('/userProfile').push({
name: userProfile.name,
age: userProfile.age,
gender: userProfile.gender,
....
}).
But since I have plenty of objects with many attributes I would prefer not writing it by hand. Loops are not allowed in push (). I could push the whole object like this:
return firebase.database().ref('/userProfile').push({
userProfile: userProfile
}).
But it will create an additional child node like
ref/userProfile/123someId/userProfile/name
which is bad practise because it disallows using filters and more later on.
Is there a more effective way to push the attributes of an entire object without writing down every key/value pair?

The answer could not be easier, but in case someone else stumbles across the same issue:
firebase.database().ref('/userProfile').push(userProfile)
Thanks guys

Related

How to store Object in Cookies

I have an app in Nuxt and I would like to store content of the shopping cart in the cookies. To store cookies I use cookie-universal-nuxt package. However, I am not able to store "some" objects in it. Here is an example:
const userInfo = {
name: 'Smith',
age: 41,
isVip: true,
}
this.$cookies.set('userInfo', JSON.stringify(userInfo))
console.log(this.$cookies.get('userInfo'))
This works as it should, no problem there.
Problem is, it does not work with my real objects:
const savedProductsArray = this.$store.getters['cart/products'] // returns array of products
const savedProducts = savedProductsArray[0] // select first one
this.$cookies.set('productInfo', JSON.stringify(savedProducts))
console.log(this.$cookies.get('productInfo')) // prints undefined
So the second object is apperently not stored in cookies. Any idea why? Thanks!
Btw, this is how userInfo object looks like in console:
Object {
age: 41,
name: "Smith",
isVip: true,
}
and savedProducts:
Object {
calories: 123,
name: "a",
...
}
So it looks like they are the "same" objects, but somehow only the first one can be stored in cookies...
Update: OP confirmed the issue was with cookie size.
There could be multiple issues, could you check what is the value of JSON.stringify(savedProducts) also it will help if you could include fully stringified savedProducts in the post.
Also, be aware per domain only about 4KB is allowed size for cookie so if you are trying to store that much data that could be the reason as well

How to get only column name from relation

How to join column, that when i launch my function, he return me only columns name instead of entity_columnName.
I'm using TypeORM, and i try this;
const data = this.conn.getRepository(User).createQueryBuilder('user');
data.leftJoinAndSelect('user.orders', 'orders');
data.getRawMany();
but return me:
firstName: ...
lastName: ...
age: ...
order_name: ...
order_price: ...
instead of:
firstName: ...
lastName: ...
age: ...
name: ...
price: ...
can someone tell me how do this? thanks for any help
How are your User and Order entities defined?
If you define a relation (e.g. OneToMany) with the eager: true option, then TypeORM will automatically include the related entities when you query using the repository *find methods. It won't do this when you use the QueryBuilder, where you have to add them such as with leftJoinAndSelect() (as you have done).
An example from an Invoice entity that has OneToMany line items:
#OneToMany(
() => InvoiceLineItem,
(item: InvoiceLineItem) => item.invoice,
{ eager: true }
)
items: InvoiceLineItem[]
Per the example, if I were then to find() or findMany() invoices, then the related objects, items will be included as well because eager: true.
This behaviour might translate well to your situation with users and orders.
Also be aware of the differences between getMany() and getRawMany() when using the query builder.
If you use getMany() then TypeORM will automagically give you entities back (e.g. you'd get an instance of User with property orders that is an array of Order instances). The property names will be correct.
Since you added the NestJS tag to your question, also understand serialization:
https://docs.nestjs.com/techniques/serialization
There is a built-in ClassSerializerInterceptor that comes with NestJS that you might find useful.
In your controller you can decorate the class or any of its methods e.g.
#UseInterceptors(ClassSerializerInterceptor)
This will transform the response to JSON, and will apply the rules specified with class-transformer decorators on the entity/DTO class.
If you were to use this interceptor, the response sent to the client will have your desired property names.
If you really want to modify the response that your client gets back, you can also look into writing your own Interceptor.

Why should my Redux store be serializable?

When reading the redux docs I found this:
Still, you should do your best to keep the state serializable.
Don't put anything inside it that you can't easily turn into JSON.
So my question is, what's the benefit of keeping state serializable?
Or, what difficulties I may have if I put non-serializable data into store?
And I believe this is not unique to redux - Flux, even React local state suggest the same thing.
To make me clear here is an example. Suppose the store structure is like this.
{
books: {
1: { id: 1, name: "Book 1", author_id: 4 }
},
authors: {
4: { id: 4, name: "Author 4" }
}
}
This should all looks good. However when I try to access "the author of Book 1", I have to write code like this:
let book = store.getState().books[book_id];
let author = store.getState().authors[book.author_id];
Now, I'm going to define a class:
class Book {
getAuthor() {
return store.getState().authors[this.author_id];
}
}
And my store will be:
{
books: {
1: Book(id=1, name="Book 1")
},
...
}
So that I can get the author easily by using:
let author = store.getState().books[book_id].getAuthor();
The 2nd approach could make the "book" object aware of how to retrieve the author data, so the caller does not need to know the relation between books and authors. Then, why we are not using it, instead of keeping "plain object" in the store just as approach #1?
Any ideas are appreciated.
Directly from the redux FAQs:
Can I put functions, promises, or other non-serializable items in my store state?
It is highly recommended that you only put plain serializable objects, arrays, and primitives into your store. It's technically possible to insert non-serializable items into the store, but doing so can break the ability to persist and rehydrate the contents of a store, as well as interfere with time-travel debugging.
If you are okay with things like persistence and time-travel debugging potentially not working as intended, then you are totally welcome to put non-serializable items into your Redux store. Ultimately, it's your application, and how you implement it is up to you. As with many other things about Redux, just be sure you understand what tradeoffs are involved.
Further reading:
What is time travel debugging?
Adding to what #Timo said , If you want to setup relation between 2 states in your state tree and use computed values, reselect is the best suitable fit for that scenario. It allows to creareselectors which can be used to define computed states. In your case author can be created using a selector on top of book. https://github.com/reactjs/reselect
#timo 's answer is correct. In addition, I recommend a library called Redux-ORM to work with normalized/relational data in your Redux store. See my recent comment at Dealing with data consistency in a very large store in React + Redux SPA SaaS for links to more information.
Adding this because you asked for a suggestion. If you only want to create an object out of your class then you can simply create a function that returns an object. In your Book class it could be something like
function newBookObject({id, name}) {
return {id, name}
}
And your store would look like
{
books: {
1: newBookObject({id: 1, name: "Book 1"})
},
...
}
The object being returned can't contain any function's in it though, it should be just a plain static object with pure data and nothing else. You can't serialize something that isn't pure data.

Angular2, child properties and elvis operator

So i have a complex date model coming from the server to feed my Angular2 component. Following shows a small part of the template for this component:
<div>
<span>{{Person.Address.City}}</span>
<input type="text" [(ngModel)]="Person.Address.City" />
</div>
The Address might be null or undefined depending on the data that's returned from the server. I know that elvis operator will save me from one error:
<span>{{Person?.Address?.City}}</span>
but unfortuantely it won't save me for [(ngModel)]="Person.Address.City" as there is no elvis defined for that. You'll get a parser error if you do something like [(ngModel)]="Person?.Address?.City" and if you don't then you'll get the null exception.
Here are two simplest variation of data, although there can be a lot more:
{
Name:'sam',
LastName: 'jones',
Address: {
Street: '123 somewhere',
City: 'some land'
State: 'SL'
}
}
or...
{
Name:'sam',
LastName: 'jones'
}
Since the responsibility of handling these scenarios should be on Angular2 rather than the server that provides the data, due to separation of presentation and business logic, how would I handle the scenario(s)?
So as it turns out, you either maintain 3 models, one for front-end (Angular2), one for middle tier (ASP.NET, JAVA, etc...) and another for your data model. Or you could make sure, as i did, that your middle-tier model will not have a null complex object. This means initializing complex properties inside your model and getting away with 2 models.
Also to note, if you have don't or can't modify your middle-tier model, then your only option is to create a compatible model for your front-end (Angular2) and merge as necessary once data has returned from API, service, etc..
At the service level you can add a blank object for Address. Right after receiving a response.
This way you fix the problem at it's source for entire application.
Here is simple solution with RxJS:
this._http.get(url)
.map(res => res.json())
.map(res => {
if (res.Address === null || res.Address === undefined) {
res.Address = {}
}
return object;
});
You might also want to consider removing the Address object if it is blank, right before saving it.

local storage expiring data

I am using localStorage to save conversations client-side to save space server-side in my db. In order to do it I use an object like this:
users = {
478vh9k52k: {
name: 'john',
messages: []
},
42r66s58rs: {
name: 'jack',
messages: []
}
};
I then use users[id].messages.push(msgObj) to push new messages inside the right user ID. Lastly I use JSON.stringify and then save the resulting string.
Problem with this is that slowly the string will grow, thus filling in the limits. It is not too much of a problem the length of the messages array, because I truncate it, but the existence of old users not being necessary anymore.
Question is simple: how can I delete the old users that are contained in the 'users' object? I was thinking to add a timestamp as a key inside the object and then accessing random users to check on them at every save.
Or is there a better way to do this?
why access them randomly? you could slice up your storage in days instead, with a
localStorage["chatLogs"] = {
"13........0" : {
bob: {},
alice: {},
christoffelson: {}
}
"13....86400" : {
bob: {},
alice: {},
christoffelson: {}
}
}
and then run through your object by its keys. If they're older than a day, delete them. Alternatively, you can have a look at using indexdb instead of localStorage if you're going to do a lot of querying/filtering.

Categories