Upgrading to Meteor Socialize 1.0

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.

<h3>Simple schema <p dir="auto">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 <a href="https://github.com/aldeed/meteor-simple-schema/blob/master/CHANGELOG.md#200" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">changelog. Here I will only cover the basics. First we need to add the new npm package: <p dir="auto"><code>meteor npm install --save simpl-schema <p dir="auto">This means that we need to change imports in filed where we use simple schema to: <p dir="auto"><code>import SimpleSchema from 'simpl-schema' <p dir="auto">You will have to replace your arrays declarations from: <p dir="auto"><code>{ foo: { type: [String] } } <p dir="auto">to this: <p dir="auto"><code>{ foo: { type: Array }, 'foo.$': { type: String } } <h3>Get the new packages <p dir="auto">First let’s start by getting the new versions of packages: <pre><code>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 <p dir="auto">Note here that <code>socialize:feed has been replaced by <code>socialize:postable , so make sure to remove it so that you don’t get conflicts. <h3>Update your collections <p dir="auto">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): <pre><code>import { Mongo } from ‘meteor/mongo’;<br /> import SimpleSchema from ‘simpl-schema’;<br /> import { BaseModel } from ‘meteor/socialize:base-model’;<br /> import { LikeableModel } from ‘meteor/socialize:likeable’;<br /> import { CommentableModel } from ‘meteor/socialize:commentable’;<br /> import { LinkableModel } from ‘meteor/socialize:linkable-model’; <pre><code>export const BlogPostsCollection = new Mongo.Collection(‘blog_posts’); <pre><code>const BlogPostSchema = new SimpleSchema({<br />  blogId: {<br />    type: String,<br />    regEx: SimpleSchema.RegEx.Id,<br />    denyUpdate: true,<br />    index: true<br />  },<br />  author: {<br />    type: String,<br />    regEx: SimpleSchema.RegEx.Id,<br />    denyUpdate: true,<br />    index: true,<br />    autoValue() {<br />      if (this.isInsert)<br />        return Meteor.userId();<br />    }<br />  },<br />  ...<br /> }); <pre><code>export class BlogPost extends CommentableModel(LikeableModel(BaseModel)) {} <pre><code>BlogPost.attachCollection(BlogPostsCollection); <pre><code>BlogPost.attachSchema(BlogPostSchema);<br /> BlogPost.attachSchema(CommentableModel.CommentableSchema);<br /> BlogPost.attachSchema(LikeableModel.LikeableSchema); <pre><code>LinkableModel.registerParentModel(BlogPost); <p dir="auto">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. <pre><code>Meteor.blogPosts.findOne(); <p dir="auto">Instead you will have to import the collection. <pre><code>import BlogPosts from '../lib/blogPosts.js'; <pre><code>BlogPosts.findOne(); <p dir="auto">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: <pre><code>import { MessagesCollection, ConversationsCollection } from 'meteor/socialize:messaging'; <h3>Update how you call your collections <p dir="auto">A big breaking change is that collections are no longer referenced in the Meteor object.So where in the past you could do: <pre><code>Meteor.blog.findOne(); <p dir="auto">Now you have to import the required collection and call it like you would in plain Meteor: <pre><code>import { BlogsCollection } from '../lib/collections'; <pre><code>BlogsCollection.findOne(); <h3>Migrating DB <p dir="auto">Some parameters have also been renamed. To make it easier here is a simple migration script that you can run (I recommend using the <a href="https://atmospherejs.com/percolate/migrations" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">percolate:migrations package for this task).First of let’s rename the old socialize collection to the new namespace: <pre><code>// establish the old socialize collections<br /> const profiles = new <em>Mongo.<em>Collection('profiles');<br /> const blocks = new <em>Mongo.<em>Collection('blocks');<br /> const comments = new <em>Mongo.<em>Collection('comments');<br /> const conversations = new <em>Mongo.<em>Collection('conversations');<br /> const messages = new <em>Mongo.<em>Collection('messages');<br /> const participants = new <em>Mongo.<em>Collection('participants');<br /> const posts = new <em>Mongo.<em>Collection('posts');<br /> const friends = new <em>Mongo.<em>Collection('friends');<br /> const<strong> requests = new<strong> <em>Mongo.<em>Collection('requests');<br /> // rename them<br /> profiles.rawCollection().rename('socialize:profiles', { dropTarget: true }, (error, collection) => {<br />  return collection;<br /> });<br /> blocks.rawCollection().rename('socialize:blocks', { dropTarget: true }, (error, collection) => {<br />  return collection;<br /> });<br /> comments.rawCollection().rename('socialize:comments', { dropTarget: true }, (error, collection) => {<br />  return collection;<br /> });<br /> conversations.rawCollection().rename('socialize:conversations', { dropTarget: true }, (error, collection) => {<br />  return collection;<br /> });<br /> messages.rawCollection().rename('socialize:messages', { dropTarget: true }, (error, collection) => {<br />  return collection;<br /> });<br /> participants.rawCollection().rename('socialize:participants', { dropTarget: true }, (error, collection) => {<br />  return collection;<br /> });<br /> posts.rawCollection().rename('socialize:posts', { dropTarget: true }, (error, collection) => {<br />  return collection;<br /> });<br /> friends.rawCollection().rename('socialize:friends', { dropTarget: true }, (error, collection) => {<br />  return collection;<br /> });<br /> requests.rawCollection().rename('socialize:requests', { dropTarget: true<strong> }, (error, collection) => {<br />  return<strong> collection;<br /> }); <p dir="auto">Second let’s upgrade our profiles: <pre><code>// get all profiles<br /> const profiles = ProfilesCollection.find({}).fetch();<br /> // remove all of them<br /> ProfilesCollection.remove({});<br /> ProfilesCollection.rawCollection().dropIndex({ userId: 1 });<br /> // insert them all back in with new id<br /> profiles.forEach((profile) => {<br />  const { userId, lastUpdate } = profile;<br />  ProfilesCollection.insert({<br />    ...profile,<br />    _id: userId,<br />    updatedAt: lastUpdate<br />  });<br /> }); <p dir="auto">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: <pre><code>const likesComments = { _likeCount: 'likeCount', _commentCount: 'commentCount' };<br /> const date = { date: 'createdAt' }; <pre><code>// for collections that have likes and comments<br /> BlogPostsCollection.rawCollection().update({}, { $rename: likesComments }, { multi: true }); <pre><code>// for socialize collections<br /> PostsCollection.rawCollection().update({}, {<br />  $rename: {<br />    _likeCount: 'likeCount',<br />    _commentCount: 'commentCount',<br />    date: 'createdAt',<br />    type: 'objectType',<br />    userId: 'linkedObjectId'<br />  }<br /> }, { multi: true });<br /> // conversations<br /> ConversationsCollection.rawCollection().update({}, { $rename: date }, { multi: true });<br /> // messages<br /> MessagesCollection.rawCollection().update({}, { $rename: date }, { multi: true });<br /> // participants<br /> ParticipantsCollection.rawCollection().update({}, { $rename: date }, { multi: true });<br /> // comments<br /> CommentsCollection.rawCollection().update({}, { $rename: date }, { multi: true });<br /> // requests<br /> RequestsCollection.rawCollection().update(<br />  {},<br />  {<br />    $rename: {<br />      date: 'createdAt',<br />      denied: 'deniedAt',<br />      ignored: 'ignoredAt'<br />    }<br />  },<br />  { multi: <strong>true }<br /> ); <h3>Update API calls <p dir="auto">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 <a href="https://github.com/copleykj/socialize-friendships/blob/devel/API.md" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">API docs. <h3>Take advantage of new functionality <p dir="auto">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 <a href="https://atmospherejs.com/cultofcoders/redis-oplog" target="_blank" rel="nofollow noreferrer noopener" title="This link will take you away from hive.blog" class="external_link">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.