Silence is Foo Mental notes on Ruby/Git/Rails/Flex

27Aug/103

MUSh, a multi-service URL shortener in Ruby

I have to tell the truth, I'm really lazy, if there is a way to avoid to do something I will do so.

What about avoiding to open a browser or create a new tab and click a bookmark or type the address of a URL shortener service when I want to shorten a URL? If I have an opened terminal with IRb and Bash almost the whole day, why don't use it to shorten URLs?

Using the most pure principles of LDD (Laziness-Driven Development) I've created a gem called MUSh, a Multi-service URL Shortener, hence the name.

Yes, I know there are thousands of API wrappers in Ruby for bit.ly, etc. but most of them are fully-featured API wrappers and I didn't want all of those features, I just wanted to shorten URLs, that's it, well, I wanted command-line utilities as well, but I didn't find them in any existing gem.

I've been using MUSh for almost a month now, and it really helps me, that's why I decided to release it as a gem, if you want to install it just do it this way:

$ sudo gem install mush

It currently supports bit.ly, is.gd and u.nu services and it have one command-line utility per service:

$ isgd foo.raflabs.com

$ unu foo.raflabs.com

$ bitly -l your_login -k your_apikey -u foo.raflabs.com

Hum, the last command doesn't help that much. I know. MUSh currently doesn't support storing your credentials so I use an alias.

In your ~/.bash_profile or ~/.bashrc:

alias bitly='bitly -l your_login -k your_apikey'

after adding your alias issue the following command to refresh your terminal or close it an open another one:

$ source ~/.bash_profile (or whatever is your file called)

and now you'll be able to use the bitly command without specifying your credentials, even without specifying the -u option.

$ bitly foo.raflabs.com

If you're in a Mac and want to copy the shortened URL in one step, just use the pbcopy command:

$ bitly foo.raflabs.com | pbcopy

Then paste it with Cmd-V or with the pbpaste command.

MUSh was made in Ruby, so you can use it in your Ruby applications as well.

Bit.ly

bitly = Mush::Services::Bitly.new

bitly.login = "your_login"
bitly.apikey = "your_apikey"

bitly.shorten "http://foo.raflabs.com" # => http://bit.ly/bJO5IH

Is.gd

isgd = Mush::Services::IsGd.new

isgd.shorten "http://foo.raflabs.com" # => http://is.gd/eFZXc

u.nu

unu = Mush::Services::Unu.new

unu.shorten "http://foo.raflabs.com" # => http://u.nu/3hsje

Besides, If you want to shorten a URL in your Ruby or Rails console in a fast way add the following to your ~/.irbrc:

require 'mush'

def by(url)
  bitly = Mush::Services::Bitly.new
  bitly.login = "your_login"
  bitly.apikey = "your_apikey"

  bitly.shorten url
end

def is(url)
  Mush::Services::IsGd.new.shorten url
end

def un(url)
  Mush::Services::Unu.new.shorten url
end

An use it like this


by "google.com"

is "google.com"

un "google.com"

It's a nice set of shortcuts, I'd say.

Again, if you're in a Mac and want to copy the shortened URL in one step, just use my pasteboaRb gem:

$ sudo gem install pasteboaRb

Basically, pasteboaRb adds to_pb and paste methods to the Object class.

is("foo.raflabs.com").to_pb # => http://is.gd/eFZXc

Then paste it in any Mac application with Cmd-V, in the Terminal with the pbpaste command or in a Ruby terminal with the paste method.

paste # => http://is.gd/eFZXc

Finally, why supporting 3 services? it depends on the size you want, If you want the shortest url and you don't care about statistics use u.nu, if you want to see statistics of your shorten URLs and you don't mind to have 1 or 2 extra characters use bit.ly or is.gd.

To see statistics just add a + or - sign to the URL.

http://bit.ly/bJO5IH+
http://is.gd/eFZXc-

Thanks for reading.

Filed under: ruby 3 Comments
12Aug/1010

nil, nil?, true and false in Ruby

A friend of mine I'm teaching Ruby to asked me just a few days ago about the difference between nil and false and nil and nil? in Ruby. I gave him a very short answer:

    nil = null
    false = boolean value
    nil? is a method

yes, I kinda lied to him about the null and false, but here is the long answer:


First of all, in order to understand how nil, true and false works you have to know that in Ruby:

  • Every expression evaluates to false or true
  • Every object evaluates to false or true.

conclusions:

  • Expressions and objects never evaluates to nil
  • nil and false are different each other

so, we all know that true and false are boolean values but what is nil and nil? anyway?

nil represents the nothing, null, None; some books say that it's the emptiness, I don't like to use that term because it sounds to me like it represents an empty string or an empty object and that isn't the case at all.

nil? is a method, more precisely, it's an instance method of the Object class, it's like asking "is my_object nil?":

NOTE: "expression/object # => value" means that such "expression" or "object" returns such "value".


my_object = nil
foo = "baz"

my_object.nil? # => true
foo.nil? # => false

Second, there's a big difference between the object's value and the value an object evaluates to:

  • The value of nil is nil
  • The value of false is false
  • The value of true is true
  • nil evaluates to false
  • false evaluates to false
  • true and everything, everything, everything else evaluates to true

Let's see some examples:

bar = "silence is foo"
  • The value of bar is "silence is foo"
  • bar evaluates to true
foo = ""
  • The value of foo is an empty string
  • foo evaluates to true
baz = 0
  • The value of baz is zero
  • baz evaluates to true
qux = nil
  • The value of qux is nil
  • qux evaluates to false
corge = false
  • The value of corge is false
  • corge evaluates to false

That's why we don't need to do things like:


my_object = nil

if !my_object.nil?
   puts "my_object is not nil"
end

if my_object == nil
   ...
end

if my_object != nil
   puts "my_object is not nil"
end

Since we know nil evaluates to false, we'd do instead:


if my_object
   #it won't hit this part
end

unless my_object
   #it'll hit this part
end

you should be aware that if you need to know if an object is exactly nil the code above won't help you in some cases. Look:


my_object = false

unless my_object
   puts "my_object evaluates to false but we don't know if it's nil OR false"
end

unless my_object.nil?
    puts "we certainly know that my_object is not nil"
end

my_object = nil

if my_object.nil?
   puts "we certainly know that my_object is nil, anything else"
end

Let's see another case now with hashes, don't do this:


my_hash = {:name => "Ruby" }

my_hash[:version] # => nil (if a key doesn't exist in a hash it will return nil)

if !my_hash[:version].nil?
   puts "The version is #{my_hash[:version]}"
end

if my_hash[:version] != nil
   puts "The version is #{my_hash[:version]}"
end

if my_hash[:version] == nil
   ...
end

Instead we should do:


if my_hash
   puts "even an empty hash will evaluate to true"
end

if my_hash.nil?
   puts "you won't see this"
end

unless my_hash
   puts "you won't see this"
end

unless my_hash.nil?
    puts "we certainly know that my_hash is not nil and it is not false."
end

if my_hash[:version]
   puts "you won't see this
else
   puts "hash[:version] doesn't exist"
end

unless my_hash[:version]
   puts ":version key doesn't exists"
end

if my_hash[:name]
    puts "we know my_hash has a :name key"
end

Cool! now I have to say a last thing.

In Ruby, the value every object evaluates to is not a native boolean value it's actually an object.

meaning, nil, false and true are not simple keywords but objects and every object is instance of a class, in this case:

A real world example of why is this very useful? What about the Whiny Nils in Ruby on Rails?.

oh, yeah, but why nil and false, why don't just false?

false and true are used in boolean expressions and nil is the value a method returns when something went wrong or when there's nothing to return, pretty different than false, don't you think?

Let's see some examples:


puts "foo" # => nil

The Kernel#puts method prints the given string in the STDOUT and returns nil, why we would want Kernel#puts to return false after all? Of course, there's a lot of methods that returns nil in the same fashion, like Regexp#match.


"foo" == "foo" # => true
"foo" == "bar" # => false

nil.nil? # => true

That's all folks, please, don't be shy, leave a comment.

Thanks for reading!

Filed under: ruby 10 Comments