A Guide to Building Meteor Apps for Rails Developers

Snippet Ruby on Rails Meteor JavaScript

Last updated Mar 23, 2016

For the last 5 years, the majority of my consulting work has involved Ruby on Rails projects, paired with a variety of frontend JS frameworks. I use Rails conventions so often that they often pop up in my dreams alongside whale sharks and the sphinx. After deciding to open-source a custom icon font that we use for internal projects, I decided I needed a JavaScript platform that could build a quick demo. Meteor has been on my radar for a while and I was excited to give it a shot in a real project. Though it hardly represents the framework’s true superpowers, you can see the final Meteor app in action action.

As things got rolling, I often found myself wondering… Ok, I know how to do this in rails, but how does this work in Meteor? This lesson is going to cover some of the most common tasks in rails and show you how to replicate them in Meteor.

Lesson Checkpoints

0. First, the Striking Contrasts

How is Meteor different than Rails?

  • Full Stack Javascript: Meteor is built on NodeJS, so get comfortable coding in JavaScript.
  • WebSockets: Meteor apps open a realtime connection between the client and server. When data changes in your database, it is instantly reflected on the client side. (Note: Rails 5 has integrated ActionCable websockets, but it uses a much different architectural stack.)
  • NoSQL: MongoDB is way more fun than SQL. Way more…
  • Optimistic UI: Meteor can predict the future. See section 1.

1. Fetching and Modifying Data from the Server

This is probably the most fundamental responsibility of anything that calls itself a web app. Rails and Meteor take a significantly different approach to interacting with data. 

The Rails Way is RESTful

When the client triggers a controller action from the view, it will start the RESTful (GET, POST, PUT, DELETE) cycle. (1) Client Request  (2) Server Grinds (3) Server Responds.

posts_controller.rb

def create
  @post = Post.new(params)
  @post.save!
end

This is great for many web apps, but you’re stuck waiting for a server response after every post. Even when using AJAX, this can be too slow for modern web users.

The Meteor Way is OpenSockets

In meteor, you tell the server to publish data, then tell the client to subscribe to it. When you do this, meteor creates a miniature MongoDB instance ported to JavaScript that is stored in the client’s memory. Because it is in memory, it will respond at the speed of light. When the client makes a request, it will draw from the in-memory DB first, then the actual server will respond and make changes if necessary - this is known as an Optimistic UI. Think of miniMongo as a crystal ball that will provide an instant prediction when asked, but then correct itself if the future turns out different.

Let’s say we have a user that wants to view some posts.

server.js

Meteor.publish("Posts", function(){
  return Posts.find({});
});

client.js

Meteor.subscribe("Posts");

Template.example.helpers({
    posts: function () {
      return Posts.find({});
    }
});


example.html


{{#each posts}}
  {{title}}
{{/each}}

Think of the server as a waterfall and the client as a thirsty hiker. Published data is constantly flowing, the client just needs to subscribe to it.

The publish and subscribe concept can be a bit befuddling, so do yourself a favor and check out this Discover Meteor article.

2. URL Routing

Applications need a logical routing structure to make sense in a web browser. If you have content that needs to be indexed in search engines, a well-formatted URL is essential.

The Rails Way

Routing is dead simple in rails. This modest line of code gives you an entire set of URLs and HTTP verbs for resource. As long as you follow the naming conventions in your app’s view directory, rails will render out the view in to browser to the appropriate URL.

routes.rb

resources :posts

The Meteor Way

As learned in section one, Meteor apps don’t need rely on REST, so routing is not included in the core package. We can add a powerful router with the Iron Router Package. Packages in Meteor are the equivalent to Gems in Rails. Expect routing to be much more verbose by comparison, but you can achieve the same client-side structure that you can with rails. On the plus side, you usually only need routes for actions that produce GET requests in rails.

Note: You can generate RESTful routes with iron router if needed, useful for webhooks that rely on specific HTTP verbs.

command line

meteor add iron-router

router.js


Router.route('/posts', function () {
  this.render('Posts');
});

Router.route('/post/:_id', function () {
  this.render('Post');
});

Router.route('/posts/new', function () {
  this.render('PostNew');
});

// and so on…

3. Callbacks when Making Changes to the Database

Chances are high that you will need to denormalize some data before it saving it. For example, let’s say we want to programmatically create a url permalink before a new post is created (or inserted in MongoDB).

The Rails Way

Rails has this really useful library called ActiveRecord, which allows all sorts of database hooks out of the box. This makes it easy to modify data at any stage in the commit process.

models/post.rb

before_create :generate_peralink

def permalink
  self.permalink = 'hello-world'
end

The Meteor Way

In meteor, there is a popular package for running collection hooks that works just like ActiveRecord.

command line

meteor add matb33:collection-hooks

collections.js

var posts = new Mongo.Collection(“posts”);

posts.before.insert(function (userId, doc) {
  doc.permalink = 'hello-world';
});

4. Validating Data

In Meteor, you will be using MongoDB, which is a NoSQL database. This means we can change the database schema/structure on the fly, but that’s not desirable when we need to have rigid data standards.

The Rails Way

Again using ActiveRecord, we have a library for validations in the model layer. The validation below verifies that a post’s title does not exceed 15 characters.

models/post.rb

validates :title, length: { maximum: 15 }

The Meteor Way

Our data can be validated by defining an explicit schema with the simple-schema package. I actually find it pretty useful to have all your data validations in a manifest-style file like this.

collections.js

PostSchema = new SimpleSchema({
  title: {
    type: String,
    label: "Title",
    max: 15
  },
  body: {
    type: String,
    label: "Body",
    min: 100
  }
});

5. Managing Environment Variables

When deploying an app to production or to a public repo, you need to keep your sensitive information, such as API keys, hidden from hackers. In both examples below, you should always remember to keep these files out of public repos.

The Rails Way

In rails, you’ve probably used the figaro gem to manage sensitive environment variables.

application.yml


MY_API_KEY = 'foo'

Then you access it throughout your rails app by calling Figaro.env.MY_API_KEY

The Meteor Way

In meteor, you can create a settings.json file in the root directory to hold API keys. For all intents and purposes, it works just like Figaro.

settings.json


{
  "MY_API_KEY" : "foo"
}

Then you can call Meteor.settings.MY_API_KEY

6. Setting a Default HTML Title

One of the first things I remember learning in rails was how to create a default title in Michael Hartl’s tutorial. It went something like this:

The Rails Way

application_helper.rb

module ApplicationHelper
  def page_title(title)
    if title.empty?
      "CodeDiode | Ideas for Web Development"
    else
      title
    end
  end
end

application.html.erb

<title><%= page_title(yield(:title)) %></title>
<% content_for :title, “Sea Turtles are Rad” %>

The Meteor Way

In meteor, you can register a global helper that will be available in any template. Then its just a matter of passing a string to this helper directly from the template and updating the page title with JavaScript. 

client.js

Template.registerHelper("pageTitle", function(title) {
 if ( title )
    document.title = title;
 } else {
    document.title = "CodeDiode | Ideas for Web Development";
 }
});

any_template.html


<template name="anyTemplate">
  {{pageTitle 'Dolphins are the Bomb'}}
</template>

7. Deployment to the Cloud

You've finished building your app... Now where do you put it for the world to see? 

The Rails Way

Heroku has been the de facto official cloud PaaS solution for rails apps for as long as I’ve been involved. Pushing your app to production is as easy as..

command line

$ git push heroku master
$ heroku run rake db:migrate

The Meteor Way

Meteor recently launched its own PaaS, appropiately named Galaxy. Just like Heroku, Galaxy provides the most desired features, like one-click deployment from the command line, instant scaling, and realtime analytics. It’s not nearly as mature or feature-rich as Heroku, but it has just enough to get the job done.

command line

$ DEPLOY_HOSTNAME=galaxy.meteor.com meteor deploy –settings settings.json 

The one glaring issue with meteor deployment is that you must also host a MongoDB database from another provider, such as MLab. They provide a free tier, but it is still annoying to manage moving parts separately. That aside, Galaxy is a very slick solution to quickly get your app to production.

Comments