Attribute accessors in ruby – behind the scene

In the last post we saw that, what attribute accessors methods are and how it can be used. In this post, we’ll see how actually these accessors are implemented.

lets take the example from last post and see why errors were thrown in some cases :-

  
class Person
  attr_accessor :age
  attr_writer :name
  attr_reader :gender
 end 
1.9.3-p125 :013 > p = Person.new
=> #<Person:0x00000001309c00> 
1.9.3-p125 :014 > p.age=20
=> 20 
1.9.3-p125 :015 > p.age
=> 20 
1.9.3-p125 :016 > p.name='vikram'
=> "vikram" 
1.9.3-p125 :017 > p.name
NoMethodError: undefined method `name' for #<Person:0x00000001309c00 @age=20, @name="vikram">
	from (irb):17
	from /home/inbelu013521a/.rvm/rubies/ruby-1.9.3-p125/bin/irb:12:in `'
1.9.3-p125 :018 > p.gender
=> nil 
1.9.3-p125 :019 > p.gender='male'
NoMethodError: undefined method `gender=' for #<Person:0x00000001309c00 @age=20, @name="vikram" >
	from (irb):19
	from /home/inbelu013521a/.rvm/rubies/ruby-1.9.3-p125/bin/irb:12:in `'

Lets analyze all three accessor methods one by one and see what is happening behind the scene.
In above example we saw that, we can read and write the attribute age, only write the attribute name and only read the attribute gender and that happens because behind the scene ruby translates the method call

attr_accessor :age

into

def age=(value)
  @age = value
end
def age
  @age
end
attr_writer :name

into

def name=(value)
  @name = value
end
attr_reader :gender

into

def gender
  @gender
end

So, now it makes clear that why those method calls were throwing error.

Attribute accessors in ruby

As we all know that ruby is an object oriented language and we always deal with classes and objects directly or indirectly with it. Now when we deal with objects, we certainly have one or more attributes associated with it which is like an instance variable and can be accessed using the object dot notation.

To access the attributes of an object, like any object oriented language, we need to have getters & setters method and ruby does not make any difference between getters & setters methods and normal methods. Let’s see an example of getters and setters in ruby.

Suppose we have to define a class person with an attribute called age, the class skeleton with getter & setter method will look like the code given below :-

class Person
  def age=(age)
    @age = age
  end

  def age
    @age
  end
 end 
1.9.3-p125 :020 > p = Person.new
=> #<Person:0x000000012cc6e8> 
1.9.3-p125 :021 > p.age=20
=> 20 
1.9.3-p125 :022 > p.age
=> 20  

Now these above getters & setters methods are called attribute accessor methods in ruby.

As we know that ruby does so many things on its own(one of the main reasons i love it), by default it has given some accessor methods which serves their own purpose. The accessors that ruby provides by default are attr_accessor, attr_reader and attr_writer. Lets see how they work :-

    
class Person
  attr_accessor :age
  attr_writer :name
  attr_reader :gender
 end 
1.9.3-p125 :013 > p = Person.new
=> #<Person:0x00000001309c00> 
1.9.3-p125 :014 > p.age=20
=> 20 
1.9.3-p125 :015 > p.age
=> 20 
1.9.3-p125 :016 > p.name='vikram'
=> "vikram" 
1.9.3-p125 :017 > p.name
NoMethodError: undefined method `name' for #<Person:0x00000001309c00 @age=20, @name="vikram">
	from (irb):17
	from /home/inbelu013521a/.rvm/rubies/ruby-1.9.3-p125/bin/irb:12:in `'
1.9.3-p125 :018 > p.gender
=> nil 
1.9.3-p125 :019 > p.gender='male'
NoMethodError: undefined method `gender=' for #<Person:0x00000001309c00 @age=20, @name="vikram" >
	from (irb):19
	from /home/inbelu013521a/.rvm/rubies/ruby-1.9.3-p125/bin/irb:12:in `'

So, from the above snippets, it is clear that we can read and write the attribute age, can only write the attribute name and can only read the attribute gender and we can generalize it by saying that

    
class Person
  attr_accessor :age   # provides getters & setters
  attr_writer :name    # provides only setters
  attr_reader :gender  # provides only getters
end 

I think above paragraphs make it clear about the different accessor methods and when & how to use it.

In the next post I’ll describe about behind the scenes for these methods.

Cheers 🙂

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? 😀

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.

Receiving 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 🙂