Modifying built-in classes

Inheritance is a powerful idea in object oriented programming. This lets you add new enhancements to existing classes. Well, not exactly. You have to create a new data type derived from the existing classes and use these for additional enhancements.

For example, if we want to add a function palindrome to String class. Solution existing in all (most?) object oriented programming languages is to create a class say Word derived from String and add the function to this class. In Ruby for example it would look like:

Note – replace ‘LT’ with corresponding symbol for less than. HTML is messing it up and I feeling lazy to find the &; version for it.

 
 
class Word 'LT' String 
def palindrome? 
   self == self.reverse 
end
end 
... 
irb> w = Word.new("level")
irb> w.palindrome? 
true
irb> w1 = Word.new("simple")
irb> w1.palindrome? 
false 
 

What we lose here is that we CANNOT call the function on String objects e.g., following is invalid:

 
irb> "level".palindrome? 
NoMethodError: undefined method `palindrome?' for "level":String
 

Ruby, quite surprisingly (and did i mention it never fails to amaze!) provides this. It lets you modify the built-in classes. So we can add a function simply by following:

 
 
class String 
def palindrome? 
   self == self.reverse 
end
end 
 

and it gets your String more powerful!

 
 
irb> "level".palindrome? 
true
 

Isn’t that coooooool??

Advertisements

Ruby require error in loading gems

Long time that I coded in Ruby so thought lets replenish the love.

I started reading Graph APIs from Facebook to get some idea of what capabilities they provide with. Graph APIs are immensely powerful in the kind of data they allow developers to access. No doubt how such powerful ecosystem got created. Graph API responses are in JSON (Javascript Object Notation). I have little familiarity with this representation of data. Coming from old school I’ve mostly played with XML data. So I thought lets first try practicing JSON on Ruby. So first step –

$ gem install json

It was easily installed.

Then I wrote the script to load JSON gem in my script i.e.

require ‘json’

and just to test if this is fine I executed it (being almost sure that it will and I will move on). Ruby interpreter yelled!

$ ruby temp.rb
temp.rb:1:in `require’: no such file to load — json (LoadError)
from temp.rb:1

Hmm. so again. Some googling helped (and refreshed some memory) –

There are three ways to handle this –

1. Put following line to the starting of the script

require ‘rubygems’

2. Execute it as:

$ ruby -rubygems script.rb

3. Add rubygems to RUBYOPT

$ export RUBYOPT=”rubygems”

Well, just now I read this article on Github and it clearly says:

You should never do this in a source file included with your library,
app, or tests:

require ‘rubygems’

Why You Shouldn’t Force Rubygems On People!

So guys, (2) and (3) are the way to go and (1) is to be avoided if you plan to share your Ruby script.

Compile Ruby Script To Exe (MS DOS or Windows)

Today I spent some time compiling a small ruby script of mine into an executable. Why? well, I don’t have concerns of hiding the code but this was a requirement of one of the users of my script.

I started with a Google search on such compilers. RubyScript2Exe is what I used. After installing it as a gem I got an error. I downloaded the script RubyScript2Exe.RB and tried again. But fate had it – the same error.

C:\Users\mawasthi\Desktop>ruby rubyscript2exe.rb theboringstuff.rb
rubyscript2exe.rb:621:in `replace’: can’t modify frozen string (RuntimeError)
from rubyscript2exe.rb:577:in `block in newlocation’
from rubyscript2exe.rb:505:in `block in newlocation’
from rubyscript2exe.rb:472:in `newlocation’
from rubyscript2exe.rb:505:in `newlocation’
from rubyscript2exe.rb:577:in `newlocation’
from rubyscript2exe.rb:619:in `<main>’

I read about solutions on forums. None helped. Problem was clear (some change in Ruby updated version in which program name will be a frozen string).

Then I got from one of the forums a link to another “less SEO’ed” compiler “ocra”. I installed it –

C:\Users\mawasthi\Desktop>gem install ocra
Fetching: ocra-1.3.0.gem (100%)
Successfully installed ocra-1.3.0
1 gem installed
Installing ri documentation for ocra-1.3.0…
Installing RDoc documentation for ocra-1.3.0…

Worked like charm:

C:\Users\mawasthi\Desktop>ocra theboringstuff.rb
=== Loading script to check dependencies
:: === Including 52 encoding support files (2741248 bytes, use –no-enc to exclude)
=== Building theboringstuff.exe
=== Adding user-supplied source files
=== Adding ruby executable ruby.exe
=== Adding library files
=== Compressing 5678626 bytes
=== Finished building theboringstuff.exe (1391140 bytes)

Building Strings in Ruby

If efficiency is important to you, don’t build a new string when you can append items onto an existing string. Constructs like str << ‘a’ + ‘b’ or  str << “#{var1} #{var2}” create new strings that are immediately subsumed into the larger string. This is exactly the thing to avoid. Use str << var1 << ” ” << var2; instead.

Rails: getting multiple selected values from selection box

I got stuck for last half an hour at ‘getting the values of multiple selected items in a muliple selection box’ using Ruby/Rails. Got it after hard ‘googling’ and got the solution here.

When trying to get multiple selected values from a <SELECT> tag into @params, call your parameter something with [] on the end. That way rails knows it’s multiple.

So instead of

<select name="job[techs]" size="5" multiple="multiple">

Use:

<select name="job[techs][]" size="5" multiple="multiple">

Thanks google and Ruby/Rails community !

sending mails using ruby

There is a very common requirement especially in web services, that of sending notification email for some action say, addition/deletion/updation of database in user signup or product selection in a shopping cart. Ruby handles it beautifully. This is obvious. What is not obvious is that it actually gives user different ways of implementing it.

  • RubyMail
  • TMail
  • ActionMailer (uses TMail)

I used ActionMailer. I had a database driven website. I wanted to notify administrator for any updation in the database (addition/edition of records). So this is how I did it :-

ruby script/generate mailer Notifier

This creates a file in several files :-


test/unit/notifier_test.rb
test/fixtures/notifier
app/models/notifier.rb
app/views/notifier

Of Particular interest is file :- app/models/notifier.rb. Add following method in this file in the class Notifier,


def notifyMyAction( argument )
  # Email header info MUST be added here
  @recipients = "xyz@abc.com, mno@def.com"
  @from = "intelligent@ruby.com"
  @subject = “Action happened” 

  # Email body substitutions go here
  @body[“argument”] = argument
end

And following code in the controller’s method where you want to notify.


def update_db_and_notify
...
  Notifier::deliver_notifyMyAction((arg)
...
end

NOTE: ‘deliver_’ before the function name !!

Now put the mail body as you would like to put, in the view/notifier/notifyMyAction.rhtml


Dear  <%= @argument >, 

Your database just got updated !! 

Thanks
-Notifier

We are just done. Finally, append following text to the config/environment.rb file (if not already there)
and change address to _your_ mail server address. domain is optional but should make senses since some spam filters filter out the mails on the basis of this. username and password are also optional as is the last one which i commented in my case 🙂


ActionMailer::Base.server_settings = {
  :address  => "mail.server.com",
  :port  => 25,
  :domain  => 'www.abc.com',
  :user_name  => "me@abc.com",
  :password  => ‘mypass’,
#  :authentication  => :login
    }

There is more to learn like attachments, HTML messages, and many other tweaks. You can get it here.

Hail ruby !