Solving 10 most common issues of Ruby on Rails

Being a Ruby on Rails developer for last 5 years, I realised that newbie/fellow developers who just started learning Ruby on Rails struggles with many issues which are pretty common and obvious. This post takes you through the most common issues and their resolution while learning RoR development.

Let’s see the most common issues that occur while application development.

1. PostgresQL: Can’t find the ​​’libpq-fe.h’ header while installing pg gem.

Building native extensions. This could take a while...
ERROR:  Error installing pg:
ERROR: Failed to build gem native extension.Can't find the 'libpq-fe.h header
*** extconf.rb failed ***
Could not create Makefile due to some reason, probably lack of
necessary libraries and/or headers.  
Check the mkmf.log file for more
details.  You may need configuration options.
Provided configuration options:
    --with-opt-dir
    --without-opt-dir
    --with-opt-include
    --without-opt-include=${opt-dir}/include
    --with-opt-lib
    --without-opt-lib=${opt-dir}/lib
    --with-make-prog
    --without-make-prog
    --srcdir=.
    --curdir
    --ruby=/home/u/.rvm/rubies/ruby-1.9.2-p0/bin/ruby
    --with-pg
    --without-pg
    --with-pg-dir
    --without-pg-dir
    --with-pg-include
    --without-pg-include=${pg-dir}/include
    --with-pg-lib
    --without-pg-lib=${pg-dir}/lib
    --with-pg-config
    --without-pg-config
    --with-pg_config
    --without-pg_config

Above error occurs while `gem install pg` or  `bundle install` with pg gem. It says that gem could not find required packages for successful installation.

Solution:

Installing required packages: pg gem needs libpq-dev package which can be installed as follows

Ubuntu: sudo apt-get install libpq-dev
Mac: brew install postgresql (with Homebrew)

Or install gem with include directory: if package is already installed and gem install is not able to locate it.

gem install pg -- --with-pg-include=path/to/postgres/include/directory 
Mac OS - include directory usually located in /usr/local/opt i.e. /usr/local/opt/postgresql\@9.5/include/
Ubuntu OS - include/config directory usually located in /etc/postgresql/9.x/*

2. PostgreSQL:  FATAL: Peer authentication failed for user “postgres”

Above error is because of database user postgres(default user) can’t be authenticated with the password provided in config/database.yml.

Solution:

Either you need to set the password for ‘postgres’ user or allow password less authentication for ‘postgres’ user from the localhost. You can do this by editing `pg_hba.conf`, which is located in following locations
Ubuntu : /etc/postgresql/9.x/main,
Mac : /usr/local/var/postgres/pg_hba.conf

Allowing password less authentication:  Change following line in `pg_hba.conf`

# TYPE  DATABASE        USER          ADDRESS           METHOD
local   all             all           127.0.0.1/32       peer

to

local   all             all           127.0.0.1/32       trust

Restart postgres service with:

Ubuntu: sudo service postgresql restart
Mac: brew services restart postgresql

3. MySQL: Error installing mysql2: ERROR: Failed to build gem native extension.

This error occurs while ‘bundle install’ with ‘mysql2’ gem or while executing ‘gem install mysql2’ command, It is because required packages for mysql2 gem are missing.

Solution: 

Installing required packages for mysql2 gem.

Ubuntu: sudo apt-get install libmysql-ruby libmysqlclient-dev 
Mac: brew install mysql

4. TCPServer Error: Address already in use – bind(2)

This error pops up when you run `rails s` command in your rails app directory, it is because you are trying to start rails server on a port (default 3000) which is already used by some other process or you have running rails server instance on same port (i.e. 3000).

Solution: 

To resolve this error, find the process that is using port 3000 (default or whichever you use) and kill the process or find the already running rails server process and kill it.

ps -ef | grep rails -> will get you the pid of running rails server  
lsof -wni tcp:3000 ->  will get you the pid of the process which is using port 3000 
sudo kill -9 pid #kill the process

5. Could not find a JavaScript runtime. See https://github.com/sstephenson/execjs,

This is the another most common error occurs because of the missing javascript runtime for your application.

Solution:

ExecJS supports various Javascript runtimes, most of the developer uses `therubyracer` as a runtime. You can install it by adding following lines into your Gemfile.

gem 'execjs' 
gem 'therubyracer', platforms: :ruby

Or to fix this problem for all the project install Node.js

sudo apt-get install nodejs

6. Unpermitted parameters

If your are working with nested attributes/parameters using accepts_nested_attributes_for this is the most common issue that you face.

Example:

class Category < ActiveRecord::Base
  belongs_to :brand
end
class Brand < ActiveRecord::Base
  has_many :categories, dependent: :destroy 
  accepts_nested_attributes_for :categories, allow_destroy: true
end

When you post the parameters with the following format.

{ 
  "utf8"=>"✓", 
  "authenticity_token"=>"sdunxlowasd=O",
  "brand"=>{"name"=>"Brand Name",
    "categories_attributes"=>{
      "0"=>{"name"=>"category name 1", "priority"=>"1"}, 
      "1"=>{"name"=>"category name 2", "priority"=>"2"},
    }
  }, 
  "commit"=>"Save"
}

Here, If you notice categories_attributes are nested inside brand. If you post these kind of parameters to controller you are likely to get following error.

Unpermitted parameters: categories_attributes

Solution:

You can permit nested parameters in controller with permit method as follows.

class BrandController < ActionController::Base
  def create
    Brand.create(brand_params)
  end

  private
  def brand_params
    params.require(:brand).permit(:name, categories_attributes: [:id, :name, :priority])
  end
end

7. No route matches “/users/sign_out”

Most of the developers uses devise gem for user authentication, when you setup all things related to devise and when you hit a ‘logout’ button first time you are likely to receive this error above message.

Solution: 

Recommended solution for this error is to add http method DELETE to the sign out link.

<%= link_to "Sign out", destroy_user_session_path, method: :delete %>

Another way to fix this issue is by updating config/initializers/devise.rb

config.sign_out_via = :delete

to

config.sign_out_via = :get

8. WARNING: Can’t verify CSRF token authenticity

When you execute AJAX requests this is most common error you get. Rails by default prevents all the request without CSRF token to protect attacks like cross-site forgery

Solution:

To resolve this issue make sure you have

  1. <%= csrf_meta_tag %> in your layout
  2. Every AJAX request sending CSRF token in request headers

You can setup all AJAX request to send CSRF token as follows

$.ajaxSetup({
  headers: {
    'X-CSRF-Token': $('meta[name="csrf-token"]').attr('content')
  }
});

9. Don’t know how to build task ‘test’ (See the list of available tasks with `rake –tasks`) 

When you write the rake tasks for the first time in your rails application, this is the first error you will encounter.
Solution:
1. Make sure you save your rake task file in lib/tasks/*
2. Rake file must have `.rake` as a file extension many a time mistakenly we add `.rb` as a file extension.

10. ActionView::Template::Error (application.css isn’t precompiled)

When you visit your application for the first time after deploying it to the production, You are likely to receive above error message. Rails by default assumes that all the applications assets (jasvascripts, css etc) are pre-complied in production environment and try to find the pre-complied assets.
Solution:
Recommended way to solve this issue is, you should pre-compile Rails assets with following command.
bundle exec rake assets:precompile

You can make this command as a part of application deploy script using Mina or Capistrano.

Another way to resolve this error is by telling rails to compile assets on runtime but this is not an efficient solution which is not recommended. You can resolve this error by setting assets compile to true in config/environments/production.rb.
config.assets.compile = true

Hope you enjoyed this article! If you have any suggestions/thoughts about this post let me know via comments. Happy learnings…

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out /  Change )

Google+ photo

You are commenting using your Google+ account. Log Out /  Change )

Twitter picture

You are commenting using your Twitter account. Log Out /  Change )

Facebook photo

You are commenting using your Facebook account. Log Out /  Change )

Connecting to %s

This site uses Akismet to reduce spam. Learn how your comment data is processed.