Method Chaining and its benefits in ruby

Being a rails/ruby developer, we do method chaining every day but many of us are unaware of the term.

Let me give you a simple example of method chaining :-

User.where(SOME_CONDITION).order(SOME_FIELD)

yes, that is method chaining. Now, lets define it in standard way.

What is method chaining ?

Method Chaining is a common syntax for invoking multiple method calls. Each method returns an object, allowing the calls to be chained together in a single statement.

How to write code to do method chaining?

Lets start with designing a simple class with some methods. Lets say the class Book.

class Book 
  def title(title)
    @title = title
  end

  def author(name)
    @author = name
  end
  
  def price(price)
    @price = price
  end

  def book_details
    puts "The book titled #{@title} is written by #{@author} and is available at price $#{@price}"
  end
end

Now our class is ready with some basic methods. Lets try to execute the methods and do the method chaining on methods title(), author() and price().

1.9.3-p125 :021 > book = Book.new
 => #<Book:0x00000001f38468>  
1.9.3-p125 :022 > book.title("Method Chaining in Ruby")
 => "Method Chaining in Ruby" 
1.9.3-p125 :023 > book.title("Method Chaining in Ruby").author("Vikram Kumar Mishra")
NoMethodError: undefined method `author' for "Method Chaining in Ruby":String

:(…throwing error :). Well it was expected but what’s wrong with the code written? If you see the error carefully, it is trying to call the author() method on the string “Method Chaining in Ruby” because the title() method is returning the string and so the error is. Basically if we want to call any instance method, we should have the instance first, right? Yes. Lets modify our methods a bit.

class Book 
  def title(title)
    @title = title
    self
  end

  def author(name)
    @author = name
    self
  end
  
  def price(price)
    @price = price
    self
  end

  def book_details
    puts "The book titled #{@title} is written by #{@author} and is available at price $#{@price}"
  end
end

lets try chaining the method again

1.9.3-p125 :044 > book = Book.new
 => #<Book:0x00000001f38468> 
1.9.3-p125 :045 > book.title("Method Chaining in Ruby")
 => #<Book:0x00000001f38468 @title="Method Chaining in Ruby"> 
1.9.3-p125 :046 > book.title("Method Chaining in Ruby").author("Vikram Kumar Mishra")
 => #<Book:0x00000001f38468 @title="Method Chaining in Ruby", @author="Vikram Kumar Mishra"> 
1.9.3-p125 :047 > book.title("Method Chaining in Ruby").author("Vikram Kumar Mishra").price(100)
 => #<Book:0x00000001f38468 @title="Method Chaining in Ruby", @author="Vikram Kumar Mishra", @price=100> 
1.9.3-p125 :048 > book.title("Method Chaining in Ruby").author("Vikram Kumar Mishra").price(100).book_details
The book titled Method Chaining in Ruby is written by Vikram Kumar Mishra and is available at price $100
 => nil

Whoa…it worked..yay :)

Benefits of method chaining:

1) Improves the readability of the code.

2) Reduces the amount of code needed when interacting with a class or an instance of a class.

3) Eliminates the need for intermediate variables.

Useful, isn’t it? :)

Reference :- Method Chaining-SitePoint

Difference between map, each, select and collect in ruby

In ruby we have some predefined iterators which we use everyday in practice to iterate ever an collection of data and those are map, collect, each and select. Let’s see how they differs with each others :-

Suppose we have an array of numbers like [1,2,3,4] and we will use all those predefined iterators on this array and will see the difference in result.

1.9.3-p125 :029 > a = [1,2,3,4]

=> [1, 2, 3, 4]

1.9.3-p125 :030 > a.map{|n| n*22}

=> [22, 44, 66, 88] #operates on each element of the array and returns the result

1.9.3-p125 :031 > a.map{|n| n>22}

=> [false, false, false, false] #operates on each element of the array and returns the result

1.9.3-p125 :032 > a.collect{|n| n*22}

=> [22, 44, 66, 88] #operates on each element of the array and returns the result

1.9.3-p125 :033 > a.collect{|n| n>22}

=> [false, false, false, false] #operates on each element of the array and returns the result

1.9.3-p125 :034 > a.select{|n| n*22}

=> [1, 2, 3, 4] #operates on each element of the array and ignores the result because we are not selecting anything.

1.9.3-p125 :035 > a.select{|n| n>22}

=> [] #operates on each element of the array and returns the selected result

1.9.3-p125 :036 > a.each{|n| n*22}

=> [1, 2, 3, 4] #operates on each element of the array and ignores the result

1.9.3-p125 :037 > a.each{|n| n>22}

=> [1, 2, 3, 4] #operates on each element of the array and ignores the result

1.9.3-p125 :038 > a

=> [1, 2, 3, 4] #array is unchanged

From the result, we can see that map and collect are one and the same and differs from each and select method.

The select method returns the result of the code block if it is selective i.e. we are writing the code to return the conditional result.

When to use what

Map OR Collect – When we need to operate on existing data and get the result. For example :-

a.collect{|n| n*22} #[22, 44, 66, 88]

a.map{|n| n*22} #[22, 44, 66, 88]

select – When we need to select one or more data from a collection of data based on certain condition. For example :-

a.select{|n| n>22} #[]

a.select{|n| n>2} #[3,4]

a.select{|n| n<2} #[1]

each – When we need to call any other method/block on each element of the array. For Example :-

a.each{|n| print n} #1234

a.each{|n| do_something(n)}

Easy and powerful, right? :) That’s why I love ruby :)

Send inline image in email with rails

There are situations, when we need to send images as inline images, not as attachment via rails application. I also recently faced similar need. dig around and brought up the solution for you all and its very simple.

In mailer method, write the following line :-

attachments.inline["what_ever.image_format"] = File.read("Path to image")

For Example, in notifier_mailer.rb, I have

def send_admin_statistics param1, param2
  .............................
  .
  .
  attachments.inline["what_ever.image_format"] = File.read("Path to image")
  .
  .
  .............................
end

and in corresponding view of mailer method, add the line

  <%= image_tag(attachments["what_ever.image_format"].url) %>  

Like in app/views/notifier_mailer/send_admin_statistics.html.erb, I have

  ..............................
  .
  .
  <%= image_tag(attachments["what_ever.image_format"].url) %>
  .
  .
  ..............................

Simple, isn’t it? :D

Cheers
Vikram

Deprecation Warning for vendor plugins in rails 3.2 and higher versions OR Convert simple rails 2.3 style plugins

As we all know that till rails 3.1, we were able to use vendor-ed plugins by keeping the code for any plugin in vendor/plugins directory. But, using vendor-ed plugins is deprecated in rails versions 3.2+ and throws the deprecation warning for the same. In rails 4, it will be completely removed.  So, its a big headache when we try to upgrade any application with version rails 3.1 or lesser to rails versions 3.2.0 and higher.  So, if you are like me, do not worry. Every problem has a solution and so does for it also :) .

If you have plugins in your vendor/plugins in directory then try to replace that plugin with a gem, which serves the same purpose as the plugin does. If you can not find any equivalent gem for your plugin or any alternative does not exist or you do not want make any changes in the code-base, please follow the steps on the below given link :-

http://matt.coneybeare.me/how-to-convert-simple-rails-23-style-plugins/

Thanks

Vikram

Disable page caching in all browser

Many times we face some serious issue while dealing with web page visibility after and before login and that happens due to browser’s property to cache pages.

Here is the solution to avoid browser caching problem using HTML and rails 3 :-

In application_controller.rb add

  before_filter :set_cache_buster

  def set_cache_buster
   response.headers['Cache-Control'] = 'no-cache, no-store, max-age=0, must-revalidate'
   response.headers['Pragma'] = 'no-cache'
   response.headers['Expires'] = 'Fri, 01 Jan 1990 00:00:00 GMT'
  end

But above solutions does not work for all browsers. Like you will still face issue in browser like safari and in some versions of IE too. So to avoid it all, in layouts/application.html.erb

  <body onunload="">

Now, it will work like a charm…cheers :)

Autoloading modules or classes from lib directory rails 3

From the title of this post, it seems that this is too easy to do and it indeed is but common too. However in some cases especially in production environment, it becomes a serious headache and this is my personal experience which I faced yesterday.

It is a very common problem for developers using rails 3 that they are not getting the modules or classes from their lib directory loaded in Rails 3, especially in production. This leads to errors like “NoMethodError”, “No such file to load”, and “uninitialized constant” etc. I also faced the same and googled it and found many of the posts for this problem with different reasons and different solutions. So, I am trying to summarize the basic fixes for it.

1) Your lib directory is not included in your autoload path.
In Rails 2, classes and modules were auto loaded but in rails 3, it has been updated such that classes and modules are lazy loaded. So a class/module wont be loaded to your application until you require it. A easy solution to this is to include lib folder and its sub folders in autoload paths. Just open the file config/application.rb and insert the line

  config.autoload_paths += %W(#{config.root}/lib)
  config.autoload_paths += Dir["#{config.root}/lib/**/"]

2) Your class/module is not named correctly
Remember the quotation, convention over configuration. Please follow the classes/modules naming standard in rails way. i.e. if there is a class named ClientUser, then file name should be client_user.rb and vice versa.

3) Your application is threadsafe.
This was the solution to my problem. If you have threadsafe enabled in production environment, then the classes/modules will not be autoloaded even if they are included via autoload path. So, to workaround this either require your library files or comment out the line config.threadsafe! from config/production.rb.

Hope it will help! :)

finding subsets of an array in ruby

Lets say we have to find all subsets of specific length from an array. The very first thing that will hit our mind is ohh no.. :(, now i will have to write more complex logics and all. But don’t worry, ruby provides a simple method for doing it. Now happy?? :). Ok, let me show you how it works.

Lets say we have an array [a,b,c,d,e,f,g,h,i,j,k,l] and need to find all subsets of length 2 to 5. So here we go

  
  our_array = [a,b,c,d,e,f,g,h,i,j,k,l]
  our_required_subsets = 2.upto(5).flat_map { |n| our_array.combination(n).to_a } 

  our_required_subsets.each do |subset|
  
    print subset
    print "\n"

  end

Easy isn’t it ? That’s why I love ruby :) .

Receiving incoming emails in rails 3

Well..we all probably use our web applications for sending email for any kind of notifications but when it comes to receiving the email from gmail or any other email service, we rarely do. I also ran into same rarest scenario where i had receive email from gmail. So, I will be stick to using gmail as my email service provider but you can use any of your interest.

Receiving email in Rails however is slightly less documented. But there are many options available for it-from ruby gems to rails native way of receiving it and choosing the right path is completely subject of one’s requirement and choice. However please have a look at below link for some available options and pros and cons associated with it.

http://steve.dynedge.co.uk/2010/09/07/incoming-email-in-rails-3-choosing-the-right-approach/

Looking at the above link, I decided to go for using IMAP. We do not need any external gem for it as ruby provide us the library to accomplish the task.

Before writing any code for it, we need to have a imap configured gmail account. If you do not imap configured, please configure it before moving ahead. Below is the process to enable imap in gmail:
1. Sign in to Gmail.
2. Click the gear icon in the upper right, then select Settings.
3. Click Forwarding and POP/IMAP.
4. Select Enable IMAP.
5. Click Save Changes.

Now create a yml file say config/imap.yml to store imap credentials.

  host: imap.gmail.com
  port: 993
  username: ****************
  password: ****************
  enable_ssl: true

Now we are all set to fetch email from gmail using IMAP. Now use the below code to fetch and decode email.


  require 'net/imap'
  require 'net/http'

  # imap.yml contains the imap config for the email account (ie: username, host, etc.)
  config = YAML.load(File.read(File.join(Rails.root, 'config', 'imap.yml')))

  #create imap instance and authenticate application
  imap = Net::IMAP.new(config['host'],config['port'],true)
  imap.login(config['username'], config['password'])

  #select inbox of gmail for message fetching
  imap.select('INBOX')

  #fetch all messages that has not been marked deleted
  imap.search(["NOT", "DELETED"]).each do |mail|

    message = Mail.new(imap.fetch(mail, "RFC822")[0].attr["RFC822"])

    #fetch plain part message from multipart gmail content
    plain_body = message.multipart? ? (message.text_part ? message.text_part.body.decoded : nil) : message.body.decoded

    #fetch to and from email address.. you can fetch other mail headers too in same manner.
    to_email = message.to
    from_email = message.from

    # do whatever you want to do with those data...like print it
    puts plain_body
    puts to_email
    puts from_email

    #mark message as deleted to remove duplicates in fetching
    imap.store(mail, "+FLAGS", [:Deleted])

  end
  #logout and close imap connection
  imap.logout()
  imap.disconnect()

Now you have successfully fetched email from gmail…yay…cheers :)

Getting started with ruby on rails part2

In my last post, I discussed about installing the prerequisites for working with ruby on rails. If you haven’t already seen it and having some installation problem, please check my previous post getting started with ruby on rails.

Now, since we have successfully installed the software(s) required, its time for us to move ahead and start the development. So, we’ll start with a Hello World program(as we do with almost all languages :P :D).

The very first thing we need now is an application(a rails application), so we’ll follow some below steps and will create the application. But, before going through steps, we should know that rails uses sqlite3 as default database which we can change at the application creation or later(its all your choice). Here, I will be dealing with mysql mainly.

1) Create a rails application(Provided, we already have rails installed from previous post):-

user:~/projects/rails$ rails new first_app

The above command will create a new rails application with default database sqlite3. But as I said earlier, it can be changed to others DB also of our choice. So, for example to start with mysql database, we can run

user:~/projects/rails$ rails new first_app -d mysql

. Here -d option represents the database.

2) Installing all required dependencies -
Although rails with version >3.2 do it for you in the beginning, but to be more confident about it run

user:~/projects/rails$ cd first_app/

and

user:~/projects/rails/first_app$ bundle install

3) Create the database and set your DB credentials
Edit config/database.yml with your DB username and password. Also, you can change the database name of your choice in the same file. Now run the command

user:~/projects/rails/first_app$ rake db:create

and it will create the database with given name in config/database.yml.

4) Start the server:-

user:~/projects/rails/first_app$ rails server

OR

user:~/projects/rails/first_app$ rails s

5) Open a web browser and type http://localhost:3000/. you will see something like below in the browser.
rails_welcome

If you see something like above then you have successfully ran a rails application. Congratulations :).
Now, We’ll make the rails to say “Hello World”. To get it done, we need at least a controller and a view and fortunately we can do that using a single command. So, Run this command in your terminal.

user:~/projects/rails/first_app$ rails generate controller home hello_world

Now as you can see in your terminal, several files have been created for you and app/views/hello_world.html.erb is one of them. Open this file in your text editor and edit it to contain a single line of code:

Hello, Rails!

Before doing anything else, we should remove the default file which have been rendered by rails in the beginning to render our file. To accomplish this task either go to public folder and delete the index.html file or run the below command from the terminal.

user:~/projects/rails/first_app$ rm public/index.html 

Now edit config/routes.rb and place the line

root :to => "home#hello_world"

and restart the server by pressing CTRL+C in terminal and running the

user:~/projects/rails/first_app$ rails server

again.

Yeah…..we have successfully started with rails….cheers….(beer)

To get more details and learn more about ruby on rails, please visit the official rails guide.

Now, I’ll be discussing about usage of different gems in our day to day life. So stay tuned….

Thanks
Vikram

Getting started with ruby on rails

Hey folks,

Sorry its been too long since I have wrote my last article. Actually I was busy in doing nothing ;). Anyway, now I am here to give you a walk-through of getting started with ruby on rails.

The very first step for getting started with any software/programming language/framework is to install it, any other thing comes later. So, in this post we’ll be installing our required software(s).

Installation:-

1) Install Ruby Version Manager(RVM) :- Its a command line tool which allows us to easily install, manage, and work with multiple ruby environments from interpreters to sets of gems. It’s not a hard and fast requirement but being a developer we should use it because, we are working with different versions of the software in different scenarios and it maintains those things very efficiently.
Below are the steps involved in installing Ruby Version Manager(RVM) and its requirements:
a) Download and install Ruby Version Manager(RVM) :

$ \curl -L https://get.rvm.io | bash -s stable 

or the link below can also be used to download and install Ruby Version Manager(RVM) :

$ bash < <(curl -s https://raw.github.com/wayneeseguin/rvm/master/binscripts/rvm-installer )

b) Confirm the installation

$ type rvm | head -1

and the output should be “rvm is a function“.

c) Check its requirements

$ rvm requirements

Now install the requirement as per the output of above command

$ sudo apt-get update
$ sudo apt-get install build-essential openssl libreadline6 libreadline6-dev curl git-core zlib1g zlib1g-dev libssl-dev libyaml-dev libsqlite3-0 libsqlite3-dev sqlite3 libxml2-dev libxslt-dev autoconf libc6-dev ncurses-dev automake libtool bison subversion

Now you are done with RVM…yay…

2) Install Ruby:

$ rvm install 1.9.3 

You can check ruby versions using the command

$ rvm list known | head -15

and install the specific version using the above command.

3) Install Rails:-
we can also use the beauty of rvm here and create a gemset for our specific application before installing rails, like

$ rvm gemset create first_app 
$ (sudo) gem install rails 

We have now successfully installed rvm, ruby and ruby on rails. But, we do not have any database set up yet. So let’s install the database of our choice. I am using mysql here.

$ sudo apt-get install mysql-client mysql-server libmysqlclient-dev

Now we have successfully installed required software to run a ruby on rails application. Cheers….

Thanks
Vikram