Blog Details

Organize your Javascript code in Rails with Object literal pattern

Sometimes it becomes very hard when you are working on a web application framework like Rails and your front end contains lot of Javascript functions. There are lot of functions common between different view files or helpers used inside functions itself.

So in this tutorial, I am going to show you, how can we utilize Javascript object literal pattern to make your Javascript function code more organized and reusable. With this pattern, your code will be more manageable and easy to debug.

First of all you have to create a custom Javascript file. Let’s say we have Blogging website and in it, we have a view file called Posts/index.html.erb so I created a Javascript file posts.js and defined an variable object Post in it.

Post = {}

Now all relevant functions, variables or any configurations will be part of this main object.

Let’s say we have two configurations cfg1 and cfg2 with some default value and can be accessible in all functions as well as can be overridden by other functions run time.

So, to write such configurations, use it like below:

Post = {
  config: {
    cfg1: 'default_val1',
    cfg2: 'default_val2'  
  }
}

Now, one more important thing is, this configurations should not be accessible directly, so we have to create a wrapper for this which is a getter method.

Also, other functions can set/change the value of this global configurations so we need a setter method as well.

Post = {
  config: {
    cfg1: 'default_val1',
    cfg2: 'default_val2'
  },
  
  setCfg1: function (value) {
    Post.config.cfg1 = value;
  },

  getCfg1: function () {
    Post.config.cfg1;
  },

  setCfg2: function (value) {
    Post.config.cfg2 = value;
  },

  getCfg2: function () {
    Post.config.cfg2;
  }
}

Now, let’s say you want to bind some events on a specific element of your form or somewhere in UI. And you want to do this on turbolink load or when your DOM is ready.

So in this case, you should cretae init() in your object.

Post = {
  config: {
    cfg1: 'default_val1',
    cfg2: 'default_val2'
  },
  
  init: function () {
    Post.bindClickWithMe();
    Post.bindHoverWithMe();
  },
  
  setCfg1: function (value) {
    Post.config.cfg1 = value;
  },

  getCfg1: function () {
    Post.config.cfg1;
  },

  setCfg2: function (value) {
    Post.config.cfg2 = value;
  },

  getCfg2: function () {
    Post.config.cfg2;
  },
  
  bindClickWithMe: function () {
    // your function definition goes here...
  },
  
  bindHoverWithMe: function (){
    // your function definition goes here...
  }
}

Now you can define all the other functions which you want to be called upon certain actions or intervals. Also, let’s say you have some functions which are private and no need to access outside. To indicate this, you just need to add “_” (underscore) in the beginning of the function name. That just indicates the function is private though it is accessible but just for proper naming convention.

Post = {
  config: {
    cfg1: 'default_val1',
    cfg2: 'default_val2'
  },
  
  init: function () {
    Post.bindClickWithMe();
    Post.bindHoverWithMe();
  },
  
  setCfg1: function (value) {
    Post.config.cfg1 = value;
  },

  getCfg1: function () {
    Post.config.cfg1;
  },

  setCfg2: function (value) {
    Post.config.cfg2 = value;
  },

  getCfg2: function () {
    Post.config.cfg2;
  },
  
  bindClickWithMe: function () {
    // your function definition goes here...
  },
  
  bindHoverWithMe: function () {
    // your function definition goes here...
  },
  
  fnUsesPrivateFunction: function () {
    Post._myPrivateFunction(1,2);
  },
  
  _myPrivateFunction: function (a, b) {
    console.log(a);
    console.log(b);
  }
}

Once you have this whole file is ready, you can use them in your view files like below:

Post.init() // On document ready or turbolink load event call it
Post.fnUsesPrivateFunction() // call it as per the need

So the above version is the complete set of conventions. Always try to maintain the order of functions which is,

1. Configurations : config

2. Initialize bindings: init

3. Setter/getter methods

4. Other functions

5. Private functions

These are just conventions and can be changed according to your convenience but it would be better if you follow this. It will make your code more manageable and reusable!

Hope you enjoyed the article! Keep coding!