Weird! "def" behaves different in class_eval and instance_eval

I found the behavior of keyword def in ruby is really confusing! At least, really confusing to me!
In most case, we use def in class context, then it defines a instance method on specific class.

Use def in class
1
2
3
4
5
6
7
8
9
class Foo
def foo
:foo
end
$context = self
end
Foo.new.foo.should == :foo
$context.should == Foo

Besides the typical usage, we can also use def in block.

Use def in class_eval block
1
2
3
4
5
6
7
8
9
10
11
class Foo; end
Foo.class_eval do
def foo
:foo
end
$context = self
end
Foo.new.foo.should == :foo
$context.should == Foo

This previous piece of code works as we reopened the class Foo, and add a new method to it. It is also not hard to understand.

The fact that really surprised me is in the following code:

Use def in instance_eval block
1
2
3
4
5
6
7
8
9
10
11
class Foo; end
Foo.instance_eval do
def foo
:foo
end
$context = self
end
Foo.foo.should == :foo # Method foo goes into the Foo class itself rather than Foo's instance!
$context.should == Foo

Here we can found that method foo goes into the Foo class itself, rather than Foo‘s instance! But the $context is still Foo class!

So in a word, calling def foo in instance_eval block is equivalent to calling ‘def self.foo’ in class_eval block, even though the context of both block are the class itself.
So we can figure out that keyword def works different than method define_method and define_singleton_method, since it doesn’t depend on self, but the two methods does!

To me it is kind of hard to understand. and confusing. And I think it is not a good design!
Ruby is different to other Java or C#, ruby uses methods on class to take place of the keywords in other languages, such as public, protected and private. In most of the language, they are keywords. But in ruby they are actually the class methods of Class.
This design is good, because it is kind of enabled the developer to extend the “keyword” they can use! But at the same time, this design melted the boundary between customizable methods and predefined keywords, so people won’t pay much attention to the difference of the two. So it is important to keep the consistency between methods and keyword behaviors. But def breaks the consistency, so it is confusing!

Look the following code:

def vs define_method
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
definition_block = Proc.new do
def foo
:foo
end
define_method :bar do
:bar
end
end
class A; end
class B; end
A.class_eval &definition_block
B.instance_eval &definition_block

Comparing class A and class B, we can find that they are different, even they are defined with exactly same block!

Introduce Prototype Style OO inheritance in Ruby

Days ago, I post a blog about the ruby inheritance hierarchy. When discuss the topic with Yang Lin, he mentioned a crazy but interesting idea that introducing the prototype based OO into ruby.
To introducing the prototype OO into ruby, Lin mentioned a possible approach is by using clone. But I’m not familiar with clone mechanism in ruby. So I tried another approach.
Thanks to Ruby’s super powerful meta-programming mechanism, so I can forward the unknown message to prototype by using method_missing. And I encapsulate the code in a module, so every instance extended that module will obtain such capability.

Prototype Module
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
module Prototype
def inherit_from(prototype)
@prototype = prototype
self
end
def create_child
Object.new.extend(Prototype).inherit_from(self)
end
def respond_to?(msg_id, priv = false)
return true if super
if @prototype
@prototype.respond_to?(msg_id, priv)
else
false
end
end
def method_missing(symbol, *args, &block)
if @prototype
@prototype.send(symbol, *args, &block)
else
super
end
end
def self.new
Object.new.extend(Prototype)
end
end

If I have the following code:

Prototype Inheritance
1
2
3
4
5
6
7
8
9
10
11
12
13
a = Object.new
def a.foo
'foo'
end
b = Object.new
b.extend(Prototype).inherit_from(a)
c = b.create_child
p b.foo # => 'foo'
p c.foo # => 'foo'

So b.foo and c.foo will yield ‘foo’.

And I can override the parent implementation by refine a method with the same name:

Prototype Overrides
1
2
3
4
5
6
7
8
9
10
11
def a.bar
'bar'
end
def c.bar
'c.bar'
end
p a.bar # => 'bar'
p b.bar # => 'bar'
p c.bar # => 'c.bar'

So I add a new singleton method bar in a, and b automatically inherits the method, and I override the bar on object c.

As a conclusion that we’re able to introduce the prototype based inheritance in ruby by using ruby’s powerful meta-programming mechanism. This implementation is only for concept-proof, so its performance is not quite good. But we can try to improve the performance by consolidating process by defining the method dynamically. The child object will query the parent for the first time, if invoking succeeded then it can consolidate the behavior into a method to avoid calling method_missing every time.

Ruby Class Inheritance

I just realize I have misunderstood the ruby “class methods” for quite a long time!

Here is a piece of code:

Instance Methods Inheritance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
class A
def foo
'foo'
end
end
class B < A
end
a = A.new
b = B.new
a.foo.should == 'foo'
b.foo.should == 'foo'

The previous piece of code demonstrated the typical inheritance mechanism in almost every Class-Object style OO language (There are a few exceptions, which are Prototype inheritance. Such as JavaScript, but it is also a miracle that whether Javascript is OO language XD).
In most common OO languages, this is what inheritance about! But in Ruby, things is not that easy! Great thanks to Ruby’s eigen-class (aka Singleton class or Metaclass)

In ruby, I just found that derived class not just inherits the instance methods but also the class methods! It is kind of surprise to me!

Class Methods Inheritance
1
2
3
4
5
6
7
8
9
10
11
class A
def self.bar
'bar'
end
end
class B < A
end
A.bar.should == 'bar'
B.bar.should == 'bar'

For most people who knows Java or C# or even C++, who won’t be surprised about A.bar.should == 'bar', but you might feel surprised about B.bar.should == 'bar' like I do.

To me, bar is declared on class A, B inherits A, than I can even call method declared on class A on class B! It is amazing!

Since in ruby, “class method” is actually the instance method of the eigen-class of the class. And def self.foo is just a syntax sugar. So we can rewrite the code as:

Rewriten Class Methods Inheritance
1
2
3
4
5
6
7
8
9
10
11
12
13
14
class A
end
class B < A
end
class << A
def bar
'bar'
end
end
A.bar.should == 'bar'
B.bar.should == 'bar'

If we call A’s eigen-class AA, and B’s eigen-class BB. Then we will found that BB.superclass == AA

BB and AA
1
2
3
4
5
6
7
8
9
10
11
class A; end
class B < A; end
AA = class << A; self; end
BB = class << B; self; end
B.superclass.should == A
BB.superclass.should == AA

And we know A is actually an instance of AA, and B is an instance of BB, so obviously on B we can call the instance methods defined on AA.
That’s the reason why class method in Ruby can be inherited!

But there are so inconsistency in Ruby, that AA is the superclass of BB, but you won’t be able to found AA in BB‘s ancestors! In fact, BB.ancestors might yield something similar to [Class, Module, Object, BasicObject, Kernel] if not any module is injected to Class, Module, Object

Inconsistency
1
2
3
4
5
6
7
8
9
10
11
12
class A; end
class B < A; end
AA = class << A; self; end
BB = class << B; self; end
BB.superclass.should == AA
BB.ancestors.should_not includes AA
# BB.ancestors == [Class, Module, Object, BasicObject, Kernel]

This design is wield to me, and kind of hard to understand, so for quite a long time, I don’t even know class methods in ruby can be inherited!
I drew a graph to show the relationship about the classes, in graph I use <class:A> to indicate the class is the eigen class of A. And the line with a empty triangle to represents the inheritance, and arrow line to represents the instantiation.
And this graph is not a complete one, I omitted some unimportant classes, and I uses the dot line to indicate that something is missing on the line.

Inheritance Hierarchy

pitfall when return string in via json in rails

Today we met a weird problem when return a string via json.

Here is the coffee script code:

Front End
1
2
3
4
$.post serverUrl, data, (status) ->
console.log status

And here is our controller:

Backend Action
1
2
3
4
5
6
7
def action
# do some complex logic
render json: "success"
end

Code looks perfect, but we found that the callback is never called! When we check the network traffic, you will found that server does send its response “success”, but the callback is not called!

After spending half an hour to struggle against the jQuery, we finally find the problem!

The reason is that success is not a valid json data! A valid json string should be quoted with “”, or JSON parser will treat it as token, like true or false or nil.

So to fix the problem, we need to change our action code:

Fixed Backend Action
1
2
3
4
5
6
7
def action
# do some complex logic
render json: '"success"'
end

This is really a pitfall, since the wrong code looks so nature!

Pretty Singleton in RoR app

Thanks to Ruby powerful meta programming capability and Rails delegate syntax, we can easily write graceful singleton class which makes the class works like a instance.

In traditional language such as C#, usually we write singleton code like this:

Singleton in C##
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
class Foo
{
// Singleton Declaration
private static readonly Foo instance;
pubilc static Foo Instance
{
get
{
if(instance == null)
{
instance = new Foo();
}
return instance;
}
}
// Define instance behaviors
// ...
}

The previous approach works fine but the code that uses Foo will be kind of ugly. Every time when we want to invoke the method Bar on Foo, we need to write Foo.Instance.Bar() rather than more graceful way Foo.Bar().
To solve this problem we need implement the class in this way:

Class Delegation in C##
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
class Foo
{
// Singleton Declaration
// ...
// Define instance behaviors
public void Bar()
{
// Bar behaviors
// ...
}
public static void Bar()
{
Instance.Bar();
}
public string Baz
{
get { /* Getter behavior */ }
set { /* Setter behavior */ }
}
public static string Baz
{
get { return Instance.Baz; }
set { Instance.Baz = value; }
}
}

This approach simplified the caller code but complicated the declaration. You can use some trick such as Code-Snippet or code generating technology such as Text Template or CodeSmith to generate the dull delegation code. But it is still not graceful at all.

If we write same code in ruby, things become much easier, great thanks to Ruby’s powerful meta programming capability.

Singleton in Ruby
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
# foo.rb
class Foo
extend ActiveSupport::Autoload
autoload :Base
include Base
autoload :ClassMethods
extend ClassMethods
end
# foo/base.rb
module Foo::Base
# Define instance behaviors
# ...
end
# foo/class_methods.rb
module Foo::ClassMethods
# Singleton Declaration
def instance
@instance ||= new
end
delegate *Foo::Base.instance_methods, :to => :instance
end

So in ruby solution we just use one statement delegate *Foo::Base.instance_methods, :to => :instance then delegate all methods defined in base to instance.

Besides this solution, there is also another kind of cheaper but working solution:

Singleton in Ruby
1
2
3
4
5
6
7
8
9
10
11
12
13
14
# foo.rb
class Foo
autoload :Base
include Base
extend Base
end
# foo/base.rb
module Foo::Base
# Define instance behaviors
# ...
end

Two different approaches make the code behaves slightly different, but anyway they both works.

Extend RSpec DSL

I’m working on a project that need some complicated html snippets for test, which cannot be easily generated with factory. So I put these snippets into fixture files.

RSpec provides a very convenient DSL keyword let, which allow us to define something for test and cached it in the same test. And I want I could have some similar keyword for my html fixtures. To achieve this goal I decide to extend DSL.

So I created module which contains the new DSL I want to have:

DSL module
1
2
3
4
5
6
7
8
9
10
11
# spec/support/html_pages.rb
module HtmlPages
def load_html(name)
let name do
file = Rails.root.join('spec/html_pages', "#{name}.html")
Nokogiri::Html File.read(file)
end
end
end

Put this file into the path spec/support, by default, spec_helper.rb would require this file for you.
Then we should tell rspec to load the DSL into test cases.

Load DSL
1
2
3
4
5
RSpec.configure do |config|
# ...
config.extend HtmlPages
# ...
end

By telling config to extend the module, our DSL will be loaded as the class methods of RSpec::Core::ExampleGroup, where let is being defined.

HINT: Rspec config has another way to extend DSL by calling config.include. Then the DSL methods will be injected into the test example group instance, then these methods can be used in the test cases. That’s how runtime DSLs like FactoryGirl work.