Tuesday, March 6, 2012

How to install sqlite3-ruby gem on linux

If you are having trouble to install the sqlite3-ruby gem, try the following:

In systems with apt-get:

# apt-get install libsqlite3-dev

In systems with yum:

# yum install sqlite-devel

How to install bson_ext gem on linux

MongoDB requires the bson_ext gem to increase performance. However, it's common to be not ready to install it.

In ubuntu (10.04 32bit) I had to run:

# apt-get install ruby1.8-dev

In systems with yum I had to run:

# yum install gcc
# yum install make
# yum install ruby-devel


Finally in both systems I could run, with no errors:

# gem install bson_ext

A little bit on require behavior

require filename will:
  • return true when it finds filename;
  • return false when it already loaded filename;
  • raise LoadError when it doesn't find filename.
That was not properly documented; the official documentation lean us to guess it would return false when the file is not found, and that's not the case.

Monday, February 27, 2012

Changing aliased method does not alter the original one

Changing aliased method does not alter the original one, and vice-versa.

So, if you need to alter some method that you know it's aliased, you may stay unworried: you won't affect the other aliased methods, and you can use them if you need the original behavior.

See my tests and the results below.

#!/usr/bin/ruby

class A
  def original_method
    puts "original content"
  end
  alias aliased_method original_method
  alias_method :alias_methoded_method, :original_method
end

class B < A
  def original_method
    puts "modified content"
  end
end

class C < A
  def aliased_method
    puts "modified content"
  end
end

class D < A
  def alias_methoded_method
    puts "modified content"
  end
end

[A, B, C, D].each do |klass|
  puts "#{klass}:"
  obj = klass.new
  [:original_method, :aliased_method, :alias_methoded_method].each do |meth|
    print "#{meth}: "
    obj.send meth
  end
  puts
end
The results:
A:
original_method: original content
aliased_method: original content
alias_methoded_method: original content

B:
original_method: modified content
aliased_method: original content
alias_methoded_method: original content

C:
original_method: original content
aliased_method: modified content
alias_methoded_method: original content

D:
original_method: original content
aliased_method: original content
alias_methoded_method: modified content

Friday, February 17, 2012

RewriteRule running twice

Sometimes it seems that RewriteRule is running twice, even we use the [L] flag.

The truth is: it really runs twice (or even more times)! But only when URL is changed.

The [L] flag stops the running of rules following it, but if URL is changed, the new URL will be parsed again from the beginning.

There are many solutions to that (e.g., by using RewriteCond), but the one I used is to put, as first rule, one to tell the RewriteEngine to do nothing if the URL is what I want:


RewriteEngine on

# index is the last rule - is what I want, so doesn't change anything
# and go to it (thank's to [L])!
RewriteRule ^index.php$ - [L,QSA]

# get user id - URL changed, so [L] will cause the new URL to be reparsed
# - and so it will be matched on the above rule.
RewriteRule ^user/(.*)$ index.php?user=$1 [L,QSA]

# in case of user/..., following rules don't apply,
# since the above rule has [L]
# ...

See this post in Portuguese.

Saturday, July 30, 2011

Caller binding

One of most useful feature not present in Ruby is to get the binding of the caller of current method, to do something with its local variables.

There is an implementation in the Extensions gem, but it must be the last method call in the method, and we must use the binding within a block.

There is another implementation here, but it depends on tracing along all the code execution, compromising the performance.

However, in this answer in StackOverflow, Taisuke Yamada implemented an version of ppp.rb (what is it?) which inspired me to implement my own version of a caller_binding method. Enjoy!

#!/usr/bin/ruby
#
# (c) Sony Fermino dos Santos, 2011
# License: Public domain
# Implementation: 2011-07-30
#
# Published at:
# http://rubychallenger.blogspot.com/2011/07/caller-binding.html
#
# Inspired on:
# http://stackoverflow.com/questions/1356749/can-you-eval-code-in-the-context-of-a-caller-in-ruby/6109886#6109886
#
# How to use:
# return unless bnd = caller_binding
# After that line, bnd will contain the binding of caller

require 'continuation' if RUBY_VERSION >= '1.9.0'

def caller_binding
  cc = nil     # must be present to work within lambda
  count = 0    # counter of returns

  set_trace_func lambda { |event, file, lineno, id, binding, klass|
    # First return gets to the caller of this method
    # (which already know its own binding).
    # Second return gets to the caller of the caller.
    # That's we want!
    if count == 2
      set_trace_func nil
      # Will return the binding to the callcc below.
      cc.call binding
    elsif event == "return"
      count += 1
    end
  }
  # First time it'll set the cc and return nil to the caller.
  # So it's important to the caller to return again
  # if it gets nil, then we get the second return.
  # Second time it'll return the binding.
  return callcc { |cont| cc = cont }
end

# Example of use:

def var_dump *vars
  return unless bnd = caller_binding
  vars.each do |s|
    value = eval s.to_s, bnd
    puts "#{s} = #{value.inspect}"
  end
end

def test
  a = 1
  s = "hello"
  var_dump :s, :a
end

test

Friday, July 29, 2011

How to return from inside eval

I have a code which I need to use within eval. Sometimes I need to get out from the middle of eval code, but how?

In PHP I can use the return keyword, but it doesn't work on Ruby:

# expected to see 1, 2 and 5; not 3 nor 4; and no errors
eval "puts 1; puts 2; return; puts 3; puts 4"
  # => Error: unexpected return
puts 5

I tried with return, end, exit, break, and I couldn't get success. exit doesn't raise errors, but then I don't get the 5.

After many tries and a question in StackOverflow, I found a solution which fits best into my problem:

lambda do
  eval "puts 1; puts 2; return; puts 3; puts 4"
end.call
puts 5

This way the intuitive return keyword can be used inside eval to get out from it successfully.

You can find alternative ways at StackOverflow.