How constant lookup and resolution works in Ruby on Rails

When a Rails application involving multiple gems, engines etc. are built then it’s important to know how constants are looked up and resolved.

Consider a brand new Rails app with model User.

class User
  def self.model_method
    'I am in models directory'

Run User.model_method in rails console. It runs as expected.

Now add file user.rb in lib directory.

class User
  def self.lib_method
    'I am in lib directory'

Reload rails console and try executing User.model_method and User.lib_method. You will notice that User.model_method gets executed and User.lib_method doesn’t. Why is that?

In Rails we do not import files

If you have worked in other programming languages like Python or Java then in your file you must have statements to import other files. The code might look like this.

import static com.googlecode.javacv.jna.highgui.cvCreateCameraCapture;
import static com.googlecode.javacv.jna.highgui.cvGrabFrame;
import static com.googlecode.javacv.jna.highgui.cvReleaseCapture;

In Rails we do not do that. That’s because DHH does not like the idea of opening a file and seeing the top of the file littered with import statements. He likes to see his files beautiful.

Since we do not import file then how does it work?

In Rails console when user types User then rails detects that User constant is not loaded yet. So it needs to load User constant. However in order to do that it has to load a file. What should be the name of the file. Here is what Rails does. Since the constant name is User Rails says that I’m going to look for file user.rb.

So now we know that we are looking for user.rb file. But the question is where to look for that file. Rails has autoload_path. As the name suggests this is a list of paths from where files are automatically loaded. Rails will search for user.rb in this list of directories.

Open Rails console and give it a try.

$ rails console
Loading development environment (Rails 4.2.1)
irb(main):001:0> ActiveSupport::Dependencies.autoload_paths
=> ["/Users/nsingh/code/bigbinary-projects/wheel/app/assets",

As you can see in the result one of the folders is app/models. When Rails looks for file user.rb in app/models then Rails will find it and it will load that file.

That’s how Rails loads User in Rails console.

Adding lib to the autoload path

Let’s try to load User from lib directory. Open config/application.rb and add following code in the initialization part.

config.autoload_paths += ["#{Rails.root}/lib"]

Now exit rails console and restart it. And now lets try to execute the same command.

$ rails console
Loading development environment (Rails 4.2.1)
irb(main):001:0> ActiveSupport::Dependencies.autoload_paths
=> ["/Users/nsingh/code/bigbinary-projects/wheel/app/lib",

Here you can see that lib directory has been added at the very top. Rails goes from top to bottom while looking for user.rb file. In this case Rails will find user.rb in lib and Rails will stop looking for user.rb. So the end result is that user.rb in app/models directory would not even get loaded as if it never existed.

Enhancing a model

Here we are trying to add an extra method to User model. If we stick our file in lib then our user.rb is never loaded because Rails will never look for anything in lib by default. If we ask Rails to look in lib then Rails will not load file from app/models because the file is already loaded. So how do we enhance a model without sticking code in app/models/user.rb file.

Introducing initializer to load files from model and lib directories

We need some way to load User from both models and lib directories. This can be done by adding an initializer to config/initializers directory with following code snippet

%w(app/models lib).each do |directory|
  Dir.glob("#{Rails.root}/#{directory}/user.rb").each {|file| load file}

Now both User.model_method and User.lib_method get executed as expected.

In the above case when first time user.rb is loaded then constant User gets defined. Second time ruby understands that constant is already defined so it does not bother defining it again. However it adds additional method lib_method to the constant.

In that above case if we replace load file with require file then User.lib_method will not work. That is because require will not load a file if a constant is already defined. Read here and here to learn about how load and require differ.

Using ‘require_relative’ in model

Another approach of solving this issue is by using require_relative inside model. require_relative loads the file present in the path that is relative to the file where the statement is called in. The desired file to be loaded is given as an argument to require_relative

In our example, to have User.lib_method successfully executed, we need to load the lib/user.rb. Adding the following code in the beginning of the model file user.rb should solve the problem. This is how app/models/user.rb will now look like.

require_relative '../../lib/user'

  class User
    def self.model_method
      'I am in models directory'

Here require_relative upon getting executed will first initialize the constant User from lib directory. What follows next is opening of the same class User that has been initialized already and addition of model_method to it.

Handling priorities between Engine and App

In one of the projects we are using engines. SaleEngine has a model Sale. However Sale doesn’t get resolved as path for engine is neither present in config.autoload_paths nor in ActiveSupport::Dependencies.autoload_paths. The initialization of engine happens in engine.rb file present inside lib directory of the engine. Let’s add a line to load engine.rb inside application.rb file.

require_relative "../sale_engine/lib/sale_engine/engine.rb"

In Rails console if we try to see autoload path then we will see that lib/sale_engine is present there. That means we can now use SaleEngine::Engine.

Now any file we add in sale_engine diretory would be loaded. However if we add user.rb here then the user.rb mentioned in app/models would be loaded first because the application directories have precedence. The precedence order can be changed by following statements.

engines = [SaleEngine::Engine] # in case there are multiple engines
config.railties_order = engines + [:main_app]

The symbol :main_app refers to the application where the server comes up. After adding the above code, you will see that the output of ActiveSupport::Dependencies now shows the directories of engines first (in the order in which they have been given) and then those of the application. Hence for any class which is common between your app and engine, the one from engine will now start getting resolved. You can experiment by adding multiple engines and changing the railties_order.

Further reading

Loading of constants is a big topic and Xavier Noria from Rails core team has made some excellent presentations. Here are some of them

We have also made a video on How autoloading works in Rails.

Using Stripe API in React Native with fetch

Stripe makes it easy to accept payments online. Stripe offers an npm package with nice documentation.

Problem with using Stripe in React Native

I added stripe to my React Native application using following command.

npm install stripe --save

Added Stripe to the project as shown below.

var stripe = require('stripe')('stripe API key');

And now I’m getting following error.

could not mount

This’s because npm package uses stripe.js and stripe.js needs http provided by Node.JS.

Our React Native code does not actually run on Node.JS. I know while building React Native we use NPM and we have a node server running in the background so it feels like we are in Node.JS land and we can use everything Node.JS has to offer. But that’s not true. React Native code can’t depend on Node.JS because Node.JS is not shipped with ios. It means we can’t use any of Node.JS packages including http. It means we can’t use stripe npm module.

Now you can remove the require('stripe') line that was added in the last step.


React Native comes with Fetch api. From the documentation

The Fetch API provides a JavaScript interface for accessing an manipulating parts of the HTTP pipeline, such as requests and responses. It also provides a global fetch() method that provides an easy, logical way to fetch resources asynchronously across the network.

stripe.js is a nice wrapper around stripe api. stripe api is very well documented and is easy to use. Since we cant use the stripe.js we will use stripe api.

We will use fetch to create a credit card token using api.

return fetch('', {
  method: 'post',
  headers: {
    'Accept': 'application/json',
    'Content-Type': 'application/x-www-form-urlencoded',
    'Authorization': 'Bearer ' + '<YOUR-STRIPE-API-KEY>'
  body: formBody

Here, the header has 3 keys. Lets go through them one-by-one:

  • 'Accept': 'application/json' : Designates the content to be in JSON format.
  • 'Content-Type': 'application/x-www-form-urlencoded' : This tells the endpoint that the payload will be one giant query string where name and value pairs will be separated by the ampersand.
  • 'Authorization': 'Bearer ' + '<YOUR-STRIPE-API-KEY>' : This key is to authorize our actions on Stripe. Here Bearer is just a prefix which we need to attach to the api-key because Stripe uses OAuth 2.0 . You can read more on the Bearer token usage here .

Payload needs to contain credit card details.

var cardDetails = {
  "card[number]": '1111 2222 3333 4444',
  "card[exp_month]": '01',
  "card[exp_year]": '2020',
  "card[cvc]": '123'

Since the Content-Type is application/x-www-form-urlencoded, the paylod should be one query string. An example of this would be: city=Miami&state=Florida

Let’s prepare a proper payload.

var formBody = [];
for (var property in cardDetails) {
  var encodedKey = encodeURIComponent(property);
  var encodedValue = encodeURIComponent(cardDetails[property]);
  formBody.push(encodedKey + "=" + encodedValue);
formBody = formBody.join("&");

That’s it. Now we can attach formBody to the body part of the fetch request and we are good to go.

Final solution

Here’s the whole code snippet.

"use strict";

var stripe_url = ''
var secret_key = '<YOUR-STRIPE-API-KEY>'

module.exports.createCardToken = function (cardNumber, expMonth, expYear, cvc) {
  var cardDetails = {
    "card[number]": cardNumber,
    "card[exp_month]": expMonth,
    "card[exp_year]": expYear,
    "card[cvc]": cvc

  var formBody = [];
  for (var property in cardDetails) {
    var encodedKey = encodeURIComponent(property);
    var encodedValue = encodeURIComponent(cardDetails[property]);
    formBody.push(encodedKey + "=" + encodedValue);
  formBody = formBody.join("&");

  return fetch(stripe_url + 'tokens', {
    method: 'post',
    headers: {
      'Accept': 'application/json',
      'Content-Type': 'application/x-www-form-urlencoded',
      'Authorization': 'Bearer ' + secret_key
    body: formBody

This is an example of registering a credit card with stripe and getting the token. Similar implementations can be done for other API endpoints.

Rails 5 allows setting custom HTTP Headers for assets

Let’s look at by default what kind of response headers we get when we start with a brand new Rails 4.2.4 application.


Now let’s say that I want to set a custom response header. That’s easy. All I need to do is add following line of code in the controller.

response.headers['X-Tracking-ID'] = '123456'

Now I see this custom response header.


Setting custom response header for assets

Let’s say that I need that custom response header not only for standard web requests but also for my assets. For example application.js file is served by Rails in localhost. How would I set custom header to the asset being served by Rails here.

Actually that’s not possible in Rails 4. In Rails 4 we can set only one response header for assets that are served by Rails and that response header is Cache-Control.

Here is how I can configure Cache-Control for assets.

# open config/environments/production.rb and add following line
config.static_cache_control = 'public, max-age=1000'

Now we have modified ‘Cache-Control` header for the assets.


Besides Cache-Control no other respone header can be set for assets served by Rails. That’s a limitation.

How Rails Apps lived with this limitation so far

Rails is not the best server to serve static assets. Apace and NGINX are much better at this job. Hence ,in reality, in production almost everyone puts either Apache or NGINX in front of a Rails server and in this way Rails does not have to serve static files.

Havig said that, Rails applications hosted at Heroku is an exception. Assets for Rails applilcations running at Heroku are served by Rails application itself.

Problem we ran into

Our website is hosted at heroku. When we ran Google page speed insights for our website we were warned that we were not using Expires header for the assets.

PageSpeed Insights Warning

Here are how the header looked for application.js.

PageSpeed Insights Warning

Now you see the problem we are running into.

  • Our application is hosted at Heroku.
  • Heroku lets Rails serve the assets.
  • Google page speed insights wants us to set Expires header to the assets.
  • Rails application allows only one header for the assets and that is ‘Cache-Control`.

One easy solution is to host our website at Digital Ocean and then use Apache or NGINX.

Rails 5 saves the day

Recently Rails merged basic support for access control headers and added ability to define custom HTTP Headers on assets served by Rails.

Behind the scenes, Rails uses ActionDispatch::Static middleware to take care of serving assets. For example, a request to fetch an image, goes through ActionDispatch::Static in the request cycle. ActionDispatch::Static takes care of serving Rack::File object from server with appropriate headers set in the response. The serverd image can have headers like Content-Type, Cache-Control.

Start using Rails master

To fix this, we first pointed the App to use Rails master.

gem 'rails', github: 'rails/rails'
gem 'rack', github: 'rack/rack' # Rails depends on Rack 2
gem 'arel', github: 'rails/arel' # Rails master works alongside of arel master.

Next, we changed asset configuration to start providing and using missing header for Expires.

# production.rb

config.public_file_server.headers = {
  'Cache-Control' => 'public, s-maxage=31536000, maxage=15552000',
  'Expires' => "#{1.year.from_now.to_formatted_s(:rfc822)}"

Here, we are first setting the Cache-Control header to use public (intermediate) caching, for a year (31536000 seconds) with maxage and s-maxage. Here s-maxage stands for Surrogate cache, which is used to cache internally by Fastly.

We then provide the missing Expires value with some future date in Internet formatted time value.

With this setup, we can see PageSpeed pickups the new headers on assets and does not warn us for the missing header.

PageSpeed Insights Warning

Here is the changed response header for asset.

PageSpeed Insights Warning

Further Reading

For better use and more details about different headers to use for the assets, please refer to RFC 2616.

Getting around Apple iTunesConnect account activation issue

It’s now 5 days since I talked to Apple support team and showed to them problem I was facing with activating my iTunesConnect account. So far I have not received any response from Apple.

And it’s not just me. A lot more people are facing the issue.

I’m sure one day Apple will fix this issue. In the meantime I’m posting how I got around this problem.

Migrating rails app from postgresql to sql server

We started development on a project with PostgreSQL as our database. However midway we had to switch to SQL Server for a variety of reasons.

Here are some of the issues we noticed while migrating to SQL Server.

Unique constraint on a column which has multiple NULL values

As per the ANSI SQL standard unique constraint should allow multiple NULL values.

PostgreSQL documentation on unique constraint states following.

In general, a unique constraint is violated when there is more than one row in
the table where the values of all of the columns included in the constraint are

However, two null values are not considered equal in this comparison.

That means even in the presence of a unique constraint it is possible to store
duplicate rows that contain a null value in at least one of the constrained

This behavior conforms to the SQL standard, but we have heard that
other SQL databases might not follow this rule. So be careful when developing
applications that are intended to be portable.

In SQL Server a unique constraint does not allow multiple NULL values.

Devise by default adds unique index on reset_password_token column.

add_index :users, :reset_password_token, :unique => true

Devise is doing the right thing by enforcing a unique index on reset_password_token so that when a user clicks on a link to reset password the application would know who the user is.

However here is the problem. If we add a new user then by default the value of reset_password_token is NULL. If we add another user then we have two records with NULL value in reset_password_token. This works in PostgreSQL.

But SQL Server would not allow to have two records with NULL in reset_password_token column.

So how do we solve this problem.

Partial index to rescue. It is also known as Filtered index. Both PostgreSQL and SQL server support it. Rails also supports partial index by allowing us to pass where option as shown below.

add_index :users, :reset_password_token,
                  unique: true,
                  where: 'reset_password_token IS NOT NULL'

Please visit this issue if you want to see detailed discussion on this topic.

This behavior of SQL Server comes in play in various forms. Let’s say that we are adding api_auth_token to an existing users table.

Typically a migration for that might look like as shown below.

add_column :users, :api_auth_token, :string,
                                    :null => true,
                                    :unique => true

In this case we have plenty of records in the users table so the above migration will fail in PostgreSQL. We will have to resort to usage of partial index to fix this issue.

Adding not null constraint on a column with an index

In PostgreSQL following case will work just fine.

add_column :users, :email, :string, :unique => true
change_column :users, :email, :null => false

Above migration will fail with SQL Server.

In SQL Server a “not null constraint” cannot be added on a column which has a index on it. We need to first remove the unique index, then add the “not null” constraint and then add the unique index back.

The other solution is to add not NULL constraint first in the migration and then add any index.

Serialize array into a string column

ActiveRecord supports Array Datatype for PostgreSQL. We were using this feature to store a list of IDs.

After switching to SQL server we converted the column into string type and serialized the array.

serialize :user_ids, Array

Configuring Pycharm IDE to run a Robot Framework test suite or a single test script

Pycharm is a convenient IDE to work with Robot framework. To run a test suite or a test script, one can do so only through console. Running tests through console is very demanding. If user can run tests from Pycharm itself then that helps improve productivity. This blog explains how to configure Pycharm to be able to run test suite or a single test from the IDE itself.

Configuration to run a single test script

pycharm robot 1 pycharm robot 2 pycharm robot 3

Running a single test script

pycharm robot 4

Configuration to run a particular test suite

pycharm robot 5

Running a particular test suite

pycharm robot 6

Optimize JavaScript code using BabelJS

Though Babel is a transpiler to convert ESNext code to ES5, it can be used to optimize the code as well.

Let’s say we want to convert following ES6 code using Babel.

let a = 10;
let b = 42;

if (a < b) {
  console.log("a is less than b");
} else {
  console.log("b is less than a");

It will get translated to:

"use strict";

var a = 10;
var b = 42;

if (a < b) {
  console.log("a is less than b");
} else {
  console.log("b is less than a");

All good so far. Let’s try Babel’s constant folding plugin. I am compiling the ES6 code from command line this time.

babel --plugins constant-folding index.js --out-file bundle.js -w

This gives us following output:

"use strict";

var a = 10;
var b = 42;

if (true) {
  console.log("a is less than b");
} else {
  console.log("b is less than a");

If condition changed from (a < b) to (true). The constant-folding plugin has smartly evaluated the conditional expression a < b and replaced the code with the result of that expression.

This plugin can also optimize other expressions as shown below.

// Unary operators

// Binary expression
console.log(20 + 22);

// Function calls
console.log(Math.min(91, 2 + 20));

Which gets optimized to:

// Unary operators

// Binary expression

// Function calls

How does this actually work?

Though we are using a “constant folding plugin” to achieve this optimization, the real work happens in Babel itself.

For every expression in the code, the constant folding plugin calls evaluate function from Babel source code. This function checks whether it can confidently find end value for a given expression.

The evaluate function returns confidence level and end value for any given expression. Based on this “confidence level”, constant folding plugin replaces the expression with their end values altering our original code as follows.

How evaluate handles different cases

For code Math.min(10, 20), evaluate will return

{ confident: true, value: 10 }

For code a < b, evaluate will return

{ confident: true, value: true }.

But for user defined function like foo('bar') or browser defined console.log('hello'), evaluate will return

{ confident: false, value: undefined }.

In the above case “confident” value will be “false” even if function returns a constant value. For example for code foo(100), evaluate will return

{ confident: false, value: undefined }.

In the above case function foo will always return 100. Still Babel has low confidence level. Why? That’s because Babel sees that it is a function and it bails out. It does not even look inside to try to figure things out.

Here is evaluate code in Babel. You should check it out.

How much optimization is possible?

How much help we will get from Babel for optimizing our code? Will it optimize everything?

The answer is unfortunately no.

As of now, Babel optimizes logical, binary, conditional expressions. It can also evaluate function calls on literals like "babel".length confidently if the literal is string or number.

For function calls, it supports only certain callees like String, Number and Math. So call to a user defined function, even if it’s returning a fixed value, will not be optimized.

Experimental feature

This feature looks great. But it’s available as experimental feature. If you use the plugin you will get following warning. unless you enable experimental flag.

$ babel --plugins constant-folding index.js --out-file bundle.js -w


In order to get rid of warning you need to pass --experimental flag like this.

$ babel --plugins constant-folding index.js --out-file bundle.js -w

Eliminating dead code

In above code example, we know that the result of if (a < b) is true based on values of a and b. Since the result is not going to change no matter what there is no need to have the if and else clauses.

That’s dead code.

Can Babel help us eliminate dead code?

Yes with the help of minification.deadCodeElimination option.

babel --optional minification.deadCodeElimination index.js --out-file bundle.js -w

Which converts earlier code to:

"use strict";

console.log("a is less than b");

I will talk about how Babel can eliminate dead code in a later post.