Upgrading to Meteor Socialize 1.0steemCreated with Sketch.

in #javascript7 years ago

There are many changes from the 0.x releases of Socialize and upgrading can be quiet daunting, but it is needed if you want to upgrade beyond 1.6.0, so let me walk you though it.

Simple schema

First things first, with 1.0 comes the newest version of Simple-schema, which will require you to update your schemas. For everything read the changelog. Here I will only cover the basics. First we need to add the new npm package:

meteor npm install --save simpl-schema

This means that we need to change imports in filed where we use simple schema to:

import SimpleSchema from 'simpl-schema'

You will have to replace your arrays declarations from:

{ foo: { type: [String] } }

to this:

{ foo: { type: Array }, 'foo.$': { type: String } }

Get the new packages

First let’s start by getting the new versions of packages:

meteor add socialize:base-model socialize:commentable socialize:friendships socialize:likeable socialize:linkable-model socialize:messaging socialize:postable socialize:requestable socialize:server-presence socialize:server-time socialize:user-blocking socialize:user-model socialize:user-presence socialize:user-profile

Note here that socialize:feed has been replaced by socialize:postable , so make sure to remove it so that you don’t get conflicts.

Update your collections

As much as simple-schema changed so too are there significant changes in schema from socialize upgrade. Base model will no longer do all the stuff for you so you will have to add all the initialization stuff and more yourself. This actually gets us to the default way that it is done in Meteor (let’s use a blog post collection as an example):

import { Mongo } from ‘meteor/mongo’;
import SimpleSchema from ‘simpl-schema’;
import { BaseModel } from ‘meteor/socialize:base-model’;
import { LikeableModel } from ‘meteor/socialize:likeable’;
import { CommentableModel } from ‘meteor/socialize:commentable’;
import { LinkableModel } from ‘meteor/socialize:linkable-model’;
export const BlogPostsCollection = new Mongo.Collection(‘blog_posts’);
const BlogPostSchema = new SimpleSchema({
 blogId: {
   type: String,
   regEx: SimpleSchema.RegEx.Id,
   denyUpdate: true,
   index: true
 },
 author: {
   type: String,
   regEx: SimpleSchema.RegEx.Id,
   denyUpdate: true,
   index: true,
   autoValue() {
     if (this.isInsert)
       return Meteor.userId();
   }
 },
 ...
});
export class BlogPost extends CommentableModel(LikeableModel(BaseModel)) {}
BlogPost.attachCollection(BlogPostsCollection);
BlogPost.attachSchema(BlogPostSchema);
BlogPost.attachSchema(CommentableModel.CommentableSchema);
BlogPost.attachSchema(LikeableModel.LikeableSchema);
LinkableModel.registerParentModel(BlogPost);

So first we create new MongoDB collection, then we define our schema. Finally we create a model class which we extend by commentable and likeable models (which will allow for blog posts to be commented on and liked). We attach the collection to our model  and then we attach all appropriate schemas. Finally we register the blog posts with linkable model.This new approach means that you will no longer be able to call your collections via Meteor.

Meteor.blogPosts.findOne();

Instead you will have to import the collection.

import BlogPosts from '../lib/blogPosts.js';
BlogPosts.findOne();

The same applies to profiles, messaging and other collection in the socialize ecosystem. These packages now export collection which you can import. For example messaging:

import { MessagesCollection, ConversationsCollection } from 'meteor/socialize:messaging';

Update how you call your collections

A big breaking change is that collections are no longer referenced in the Meteor object.So where in the past you could do:

Meteor.blog.findOne();

Now you have to import the required collection and call it like you would in plain Meteor:

import { BlogsCollection } from '../lib/collections';
BlogsCollection.findOne();

Migrating DB

Some parameters have also been renamed. To make it easier here is a simple migration script that you can run (I recommend using the percolate:migrations package for this task).First of let’s rename the old socialize collection to the new namespace:

// establish the old socialize collections
const profiles = new Mongo.Collection('profiles');
const blocks = new Mongo.Collection('blocks');
const comments = new Mongo.Collection('comments');
const conversations = new Mongo.Collection('conversations');
const messages = new Mongo.Collection('messages');
const participants = new Mongo.Collection('participants');
const posts = new Mongo.Collection('posts');
const friends = new Mongo.Collection('friends');
const requests = new Mongo.Collection('requests');
// rename them
profiles.rawCollection().rename('socialize:profiles', { dropTarget: true }, (error, collection) => {
 return collection;
});
blocks.rawCollection().rename('socialize:blocks', { dropTarget: true }, (error, collection) => {
 return collection;
});
comments.rawCollection().rename('socialize:comments', { dropTarget: true }, (error, collection) => {
 return collection;
});
conversations.rawCollection().rename('socialize:conversations', { dropTarget: true }, (error, collection) => {
 return collection;
});
messages.rawCollection().rename('socialize:messages', { dropTarget: true }, (error, collection) => {
 return collection;
});
participants.rawCollection().rename('socialize:participants', { dropTarget: true }, (error, collection) => {
 return collection;
});
posts.rawCollection().rename('socialize:posts', { dropTarget: true }, (error, collection) => {
 return collection;
});
friends.rawCollection().rename('socialize:friends', { dropTarget: true }, (error, collection) => {
 return collection;
});
requests.rawCollection().rename('socialize:requests', { dropTarget: true }, (error, collection) => {
 return collection;
});

Second let’s upgrade our profiles:

// get all profiles
const profiles = ProfilesCollection.find({}).fetch();
// remove all of them
ProfilesCollection.remove({});
ProfilesCollection.rawCollection().dropIndex({ userId: 1 });
// insert them all back in with new id
profiles.forEach((profile) => {
 const { userId, lastUpdate } = profile;
 ProfilesCollection.insert({
   ...profile,
   _id: userId,
   updatedAt: lastUpdate
 });
});

As you can see the profiles are now 1 to 1 relations to users. This means that you need to change how you look up profiles (from userId to _id).Finally let’s make the changes to the remaining socialize collections and our own collections:

const likesComments = { _likeCount: 'likeCount', _commentCount: 'commentCount' };
const date = { date: 'createdAt' };
// for collections that have likes and comments
BlogPostsCollection.rawCollection().update({}, { $rename: likesComments }, { multi: true });
// for socialize collections
PostsCollection.rawCollection().update({}, {
 $rename: {
   _likeCount: 'likeCount',
   _commentCount: 'commentCount',
   date: 'createdAt',
   type: 'objectType',
   userId: 'linkedObjectId'
 }
}, { multi: true });
// conversations
ConversationsCollection.rawCollection().update({}, { $rename: date }, { multi: true });
// messages
MessagesCollection.rawCollection().update({}, { $rename: date }, { multi: true });
// participants
ParticipantsCollection.rawCollection().update({}, { $rename: date }, { multi: true });
// comments
CommentsCollection.rawCollection().update({}, { $rename: date }, { multi: true });
// requests
RequestsCollection.rawCollection().update(
 {},
 {
   $rename: {
     date: 'createdAt',
     denied: 'deniedAt',
     ignored: 'ignoredAt'
   }
 },
 { multi: true }
);

Update API calls

There have also been some changes in the API. Most notably around requests.If you are using the friendship package make sure to update the name of functions as seen in the API docs.

Take advantage of new functionality

Now that everything is upgraded we can take advantage of new functionality.For starters publications are back. If you have been with socialize for a while you know that publications used to be baked into the packages, but were removed for a while. With v1, some of these publications are now back if you wish to make use of them. Like everything with v1 they are namespaced so they will not conflict with your existing.The biggest feature addition is the optional use of reddis-oplog. This is especially useful if you are growing and need to speed up or are already using it. You should get the most out of it in the messaging package.