Returning To Meteor And Confused

Hi all,

It’s been a while since I last used Meteor and while I think my current project is a perfect fit for it I’m fairly lost as things have changed since pre 1.0 Meteor.

My main issues so far are as follows:

  1. I created a schema (simpl-schema) for my user model and placed it in imports/users/user.js but it doesn’t get loaded automatically which matches what I expected. But how do I get the schema to attach so it can be used? Do I just import the file into the server/main.js and/or client/main.js?
  2. I am using social logins. I created a ServiceConfig file under imports/startup/server/useraccounts-configuration.js as seemed logical. I had to get the code at least somewhat tested as working, so I threw it into the startup function in server/main.js. Is that considered the go to way of managing that setup or is there a better way to organize that? I’d prefer to have it somewhere else to keep the main file cleaner.

I understand using other schemas/models as you define them and the collection they attach to and then import as needed. But any clarifications on the above would be appreciated.

It might help to spend a few minutes playing around with the template system I have my students use to become familiar with Meteor:

To attach a schema to a collection, see this:

I can’t help you with the social login stuff. : )

1 Like

Thanks for the reply, but this doesn’t answer either of my questions really. I figured out a way to answer number 2 that seems OK, but your example repo doesn’t really answer number 1 where I want to add a schema to the built in Meteor User collection so that it is used in the Accounts logic process unless I’m missing something.

Oh, sorry, I didn’t understand what you were asking.

I’ve always heard that one should avoid using the Users collection to add much application-specific functionality. Instead, define a separate collection (call it “Profiles” or something similar) and put the data you want in it. You then have complete control over visibility, schema, etc.

Ok, that makes sense. When I was last working in Meteor primarily the profile field on the user was just becoming a no-no, and so people were attaching schemas directly onto the user collection Meteor created. Interesting to see it seemingly has gone to splitting it out fully. It makes a lot more sense overall to me.

Now I just need to figure out why I’m apparently getting a type issue from dotenv O.o

You attach the schemas where you declare the collections.

import { Meteor } from 'meteor/meteor'
import { User } from '../schemas/users' // your user schema

const Users = Meteor.users

Users.attachSchema(User)

if (Meteor.isServer) {
  Users._ensureIndex({ slug: 1 }, { unique: true }) // example
  Users._ensureIndex({ username: 1 }) // example
}

The “traditional” structure includes startup folder for client and server under app/imports/startup/client (or server). In each of these folders you have a index.js file that imports all files in those folders.

Then you import the index file in your clients side, respectively the index file in the server startup folder in your server/main.js.

Your services file may look like this:

import { Meteor } from 'meteor/meteor'
import { ServiceConfiguration } from 'meteor/service-configuration'
import { Accounts } from 'meteor/accounts-base'

Meteor.startup(() => {
  const services = Meteor.settings.private.oAuth
  if (services) {
    for (const service in services) {
      ServiceConfiguration.configurations.upsert({ service }, {
        $set: services[service]
      })
    }
  }

  Accounts.config({
    sendVerificationEmail: true,
    passwordResetTokenExpirationInDays: 1
  })
})

While your settings.json includes:

{
  "private": {
    "oAuth": {
      "facebook": {
        "appId": "....",
        "secret": ".....",
        "loginStyle": "popup",
        "scope": ["public_profile", "email"]
      },
      "google": {
        "clientId": ".......apps.googleusercontent.com",
        "secret": "........",
        "loginStyle": "popup",
        "scope": ["email", "https://www.googleapis.com/auth/plus.login"]
      }
    }
}
3 Likes

No need or benefit from keeping a Profiles collection. You just publish minimum data of the user (e.g.: _id, username, avatar, slug) and get everything else with methods, as necessary.

Example: you log in … get the minimum data. Then visit the User Profile page, you load the user profile data to populate your profile fields with a method. You leave the Profile page, scrap the extra user information from memory or keep it (in an app state object like Redux). You definitely not need to stay subscribed to data that never changes and if it changes (Avatar for instance) you just pull it again with a method.
It is better to keep the profile under the User in cases you need to get an info from the User and another info from the Profile. This is a simple call to the same object in the same collection instead of having to use an aggregation over two collection (User and Profile)

2 Likes

Ok, that looks a lot more like I was remembering and thanks for pointing out I can pass in the social configs via the settings.json file. From the documentation I had gotten the image that it had become mainly for setting stuff in Galaxy. I will likely have to steal that format and use it myself.

For your first example though, would you run Users.attachSchema(someUserSchema) during server startup? That’s the part I’m not sure of at this point. The last I remember from the previous large Meteor app I worked on it had been done before I got there and I remember it being in an eagerly loaded file but I can’t remember what side, and I’m not sure if it’s even necessary?

You run it as the next line (for example) after you initialize the collection.

I‘m using a highly customized user collection, and it works fine! The only thing to consider is that you store sensitive information in keys outside of the profile key. And only publish them (or access them via methods) if you really need them and have added some safeguarding. I’m using the roles package for that.

1 Like

Does it not have to be run to take effect though? I’m using socialize:user-profile and I was putting my stuff in my imports folder, but I’m not importing it anywhere else at this point. I.e. I have /imports/api/users/user.js and I’m trying to add methods like documented here: GitHub - copleykj/socialize-user-profile. When I do that it doesn’t seem to be registered and I assume it’s because it’s not actually included. Would I just drop that file into the server startup to have it initialized?

Note that storing LOTS of custom data on the Users collection can cause performance issues, because by default Meteor’s accounts system fetches the entire user record from the database every time a user logs in or out.

I made a PR which fixed this since Meteor 1.10, have a read of this: Meteor Guide: Preventing unnecessary data retrieval

Ok, try to attach directly to Meteor.users (check this issue: javascript - Attached schema to Meteor.users and now unable to create new users - Stack Overflow)

The package does it automatically I’ve noticed by running the attach process to the Meteor User object in eagerly loaded server code. I’ve gotten my slight changes to take hold by following the same idea. I guess for other objects I make I’ll do the same for the Meteor Methods and Subscriptions I make for them, get loaded onto the server eagerly.