[RESOLVED] Where should user-related information be stored when using accounts-base?

Hi all!

I set up user management in my app with accounts-base and some additional packages. As a result, I have a user collection in the DB.

I now want to store some information related to a user profile (favorites of various entities that the user selects in the app).

What is the best practice of where to store that information?

I recall from other frameworks that were based on RDBS that it was usually recommended to create a separate entity extending the base user to “separate concerns”.

Or is there nothing much speaking against just adding attributes to user documents?

TIA
Matt

1 Like

So we’re going to cover this in the Meteor Guide: https://github.com/meteor/guide/blob/master/outlines/accounts.md

We’re going to suggest adding new top-level fields to the users collection, mostly because the two other options aren’t great:

  1. Using a sub-field like profile doesn’t work well because DDP can only send updates on top-level fields; this means you can’t really publish only some of profile to different users.
  2. Using a totally different collection doesn’t work well with Mongo since there aren’t good ways of managing related collections, especially when they are very tightly coupled.

In the favorites case, though, I think it might actually be better to have a separate collection of just the “favorites”.

2 Likes

Hey @sashko!

Thanks for elaborating. When you recommend a separate collection for the favorites, are you referring to something like this?

favorite = {
user: <user_ref>,
favorites: [, , …]
}

If so, does this effectively replicate the join table pattern from RDBMS?

So it depends on how many favorites you would envision each user having. If it’s not that many, then it’s OK to keep them in an array. If it’s a huge number, like > 1000, it could be good to normalize. Because in Meteor, there isn’t any smart diffing of arrays on the network level - every time you add a new item to the array it will resend the whole thing. Perhaps that isn’t a big problem.

Do you envision showing who favorited certain entities in your app? Like on Twitter, where you can see who favorited each tweet?

2 Likes

Thanks again for elborating, greatly appreciated (hadn’t considered the network level aspect, for example).

But for now, mine is a very small app for publishing quotes. Users should be able to favorite them, and for each user I want to show the quotes he added to favorites, as well as show a count for each quote that shows the number of users that added it as a favorite.

Yeah so the best approach there is probably tracking the number of favorites as a field on each individual quote, and then having an array on each user. Looks like you’re on the right track!

maybe something like socialize:likeable or socialize:linkable-model can help you

1 Like

I was following Meteor guide guide.meteor.com/accounts.html#custom-user-data for adding custom fields as top level fields to Meteor.user Collection , but the custom data field doesn’t seem to get updated on Meteor.user collection , My Trial code is here on github github.com/vijaydasmp/CustomFieldDemo with steps to reproduce ,

I see some inconsistent behavior also in Meteor.user document , Some times ‘profile’ field is visible some times its not,
Also https://github.com/meteor/guide/blob/master/outlines/accounts.md it doesnt exist

  1. There is a bug in the file “client/events.js”, line 4, which is displayed in the console when you click on “save”. Replace:

event.preventDefault();

by:

events.preventDefault();

  1. Data is correctly updated in the “users” MongoDB collection when you click on “save”. You can check that running:

meteor mongo

then in the shell:

db.users.find()

  1. You didn’t remove the stupid “autopublish” and “insecure” packages. First thing to do is removing that crap out of your Meteor project. It must be a reflex. I don’t understand why they are added by default. They give bad security habits to beginners and experts don’t need that since their code has good design. This is nonsense. Maybe useful for people who debug Meteor itself but definitely not something for everyone.

  2. There are curly braces in file “server/publications.js”, line 1, arround the “userIds” parameter. I don’t know why they did that in the tutorial, but this is clearly an issue. If you add this code in this file on line 2:

console.log(">>>>> userIds value is:", userIds);

and look at the console, you’ll see that it’s undefined. Now remove the curly braces on line 1 and try again: value is the one from Meteor.userId().

  1. For some reason the code in file “server/publications.js” from line 3 to 5:

    new SimpleSchema({
    userIds: { type: [String] }
    }).validate({ userIds });

doesn’t validate and consequently prevents the code from running further to this point. Comment out theses 3 lines and it will keep running. You can check proof of what I’m saying by adding this code on line 6:

console.log("Running")

You will see that this line is not displayed before you comment out the three said lines.

  1. Your publication filters on the keys “name”, “age” and “gender”. First the “gender” key doesn’t exist, it’s called “sex” in your database. Second these are not top-level keys in your “users” collection. They are sub-documents of the main document called “detail”. So in file “server/publications.js” change line 14 from:

fields: { name: 1, age :1, gender:1 }

to:

fields: {detail: 1}

or:

fields: {"detail.name": 1, "detail.age": 1, "detail.sex": 1}

I won’t talk about the huge security flaws in this code because it’s a demo app and I assume it was just made to understand how publications work. I just hope that you are aware that this code is totally insecure by design (for example: you can invoke the Meteor method with any userId and consequently update the profile of someone else).

More strictness is required in your code Sir! :wink:

1 Like

What do you mean exactly? Because if I use this, for instance:

fields: {"detail.name": 1, "detail.age": 1, "detail.sex": 1}

it will publish the 3 sub-documents, and if I use this:

fields: {"detail.name": 1, "detail.sex": 1}

it will publish only the 2 sub-documents (EDIT: and the future updates of these sub-documents). The third is not sent to the end-user despite the fact that it’s not a top-level document.

However your post was about 6 months ago so maybe Meteor updates changed that behaviour since then.