Thursday, January 31, 2013

Sequel blocking SQLite3?

I was often getting SQLite::BusyException (reraised as Sequel::DatabaseError) or Sequel::PoolTimeout exceptions when using Sequel to handle SQLite3 databases in a program with little concurrency, in a way that that exceptions are not expected (specially on reads). I rewrote my code to use the SQLite3 gem instead of Sequel, just for test, and I had no more exceptions.

There are things to be investigated, but this tip can be useful to someone as a quick (temporary?) solution.

Friday, January 18, 2013

Some undocumented differences between 1.8 and 1.9

Here I bring some differences among Ruby versions 1.8.7, 1.9.1 and 1.9.2 which I didn't found in other sites, maybe because they represent very rare use cases (or maybe because I didn't search enough). For these cases, version 1.9.3 behaves as 1.9.2. I was faced with them when trying to make Namebox compatible with Ruby 1.8.7 and 1.9.1, but after weeks of work I concluded that it doesn't worth.

Methods names' type


The method names for instance_methods will be String in 1.8.7 and Symbol since 1.9.1.
Since instance_method(method_name)don't care whether method_name is Symbol or String, this seems to be a innocuous difference, but if you code has something like Klass.instance_methods.include?("f") it will break when changing versions. This is also valid for methods and singleton_methods.

class A; def f; end; end

p A.instance_method(:f)         #=> #<Method:A#f>
p A.instance_method('f')        #=> #<Method:A#f>

p A.instance_methods(false)
#=> Ruby 1.8.7: ["f"]
#=> Ruby 1.9.1: [:f]

The superclass of the singleton class of a class


The superclass of the singleton class (also known as eigenclass) of a class X is the singleton class of the superclass of X. This follows the natural way of class methods lookup (not counting the extended modules). However, this works only since 1.9.1. In Ruby 1.8.7, the superclass of the singleton class of any class is the singleton class of the class Class:

class A; end
class B < A; end

# singleton class of B
SB = class << B; self; end

p SB        #=> #<Class:B>

p SB.superclass
#=> Ruby 1.8.7: #<Class:Class>
#=> Ruby 1.9.1: #<Class:A>

Binding class methods to a subclass


For instance methods, you can bind an unbound method to an object since that object is an instance of the method's class or subclass. For class methods, you can bind an unbound method to a subclass of the method's class (or to the class itself). This works since 1.9.2. Earlier versions raises TypeError if you try to bind a class method to a subclass:

class A
  def self.f
    "self is #{self}"
  end
end

class B < A; end

p A.method(:f).unbind.bind(B).call
#=> Ruby until 1.9.1: TypeError
#=> Ruby since 1.9.2: "self is B"

super from a module method after binding


In Ruby 1.8.7, if you bind an instance method of a module to an object (of a class which includes that module), and if that method has super, it will raise NoMethodError instead of looking for the super method. It will flow normally if that method is invoked without bind.

class A
  def f
    "Hello"
  end
end

module M
  def f
    super + " world!"
  end
end

class B < A
  include M
end

b = B.new
p b.f       #=> "Hello world!"

p M.instance_method(:f).bind(b).call
#=> Ruby 1.8.7: NoMethodError
#=> Ruby 1.9.1: "Hello world!"


Saturday, January 5, 2013

Namebox

What is Namebox?


Namebox is a gem I've developed to create namespace boxes to protect the core classes' methods from changes, like Refinements. But, unlike Refinements, Namebox can protect your classes from changes made by external unrefined libraries.

Why Namebox instead of Refinements?


Well, there are a number of reasons for that:
  • Refinements are supposed to be included in Ruby 2.0, but they're complex (see discussions) and maybe they won't be included in that version yet. Namebox can be used now.
  • Personal implementations of Refinements (like mine) could work before Ruby 2.0, but only in programmer's new projects/libraries. You can't use your Refinements to refine a gem made by other people. And even after Ruby 2.0 you must wait to gems' authors to refine them. With Namebox you can protect your core classes from changes caused by existing gems and other external unrefined libraries.
  • Namebox doesn't work exactly as Refinements.
Refinements use modules with the keyword refine, and blocks/regions with the keyword using. There is lexical scope, but it will probably affect subclasses in other files, which is bug-prone. There are some discussions about using modules for Refinements; that new module's role could create confusion.

Namebox is a box where changes can ocurr in the initialize block. When you want use that changes, you open the box in a point of your code file, and close it later. Every method call (of changed methods of the protected classes) inside that region will invoke the code defined in the initialize block. Elsewhere that methods will play their original behavior (or new ones, defined after Namebox initialization). An open region is restricted to its file; it doesn't affect subclasses nor other files. There's no place to confusion and bad surprises.

Why "Namebox"?


It was like looking for a new domain name. The original name was "Namespace", but there was a gem with that name. I tried other names, looking for a short one, and the word "classbox" made me think about "namespace boxes" - that is what nameboxes are.

What are Namebox issues?


Performance. Needless to say, every piece of code takes some time to run. Namebox must check all methods of the protected classes once to detect changes. Moreover, the changed methods are redefined to check the namebox openness and decide which version of the method must be called. If that method is heavily called, it can impact performance. Effort was made to keep that redefined methods as clean and fast as possible. I believe that the speed changes will be imperceptible in most cases, but only everyday use will tell how much.

As mentioned above, Namebox will redefine the changed methods to a decisor method, which will sometimes be in the class or module being protected. If that method is redefined later (outside another Namebox definition), there will be no way to get the desisor method back.

There are some situations where Namebox won't work as expected. For example, if two (or more) nameboxes require the same file somewhere in the initialization block, and that file changes methods of the protected classes, only the first namebox will detect that changes (since require loads each file only once), and that changes won't be available to subsequent nameboxes - unless they're defined where the first is open. I tried to hack Kernel.require to avoid it, but it would impact performance and cause several collateral effects. I expect that kind of case will be rare and circumventable.

Versions. Ruby 1.8.7 and 1.9.1 have some issues regarding class methods. To make Namebox compatible with them, it's necessary to make a more complex code, which runs differently and it's more memory-consuming. Even so, when running over Ruby 1.8.7, the class methods can loose self when changed by extending modules in subclasses (self will be the class instead of subclass when namebox is closed). Namebox versions 0.1.8 and 0.l.9 are compatible with Ruby 1.8.7 and 1.9.1, but newer versions (0.2.0 and greater) are compatible only with Ruby 1.9.2 and later.

Why Public Domain?


I like freedom, but I like it so much that I don't like the limits of GPL/LGPL - they impose freedom in a way that I feel constrained. Public Domain is the most freedom-prone license I've ever heard of. With Public Domain, anyone can do anything with the code, including changing the license, use in private code, earn money, and even improve the code and publish it in a free form.


And the most expected question...

How to use Namebox?


The principle is simple:

# Create a namebox to protect String's methods
NB = Namebox.new(String) do
  # hack String
  class String
    def to_hex
      unpack('H*')[0]
    end
  end
end

NB.open

# String#to_hex is visible here:
puts 'ABC'.to_hex   #=> '414243'

NB.close

# but not here:
puts 'ABC'.to_hex   #=> NoMethodError

Protecting core classes when requiring something:

# :core refers to all loaded modules (but not submodules)
NB = Namebox.new(:core) do
  require "sequel"
end

NB.open

puts :abc & :def     #=> # a Sequel object

NB.close

puts :abc & :def     #=> NoMethodError

There is a wrapper for require:

# :core refers to all loaded modules (but not submodules)
NB = Namebox.require "sequel", :core

NB.open

puts :abc & :def     #=> # a Sequel object

NB.close

puts :abc & :def     #=> NoMethodError

That examples are very silly. Besides you can open and close a namebox several times, you won't want to do that every time. A more practical use is to define methods to use later in your program, like in the Camelize example:

NB_CAMEL = Namebox.new(:String) do
  class String
    def camelize
      dup.gsub(/_([a-z])/) { $1.upcase }
    end
  end
end

class Foo
  NB_CAMEL.open
  def camelize_string(str)
    str.camelize            # works because NB_CAMEL is open here
  end
  NB_CAMEL.close
end

class Bar < Foo
  def change_string1(str)
    camelize_string(str)    # ok
  end
  def change_string2(str)
    str.camelize            # NoMethodError: NB_CAMEL isn't open here
  end
end

Mixing nameboxes:

# with this, you won't need to specify the
# protected modules in this file.
Namebox.default_modules = :core

NB_SEQUEL = Namebox.require "sequel"

NB_OBJECT = Namebox.new do
  class Symbol
    def & x
      "#{self} and #{x}"
    end
  end
end

NB_OBJECT.open

p :abc & :def     #=> abc and def

NB_SEQUEL.open

p :abc & :def     #=> Sequel object;
                  # included modules wins over
                  # superclass changes

NB_OBJECT.close   # you don't need to close the
                  # last opened namebox first

p :abc & :def     #=> Sequel object

NB_SEQUEL.close

p :abc & :def     #=> NoMethodError

You can use Namebox to hack Namebox itself (e.g., to define default_modules thru other files, as constants are global):

NB_DEF_MOD = Namebox.new(Namebox) do
  def Namebox.default_modules
    [Symbol, String]
  end
end

NB_DEF_MOD.open

NB_SEQUEL = Namebox.require("sequel")
# would be the same as Namebox.require("sequel", Symbol, String) 

NB_DEF_MOD.close

You can invoke the previous version of the method thru _old(...):

s = "abc"

puts s.length       #=> 3, any doubt?

NB = Namebox.new(String) do
  class String
    def length
      _old + 1      #=> please, don't do that out of home
    end
  end
end

puts s.length       #=> 3 (namebox is closed here)

NB.open

puts s.length       #=> 4

NB.close

puts s.length       #=> 3

Current version (0.2.2, by 2013-01-27) is under tests, and can be considered a pre-release for 1.0.0. Please, came back later to check for that version! ;-)