Performance Optimisations on a Rails App

Method Missing Method Missing is one of the concepts of metaprogramming ruby. Although metaprogramming is very powerful it too has some shortcomings especially speed. A normal method is comparatively 1.5x times faster than a missing method. One of our users complained about our calendar page being very slow - on inspecting we found request was taking more than 30 seconds for loading the month view of the calendar and eventually request timed out. The user had lots of activities on that calendar - 2000+. On further inspection, we found our DB query was quite fast but each activity was

Password protect PDFs

In one of our Rails application, we needed to generate password protected PDFs. We used wicked_pdf (an awesome gem that generates PDFs from HTML template) to generate PDFs but it doesn't provide feature to secure it. While searching for solution to secure PDFs we came across PDFtk (PDF toolkit). It is a cross-platform tool for manipulating PDF documents. It has feature to add password to PDF document using "user password" as well as "master password" (owner password) which is great. Installing PDFtk You need to install "PDFtk Server" which is a command-line tool

Adding new column with default value to high volume database table

Almost all Ruby on Rails developers might come across scenario where they need to add a new column with a default value to one of the database tables. Most of us (including me) would write following migration statement - add_column :table_name, :column_name, :boolean, default: false This is a good practice but would cause downtime if the table has large number of records. It took 3 secs when I ran the migration for a table having 50k records. -- add_column(:table_name, :column_name, :boolean, {:default=>false}) -> 3.3695s 3 secs is a long

Referencing Rails Assets in Javascript / CoffeeScript files

Sometimes you’ll want to refer to your image assets from inside of your JavaScript or CoffeeScript files. We have nice rails helpers that would allow us to do so but we need to append .erb to every .js or .coffee file we want to reference images. I didn’t like it that way, because ERB inside of CoffeeScript looks odd and having the file end with .erb messes up syntax highlighting. A way around this is by adding following piece of code (not the beautiful one) to one single file that ends on .erb (i.e. js_assets.js.

Communicating with Sendgrid V3 API

Sendgrid provides email service which we can use for sending emails from our app and we can even track every details of any email sent through our Sendgrid account like whether it is delivered, opened, dropped and details of unsubscribed email addresses etc. There are also API endpoints provided by Sendgrid to access user subscribe/unsubscribe related data and email event data with respect to emails sent through your sendgrid account for which documentation link is provided at bottom. To understand this lets go through simple example to fetch sendgrid subscription groups data from your sendgrid account - Generate API

Adding Custom Search Bar To ActiveAdmin

Active Admin is a great plugin that helps us to get administration functions with elegant and simple interface up and live quickly without much of a hassle or efforts. One can also make use of various customisations as per their need with very little effort. In this article, I will be explaining how we can add custom search bar in Active Admin. Adding custom search bar is not as easy and straight forward as other Active Admin customisations. I will be making use of jQuery to do this. Here, I will be taking an example of searching resources with tags

Dynamic Ruby

Ruby is too dynamic. We can do almost anything in runtime, from creating the classes at runtime to creating methods dynamically. If you are coming from some other language, it would be shocking for you too know that nothing is private in ruby. You can access private and protected method from anywhere you want. You can call this a flexibility or a curse. But a smart developer knows when to utilize the power of extreme flexibility that Ruby provides and when to stay away from it. Is this all Ruby can do in terms of flexibility? Definitely not. Ruby have

Javascript Browser Window Operations in Rails

Recently we developed one feature where we wanted to present a new tab view for an existing smaller form interface whereby users can use the full screen of the new window to move around and use the feature with ease. While we were developing the feature, we came across few challenges and thereby few learnings which we thought would be good to share. 1. Caching existing values. We have around 8-9 forms from where we can use this feature but each of them have different implementation based on the requirement. So before we open the new tab - we wanted

first_or_create caches the existing scope and applies to the model callbacks

We were debugging one issue in our application which was caching the scope we had in where clause for first_or_create in model callbacks - and found one interesting issue - Theconditions in the where clause were cached in after_create callback if we use where().first_or_create, please check example below - Example: Contact.where(first_name: 'Kiprosh').first_or_create Contact Model: after_create :sanitize def sanitize Contact.where(creator_id: 123).solr_index end This should fire Contact.where(creator_id: 123) but instead fires Contact.where(first_name: 'Kiprosh', creator_id: 123) On further

Delayed job object serialization and deserialization issue

Recently in one of our project there was a requirement to send SMS notification to users and task was to perform this functionality as background job using delayed job service. I wrote following code for sending SMS notifications to user and it was working fine. Then I just did one liner change in my code to process send_sms method asynchronously using handle_asynchronously method of delayed job and thought it will work as expected. attr_reader :client, :sender, :recepient, :message def initialize(recipient_ph_number, message_details) @client = ACCOUNT_SID, AUTH_TOKEN @sender = TWILIO_PHONE_