Archive for September, 2009

Ruby variables

Something that you might have to watch out for when working with Ruby is how it works with variables. Ruby variables are only references (pointers) to objects. Therefore, you might experience a subtle behavior that you probably don’t expect. Try this out in your irb:

irb(main):001:0> a = "some text"
=> "some text"
irb(main):002:0> b = a
=> "some text"
irb(main):003:0> a.object_id
=> 23109650
irb(main):004:0> b.object_id
=> 23109650
irb(main):005:0> a.gsub!(/ text/, "thing different")
=> "something different"
irb(main):006:0> b
=> "something different"
irb(main):007:0>

First, we assign a String object “some text”. We could have written it fully as a = String.new(“some text”).

Second, we say b = a, and for Ruby this means that b will now point to the same object as a, and you can verify it by running object_id on both variables. But now comes the catch – if you modify a, b will be automatically modified. So, by running gsub! on a, we also modify b.

However, if you assign a new value to one of those linked variables, the link breaks down, as now one of the variables points to another object. So, if you type a = “some new text”, b will not change, and actually a and b will now point to 2 different objects.

If you want to create a copy of an object and point a variable to it, instead of b = a, you could have cloned the object: b = a.clone.

Advertisements

September 24, 2009 at 9:17 pm Leave a comment

Timing attack? What’s that about?

If you are wondering, like me, what was the “timing attack” fix update in the latest 2.3.4 for, you can read this post here. Basically, if a comparison is made between two strings, it’s done one character at a time, and it stops when the first differing character is encountered. Therefore a potential hacker could measure how much time it takes to check a cookie hash to see if it’s correct or not.

It all seems far fetched, given that surely there must be the overhead in terms of routing from attacker’s PC to your server and Internet Protocol actually works that way that the packets are sent using different nodes, but there are guys who think it’s practical. It’s claimed that most Java programs are exposed under this theoretical vulnerability, so it’s actually not a problem particular to Rails.

However, the bad news about this 2.3.4 patch is that it doesn’t work under Ruby 1.9.1.

September 8, 2009 at 9:01 pm Leave a comment

Defining methods in Ruby

1 – Hashes in method calls

You must have seen this syntax in Rails a lot, for example when using this Paperclip plugin, you would put this in your model:

has_attached_file :photo, :url => "/:class/:attachment/:id/:style/:basename.:extension"

While it looks pretty natural, you might have harder time understanding that has_attached_file is really a method, and there’s a considerable amount of trickery involved to make this method call much easier on your eyes. This post will not only help you read the Ruby code better, but actually create the methods with flexible parameters yourself.

Consider this equivalent call:

has_attached_file(:photo, {:url => "/:class/:attachment/:id/:style/:basename.:extension"})

Now, it’s more clear that has_attached_file method passes 2 values, where a second value is a hash. Allowing hashes in method calls gives a great freedom for both the developer and user of the method – you do not need to remember what’s the correct sequence of the parameters for the method and it’s possible to omit some parameters altogether. So, instead of some_method(first, second, third), you can use a more flexible some_method :second => second, :first => first, :third => third.

Do note, that if you omit the round brackets, you should also omit the curly brackets, so that the hash is not confused for a block, which also uses the curly brackets.

Actually, if you look at how the method was defined in paperclip plugin, you will see this:

def has_attached_file name, options = {}
  ...
end

This method definition (def) uses the fact that Ruby makes brackets optional even for method definitions, so it’s equivalent to this definition:

def has_attached_file(name, options = {})
  ...
end

And what it means is that has_attached_file method expects 2 parameters. The one called options is a hash and it defaults to an empty hash. Actually defaults are quite powerful in Ruby – you can pass any arbitrary Ruby expression to them and call any variables in scope and link to any other parameters. You could have said, for example – def has_attached_file name, options = name.size.

So, how would you access those values passed in the hash? This is very easy, you would do something like this:

def has_attached_file(name, options = {})
  size = options[:size] || 0
  file = options[:file] || "undefined"
end

So, you would check for a hash element with a key :file and if it exists, assign it to the file local variable. If it does not exist, you will (by using ||) set a default.

2 – How many parameters do you want? – Splat arguments

Another common way to define a method is like this:

def some_method(*args)
  ...
end

This means that however many arguments can be provided and they will all be moved into array called args, so that you can access them as a normal array. You can also do something like:

def some_method(first, *args)
  ...
end

This will move the first parameter to first local var, all others (if any) will go into the args array.

Splatting comes in handy, if you want to define a method for your class that does a slight modification of the superclass’ method and then passes all the arguments to the superclass:

Class Child < Parent
  def some_method(*args)
     # your code here
     super
  end
end

If you use super without parameters, it will pass whatever parameters your method received to the parent class. And you can actually further shorten the way you define the method, by just using an asterisk in def, like this:

  def some_method(*)
     # your code here
     super
  end

3. Define your own method on fly?

Another thing you will notice a lot in Rails, is the possibility to define the methods on the fly. And great thing about it is that you can create the method name using any variables and Ruby expressions. Here’s another example from the Paperclip:

define_method "#{name}=" do
  ...
end

This will create a method using the name variable, so that you can have access to this method based on the name of your choice. For more info you can see Ruby docs.

September 6, 2009 at 6:50 pm Leave a comment

Rails 2.3.4 is out, security vulnerabilities fixed

Rails 2.3.4 is out, just a few weeks after the 2.3.3. There are no new features, the reason for this quick release are the 2 vulnerabilities found in the Rails code (one is a possible XSS epxloit and the other is a cookie hack. The release notes state that over 100 small bugs were fixed as well.

However, given the amount of problems some users have (see some comments here) – mostly as it seems with Ruby 1.9, you might want to just patch the vulnerabilities for now, or at least test before you upgrade on production ;).

September 5, 2009 at 10:12 pm Leave a comment


Recent posts

Starting to learn Rails?

Kindle

Get Kindle - the best e-book reader, that I personally use, and the only one that you can read on the beach - very useful: Kindle Wireless Reading Device (6" Display, Global Wireless, Latest Generation)