Thursday, August 19, 2010

Back to Basics

Enough is enough, i seriously don’t think i’m built to use any online blogging engines. Simply because i’m built to prefer typing in my terminal, using vim, and prefer playing with terminal-interfaced stuff, instead of so called idiot-proof online tools … i guess i’m probably more idiot than idiots.

Moreover, blogspot is blocked by the great wall of china (at least this is what i’ve encountered in shanghai), and though i can continue to access it via some customized proxy settings, it is terribly slow, slow & slow. In fact, i find it amazing that i am able to bear with it for so long …

Anyway, enough is enough, here i am, back to basics, typing my blog in vim, on the engine side, i’m using the git-based blogging engine shinmun, and deploying it at heroku

Ha, it cannot be any easier than what i have now … what a wonderful world !!

(i'm gradually do the migration to the newer blog, as and when i find time)

Friday, August 13, 2010

Benchmarking any rake task

While writing serializable_proc, i wanted to find out how the RubyParser-based implementation fair against ParseTree-based one, here's a rake task i've written to support the following use cases:

# yield benchmark results by running :spec task x5 (default)
$ rake benchmark[spec]

And:

# yield benchmark results by running :spec task x2
$ rake benchmark[spec,2]

And here's the code to acheive the above:
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
# Benchmarking
task :benchmark, :task, :times do |t, args|
times, task = (args.times || 5).to_i.method(:times), args.task
title = " ~ Benchmark Results for Task :#{task} ~ "
results = [%w{nth}, %w{user}, %w{system}, %w{total}, %w{real}]

# Running benchmarking & collecting results
require 'benchmark'
times.call do |i|
result = Benchmark.measure{ Rake::Task[task].execute }.to_s
user, system, total, real =
result.match(/^\s*(\d+\.\d+)\s+(\d+\.\d+)\s+(\d+\.\d+)\s+\(\s*(\d+\.\d+)\)$/)[1..-1]
["##{i.succ}", user, system, total, real].each_with_index{|val, j| results[j] << val }
end

# Formatting benchmarking results
formatted_results = results.map do |rs|
width = rs.map(&:to_s).map(&:size).max
rs.map{|r| ' ' + r.ljust(width, ' ') }
end.transpose.map{|row| row.join }

# Showdown .. printout
line = '=' * ([title.size, formatted_results.map(&:size).max].max + 2)
puts [line, title, formatted_results.join("\n"), line].join("\n\n")

end

And here's the output i get for the x2 run:

...
(blah blah, the output of running :spec task x2)
...
===============================================

~ Benchmark Results for Task :spec ~

nth user system total real
#1 0.000000 0.000000 1.030000 1.052567
#2 0.000000 0.000000 1.020000 1.040352

===============================================

Friday, August 6, 2010

Reliably getting a formatted time string in ur desired lang

Today, i'm spent quite abit of time playing with the very simple Time#strftime:
1
2
puts Time.now.strftime("%B %d, %Y %H:%M")
# >> August 06, 2010 17:17

What i want to acheive is to reliably get the chinese version:

八月 06, 2010 17:24

I've tried playing with the environment variable $LANG:

$ export LANG=zh_CN.utf8
$ locale
LANG=zh_CN.utf8
LC_CTYPE="zh_CN.utf8"
LC_NUMERIC="zh_CN.utf8"
LC_TIME="zh_CN.utf8"
LC_COLLATE="zh_CN.utf8"
LC_MONETARY="zh_CN.utf8"
LC_MESSAGES="zh_CN.utf8"
LC_PAPER="zh_CN.utf8"
LC_NAME="zh_CN.utf8"
LC_ADDRESS="zh_CN.utf8"
LC_TELEPHONE="zh_CN.utf8"
LC_MEASUREMENT="zh_CN.utf8"
LC_IDENTIFICATION="zh_CN.utf8"
LC_ALL=

Seems good, but nope, Time#strftime still gives me the same english output. I've trying recompiling a different ruby using rvm with the exported $LANG ... nope, doesn't work either. It seems that not matter how $LANG is set (thus affecting LC_TIME), ruby just doesn't care abt it. Yet, i swear that on flyhzm's machine, he has been getting the chinese version, no matter how hard he has tried to get the english version.

Battled, beaten & worn out, i've concluded that the most reliable way (and definitely what most people do), is to use the i18n. Given i already have this /path/to/i18n.yml:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
en:
date:
month_names: [~, January, February, March, April, May, June, July, August, September, October, November, December]

time:
formats:
default: "%B %d, %Y %H:%M"

zh:
date:
month_names: [~, 一月, 二月, 三月, 四月, 五月, 六月, 七月, 八月, 九月, 十月, 十一月, 十二月]

time:
formats:
default: "%B %d, %Y %H:%M"

The following works for mri 1.9.1:
1
2
3
4
5
6
7
8
9
10
11
require 'rubygems'
require 'i18n'

I18n.load_path << '/tmp/i18n.yml'
p I18n.available_locales # >> [:en, :zh]

I18n.locale = :en
p I18n.localize(Time.now) # >> "August 06, 2010 17:48"

I18n.locale = :zh
p I18n.localize(Time.now) # >> "八月 06, 2010 17:48"

Without modication, i got the following unfriendly output for the chinese port under mri 1.8.7, jruby & ree-1.8.7:

\345\205\253\346\234\210 06, 2010 20:27

After much googling, stumbled across this post abt $KCODE. Here's the final modified code for the 1.8.7 equivalents:
1
2
3
4
5
6
7
8
9
10
require 'rubygems'
require 'i18n'

$KCODE = 'UTF-8' # Hey, this matters !!

I18n.locale = :en
p I18n.localize(Time.now) # >> "August 06, 2010 17:48"

I18n.locale = :zh
p I18n.localize(Time.now) # >> "八月 06, 2010 17:48"

For people doing rails, here are some useful resources:
* http://guides.rubyonrails.org/i18n.html
* http://github.com/svenfuchs/rails-i18n

Wednesday, August 4, 2010

Bitten by Array#*

Have u tried Array#* ? Its a pretty cool way to return an array, built by concatenating the original array by n times:
1
2
3
4
5
a = [1] * 2
p a # >> [1, 1]

a = %w{a} * 2
p a # >> ["a", "a"]

However, u should be aware that all elements of the new array actually points to the same instance, as proven by their object_id:
1
2
3
4
5
x = 'a'
p x.object_id # >> 70212363949780

a = [x] * 2
p a.map(&:object_id) # >> [70212363949780, 70212363949780]

This means that:
1
2
3
4
5
6
7
8
9
10
11
12
13
# Reassigning one element does not affect another
a = %w{a} * 2
p a.map(&:object_id) # >> [70058328018360, 70058328018360]
a[0] = a[0].sub('a','b')
p a # >> ["b", "a"]
p a.map(&:object_id) # >> [69915340242120, 69915340242360]

# In-place manipulating one element affects another
a = %w{a} * 2
p a.map(&:object_id) # >> [70058328018360, 70058328018360]
a[0].sub!('a','b')
p a # >> ["b", "b"]
p a.map(&:object_id) # >> [70058328018360, 70058328018360]

Wednesday, July 28, 2010

Lazy evaluating with Enumerable#any?

Most of us know this:
1
2
3
4
5
6
7
8
class Awesome
def self.m1 ; true ; end
def self.m2 ; raise Exception ; end
end

# Case 1:
Awesome.m1 or Awesome.m2
# >> no error thrown

For some of us who likes Enumerable#any?, this won't work:
1
2
3
# Case 2:
[Awesome.m1, Awesome.m2].any?
# >> error thrown

That is because :m1 & :m2 are already evaluated before calling Enumerable#any?, to have lazy evaluation, we can do this:
1
2
3
# Case 3:
[:m1, :m2].any?{|m| Awesome.send(m) }
# >> no error thrown

For the perversive ones:
1
2
3
# Case 4:
Awesome.instance_exec { [:m1, :m2].any?{|m| send(m) } }
# >> no error thrown

Thursday, July 22, 2010

Everyone should start writing macros

Did some cleaning & catching up of specs for railsbestpractices.com yesterday, added quite a number of spec macros to dry up stuff, as well as cutting down the complexity within the spec files. Personally, i really really & really like macros, because it is fun to write & easy to write, it has many beneficial side effects:

#1. Since it is so simple to use macros, everyone in the team is more willing to participate in spec writing. Personal experience has proven that if specs/tests are hard to write, some developers tend to skip it.

#2. Since it is so easy to read, maintenance becomes much easier

#3. Developers are smart people (and should be paid well, but that's another story), by replacing repeated copy & paste & minor edit-here-and-there with macros-writing-and-usage, they feel smarter, a huge morale boast ~> happier team, & when people are happy, they tend to show more love towards the project, take ownership ~> project in a better state.

Btw, macro writing is no rocket-science, let's get started:

#1. Macro for 3rd party declarative
1
2
3
4
class User < ActiveRecord::Base
acts_as_authentic
# (blah blah)
end

Ok, we all know that authlogic is well tested, so there is really no point in writing specs for it. Yet, how do we know the model is pulling in authlogic support ?? Here's what i've done:
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
module RailsBestPractices
module Macros

def self.included(base)
base.extend(ClassMethods)
end

module ClassMethods

def should_act_as_authentic
# Get most basic modules included by ActiveRecord::Base
basic_included_modules = Class.new(ActiveRecord::Base).included_modules

# Grab the model class
model = description.split('::').inject(Object){|klass,const| klass.const_get(const) }

# Get the extra modules included by the model
model_included_modules = model.included_modules
extra_modules = (model_included_modules - basic_included_modules).map(&:to_s)

# As long as we have any extra module matching the regexp, we can conclude that
# :acts_as_authentic has been declared for the model
extra_modules.any?{|mod| mod =~ /Authlogic::ActsAsAuthentic::/ }.should be_true
end

end

end
end

The usage in the spec file is:
1
2
3
4
5
describe User do
include RailsBestPractices::Macros
should_act_as_authentic
# (blah blah)
end

Of course, i can probably remove the include statement altogether & do the auto-including elsewhere, but taking this route, other developers may throw WTF-is-should_act_as_authentic error ~> BAD !!

#2. Macro for project-specific declarative
1
2
3
4
class Post < ActiveRecord::Base
include Markdownable
# (blah blah)
end

I wanna make sure the support from the home-baked Markdownable is pulled in. Since it is home-baked, just making sure the module is mixed in is not good enough, i need to ensure the functionality is there as well. Thus (nested within the above mentioned RailsBestPractices::Macros::ClassMethods module):
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
def should_be_markdownable

# Determine which factory to call
factory_id = description.split('::').inject(Object){|klass, const| klass.const_get(const) }.
to_s.tableize.singularize.to_sym

# Generate an example group
describe "being markdownable" do

it "should generate simple markdown html" do
raw = "subject\n=======\ntitle\n-----"
formatted = "<h1>subject</h1>\n\n<h2>title</h2>\n"
Factory(factory_id, :body => raw).formatted_html.should == formatted
end

it "should generate markdown html with <pre><code>" do
raw = "subject\n=======\ntitle\n-----\n def test\n puts 'test'\n end"
formatted = "<h1>subject</h1>\n\n<h2>title</h2>\n\n<pre><code>def test\n puts 'test'\nend\n</code></pre>\n"
Factory(factory_id, :body => raw).formatted_html.should == formatted
end

end
end

And the usage:
1
2
3
4
5
describe Post do
include RailsBestPractices::Macros
should_be_markdownable
# (blah blah)
end

#3. Macro for any other vanilla functionality
1
2
3
4
5
class Implementation < ActiveRecord::Base
def belongs_to?(user)
user && user_id == user.id
end
end

The macro definition:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
def should_have_user_ownership
factory_id = description.split('::').inject(Object){|klass,const| klass.const_get(const) }.
to_s.tableize.singularize.to_sym

describe 'having user ownership' do

it 'should belong to someone if he is the owner of it' do
someone = Factory(:user)
Factory(factory_id, :user => someone).belongs_to?(someone).should be_true
end

it 'should not belong to someone if he is not the owner of it' do
someone = Factory(:user)
Factory(factory_id).belongs_to?(someone).should be_false
end

end
end

Finally, the usage:
1
2
3
4
describe Implementation do
include RailsBestPractices::Macros
should_have_user_ownership
end

Of course, it doesn't make sense to define macro for every functionality available. The general thumb of rule is that when similar code appears more than once, u can consider defining a macro for it. However, if similar-code is to appear more than once, u will probably start by extracting the code & placing it inside a module (eg. Markdownable), so this probably falls under #2. Macro for project-specific declarative.

Last but not least, the above macro definition can probably benefit from some refactoring, but i guess i'll leave this exercise to u :]

Wednesday, July 21, 2010

Relatively unknown Object#instance_exec

Do u happen to know Object#instance_eval's brother, Object#instance_exec ?? Here's a uninteresting way of coding wo Object#instance_exec:
1
2
3
4
5
6
7
8
9
10
11
12
Someone = Struct.new(:name, :password)

greet = lambda do |someone|
puts "Hey %s, no worries, i won't tell anyone ur password is '%s' !!" % [
someone.name, someone.password
]
end

greet[Someone.new('Peter', 'aabbcc')]
# >> Hey Peter, no worries, i won't tell anyone ur password is 'aabbcc' !!
greet[Someone.new('Jane', 'bbccdd')]
# >> Hey Jane, no worries, i won't tell anyone ur password is 'bbccdd' !!

And here's a more interesting way to do it, w Object#instance_exec:
1
2
3
4
5
6
7
8
9
10
11
12
Someone = Struct.new(:name, :password)

greet = lambda do
puts "Hey %s, no worries, i won't tell anyone ur password is '%s' !!" % [
name, password
]
end

Someone.new('Peter', 'aabbcc').instance_exec(&greet)
# >> Hey Peter, no worries, i won't tell anyone ur password is 'aabbcc' !!
Someone.new('Jane', 'bbccdd').instance_exec(&greet)
# >> Hey Jane, no worries, i won't tell anyone ur password is 'bbccdd' !!

Yet another way to do it can be:
1
2
3
4
5
6
7
8
9
10
Someone = Struct.new(:name, :password)
greet = lambda{|msg| puts msg % [name, password] }

Someone.new('Peter', 'aabbcc').
instance_exec("Hey %s, no worries, i won't tell anyone ur password is '%s' !!", &greet)
# >> Hey Peter, no worries, i won't tell anyone ur password is 'aabbcc' !!

Someone.new('Jane', 'bbccdd').
instance_exec("Hey %s, i'm glad that u entrust me with ur password '%s' !!", &greet)
# >> Hey Jane, i'm glad that u entrust me with ur password 'bbccdd' !!

Enjoy !!

Stubbing only the nth instance's method, should or shouldn't ?

A few days back, cross-stub version 0.2.0 has been released, with this release, cross process instance method stubbing is now possible. While doing review of zan's work, we've discussed the possibility of having more control on which exact instance the stub should be applied to, as illustrated below:
1
2
Time.xstub(:day, :instance => 1)    # applies to ONLY 1st Time instance
Time.xstub(:day, :instance => 2..3) # applies to ONLY 2nd ~ 3rd Time instances

Initially, i was quite happy to have brought up this. But after some thinking, i'm convinced that this a LOUSY idea, as it requires the user to have intimate knowledge of how many times a class's instance have been created, which can be tedious (if not impossible) if the instance method is provided by ruby core/std libs, or popular gems. It also results in extremely brittle tests, as nth can easily beconme xth, or zth ...

I think the issue is very fundamental, it goes down to how the code is written. Given the following example:
1
2
3
4
5
6
7
8
9
10
11
12
13
  class Papa
def free_today?
# Any papa is free on weekend but not weekday
!Time.now.strftime('%w').between?(0,5)
end
end

class Mama
def free_today?
# Any mama is free on weekday but not weekend
Time.now.strftime('%w').between?(0,5)
end
end

If i were to apply stubbing for Time#strftime, i would affect both Papa#free_today? & Mama#free_today?. Taking one step back, if we to affect only Papa#free_today?, we need to consider the context where the Time#strftime stub is-to-be applied, & do the following revision:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
class Papa

def free_today?
!today_dow.between?(0,5)
end

def today_dow
Time.now.strftime('%w')
end

end

class Mama

def free_today?
today_dow.between?(0,5)
end

def today_dow
Time.now.strftime('%w')
end

end

Therefore, by stubbing Papa#today_dow, we won't affect Mama#free_today?. Moreover, taking this approach gives us the chance to do some cleaning up:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
class Parent
def today_dow
Time.now.strftime('%w')
end
end

class Papa < Parent
def free_today?
!today_dow.between?(0,5)
end
end

class Mama < Parent
def free_today?
today_dow.between?(0,5)
end
end

Imagine if we go the other approach of doing nth instance's method stubbing, though feasible, the test will be extremely brittle (nightmarish maintenance), as nth can easily be changed to xth, or zth.

CONCLUSION: No, we don't need better control over nth instance's method stubbing, cross-stub's instance method stubbing is going to remain as it is. If u need it, drop me a mail with an example to justify the need :]

Sunday, July 18, 2010

Tidying up specs suite with otaku

In the specs suite of cross-stub, i've built a custom echo server using this approach to support testing of stubbing in another process. Nothing wrong with it, except that it is not so fun & clean. Anyway, over the weekend, i've extracted out the echo server code, and put it inside a new & fun project otaku.

Here's my tidied up specs (which serve as a good example usage of otaku):
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
33
34
shared 'has other process setup' do

behaves_like 'has standard setup'

before do
# Don't start the service if it has already been started.
$service_started ||= (
Otaku.start do |data|

# Pull in all the helpers, __FILE__ magically converts to path of this file,
# even after otaku's internal marshalling/unmarshalling.
require File.join(File.dirname(__FILE__), '..', 'includes')

# Some processing ... using helpers & class definitions pulled in by the above
# require statement.
store_type, method_call_args = data.match(/^(.*?)\/(.*)$/)[1..2]
CrossStub.refresh(cache_store($prev_store_type)) if $prev_store_type
CrossStub.refresh(cache_store($prev_store_type = store_type))

# Actually capturing of error is not necessary, cos Otaku captures any error &
# wrap it up in Otaku::DataProcessError.
do_local_method_call(method_call_args) rescue $!.message
end

true
)
end

end

at_exit do
# Stops otaku if it has been started, only this process is abt to exit.
$service_started && Otaku.stop
end

Building a simple server/client with eventmachine 2

Following previous entry, i've come up with a drop dead simple service framework based on eventmachine, just a fun project actually, as u can see from its name "OTAKU". Since code speaks a thousand words, especially for someone like me, let's jump straight into some coding:
1
2
3
4
5
6
require 'otaku'

# Starting to otaku service
Otaku.start do |data|
result = '~ %s ~' % data
end

1
2
3
4
require 'otaku'

# client sending a process request to otaku service
Otaku.process('hello') # >> '~ hello ~'

Of course, life is never as simple as the above, since we have Otaku.start accepts a proc, most people tend to code in-a-taken-for-granted-way taking advantage of contextual references:
1
2
3
4
5
6
mark = '*'
Otaku.start do |data|
'%s %s %s' % [mark, data, mark]
end

Otaku.process('hello') # #<NameError: undefined local variable or method `mark' for ...

Now now, really unexpected rite ? The reason is that otaku converts the proc passed to Otaku.start, convert it to plain ruby code, & eval in the server process, thus, naturally, any contextual references are lost. As a workaround:
1
2
3
4
5
Otaku.start(:mark => '*') do |data|
'%s %s %s' % [mark, data, mark]
end

Otaku.process('hello') # >> '* hello *'

Well, i must admit this workaround is abit not-so-comfortable ... anyway, i'm still thinking (hard) on how the contextual references can be extracted under the hood, without having user to go through the trouble of declaring the context hash explicitely. Anyway, this is what otaku has to offer for now :]

Have a look at this slightly more complicated usage of otaku.

Thursday, July 15, 2010

Building a simple server/client with eventmachine

In writing cross-stub, i need to write specs to ensure cross process stubbing indeed work as expected. This is achieved by building a simple server/client using eventmachine, here's how echo_server.rb looks like:
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
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
require 'rubygems'
require 'eventmachine'
require 'logger'
require 'base64'

module EchoServer

ADDRESS = '127.0.0.1'
PORT = 10999
LOG_FILE = '/tmp/echo_server.log'
INIT_WAIT_TIME = 2 # may need to increase this depending on how slow is ur machine

class << self

def log(*msg)
(@logger ||= Logger.new(LOG_FILE)) << [msg, ""].flatten.join("\n")
end

def cleanup
@logger.close
end

def start(other_process=false)
unless other_process
print 'Starting echo service ... '
@process = IO.popen("ruby #{__FILE__}",'r')
sleep INIT_WAIT_TIME
puts 'done (pid#%s)' % @process.pid
else
log 'Echo service (pid#%s) listening at %s:%s' % [Process.pid, ADDRESS, PORT]
EventMachine::run { EventMachine::start_server(ADDRESS, PORT, EM) }
end
end

def stop
Process.kill('SIGHUP', @process.pid) if @process
end

end

private

module EM

def receive_data(data)
log 'Received client data: %s' % data.inspect
result = process_data(data)
log 'Processed to yield result: %s' % result.inspect
send_data(Base64.encode64(Marshal.dump(result)))
end

def process_data(data)
# do some meaningful processing to yield result
result = '~ processed %s ~ ' % data
end

def log(*msg)
EchoServer.log(*msg)
end

end

end

if $0 == __FILE__
begin
EchoServer.start(true)
rescue
EchoServer.log "#{$!.inspect}\n"
ensure
EchoServer.cleanup
end
end

And echo_client.rb:
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
33
34
35
36
37
# Keeping things DRY, avoid repeated typing of requiring statements &
# server specific info (eg. address & port)
require File.join(File.dirname(__FILE__), 'echo_server')

module EchoClient

ADDRESS = EchoServer::ADDRESS
PORT = EchoServer::PORT

class << self
def get(data)
EventMachine::run do
EventMachine::connect(ADDRESS, PORT, EM).execute(data) do |data|
@result = Marshal.load(Base64.decode64(data))
end
end
@result
end
end

private

module EM

def receive_data(data)
@callback.call(data)
EventMachine::stop_event_loop # ends loop & resumes program flow
end

def execute(method, &callback)
@callback = callback
send_data(method)
end

end

end

And finally the example usage:
1
2
3
4
5
6
7
8
9
10
require File.join(File.dirname(__FILE__), 'echo_server')
require File.join(File.dirname(__FILE__), 'echo_client')

EchoServer.start

10.times do |i|
puts EchoClient.get(i)
end

EchoServer.stop

Personally, i prefer placing the server & client code inside a single file echo_service.rb, since the client code is pretty coupled with the server code. One gotcha i've encountered while working with this server/client thingy is that error in the server hangs the client, that's why having the server log file is really useful in debugging.

Marshal/Unmarshal problem with Jruby

While working on cross-stub today, ran into a marshal/unmarshal problem with jruby, caused by binary string encoding issue. Anyway, let's start by taking a look at some code:
1
2
3
4
5
6
time1 = Time.now
time2 = Marshal.load(
%|#{Marshal.dump(time1).gsub('|','\|')}|
)

puts time1 == time2

Here's what i got when running the above in different rubies:

#1. The expected output of Ruby 1.8.7 & Ruby 1.9.1 & Ree 1.8.7
# >> true


#2. The unexpected output of Jruby-1.5.1
# >> (eval):1:in `_load': marshaled time format differ (TypeError)

Did quite abit of research, either my googling skill sucks, or nobody has the same problem as me ... yet eventually found something at stackoverflow, which lights up the bulb, & here's the amended code that works for all the above-mentioned rubies:
1
2
3
4
5
6
7
8
9
require 'base64'

time1 = Time.now
time2 = Marshal.load(
Base64.decode64(
%|#{Base64.encode64(Marshal.dump(time1)).gsub('|','\|')}|
))

puts time1 == time2

Wednesday, July 14, 2010

Minimalist ... even more minimal than BasicObject

In cross-stub, it is possible to declare stubs using a proc:
1
2
3
4
5
  Someone.xstub do
def say(something)
'saying "%s"' % something
end
end

Implementation wise, i need a way to find out the methods delared within the proc in order to do further processing. The most straight-forward way is to have a bare minimum object, after instance_eval of the proc, do a diff of the original set of instance methods & the set of methods for this manipulated object. The following illustrates the concept:
1
2
(minimalist = Minimalist.new).instance_eval(&block)
minimalist.methods - Minimalist.instance_methods

Well, i've in fact considered using BasicObject, but then, it doesn't appear to be as basic as i hope it should it. Thus i decided to handroll my own Minimalist solution:
1
2
3
4
5
class Minimalist
alias_method :__instance_eval__, :instance_eval
alias_method :__methods__, :methods
instance_methods.each{|meth| undef_method(meth) if meth.to_s !~ /^__.*?__$/ }
end

As u can see (in order to prevent any methods clash with user-defined-to-be-stubbed-methods) what i've done is just:

#1. renaming instance_eval & methods to the more cryptic __instance_eval__ & __methods__, and
#2. undefining all methods, except those with prepending & appending __

It works well in ruby-1.8.7, but then, running the above in ruby-1.9.1 displays the following warning:

warning: undefining `object_id' may cause serious problem

With the solution suggested in this discussion, Minimalist is revised to:
1
2
3
4
5
6
7
class Minimalist
alias_method :__instance_eval__, :instance_eval
alias_method :__methods__, :methods
$VERBOSE = nil
instance_methods.each{|meth| undef_method(meth) if meth.to_s !~ /^__.*?__$/ }
$VERBOSE = true
end

Now the warning doesn't show. Yet in ruby-1.8.7, i got plenty of eval warnings:

(eval):1: warning: discarding old say
(eval):1: warning: discarding old say
(eval):1: warning: method redefined; discarding old bang

Hmmm ... undaunted, i got this final version of Minimalist:
1
2
3
4
5
6
7
class Minimalist
alias_method :__instance_eval__, :instance_eval
alias_method :__methods__, :methods
orig_verbosity, $VERBOSE = $VERBOSE, nil
instance_methods.each{|meth| undef_method(meth) if meth.to_s !~ /^__.*?__$/ }
$VERBOSE = orig_verbosity
end

Yet for jruby-1.5.1, it yields:

warning: `instance_eval' should not be aliased

The final final final (i promise) Minimalist becomes:
1
2
3
4
5
class Minimalist
orig_verbosity, $VERBOSE = $VERBOSE, nil
# (method aliasing & removal stays here)
$VERBOSE = orig_verbosity
end

Saturday, July 10, 2010

Painless inserting of nicely highlighted code block to my blog

If u happen to like the way i display code blocks in this blog & have read my previous post abt how i have given this blog a face-lifting, here are some extra steps i've taken to conveniently allow me to:

# 1. edit whatever code i want to display in vim

# 2. use a user-defined command (while still in vim) :Xc to process the entire (or selected lines) of the current buffer to yield nicely-highlighted code block & load it to the X11 clipboard (using xclip)

# 3. use middle mouse click (hehe, i'm using thinkpad, anyway, this can be done by doing left & right click together on mouse) to paste it to whereever i like (eg. the textarea i'm typing in right now)

Enough said, let's get into action:

# S1. Installing the required packages:

pacman -S xclip

# S2. Inserting the user-defined command :Xc to ~/.vimrc
1
2
3
4
5
func! Xclip() range
execute ":!~/bin/code2html.rb " . bufname('%') . " " . a:firstline . ":" . a:lastline . " | xclip"
endfu

com! -range=% -nargs=0 Xc <line1>,<line2>call Xclip()

# S3. Revising the existing ~/bin/code2html.rb to accept extra args
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
#!/usr/bin/env ruby

require 'rubygems'
require 'coderay'
require 'tempfile'

file = ARGV[0]
range = ARGV[1].split(':').map(&:to_i).map(&:pred) rescue nil

if range
basename = Time.now.to_i.to_s
extension = file[/\/.*?.(\.[^\.]*?)$/,1]
Tempfile.open(extension ? [basename, extension] : basename) do |fh|
fh.write(File.readlines(file)[range[0] .. range[-1]].join)
file = fh.path
end
end

puts %|#{coderay.scan_file(file).html(:line_numbers => :table)}|.
gsub('coderay','coderay').split('<pre').map{|s|
!s.include?('</pre>') ? s.gsub("\n",'').squeeze(' ') : (
parts = s.split('</pre>')
[parts[0], parts[1].gsub("\n",'').squeeze(' ')].join('</pre>')
)
}.join('<pre')

To try out, restart ur vim to edit any file, to convert the entire file, run the following command in vim:

:Xc

Alternatively, if u want to convert the selected lines (in visual mode, using Shift-v to select the specific lines):

:'<,'>Xc

And to do the pasting, just do middle (mouse) click on any textarea u are working on.

Turning off the irritating beep

# 1. Console beep:

xset b off
xset -b
xset b 0

# 2. Firefox Beep

Goto ‘about:config’, search for ‘accessibility.typeaheadfind.enablesound’ & set it to ‘false’.

Hand-rolling screenshot taking solution

Here's my handrolled solution for taking screenshot on my arch linux, using imagemagick, feh & xbindkeys for taking & displaying the just-taken screenshot on my arch linux:

# 1. Installing the required packages

pacman -S xbindkeys feh imagemagick

# 2. Scripting ~/bin/take-screenshots
1
2
3
4
5
6
7
8
#!/bin/bash

dir=~/pictures/screenshots
[ -d $dir ] || mkdir -p $dir

file=${dir}/`ls ${dir} | wc -l`.png
import -window root ${file}
feh $file

#3. Inserting the <PrtSc> key binding in ~/.xbindkeysrc
1
2
3
"~/bin/take-screenshots"
m:0x0 + c:107
Print

Restart ur X server & pressing <PrtSc> should pop up the just-taken screenshot.

Friday, July 9, 2010

New Face New Look

Finally given this blog a face-lifting. Well, 99.9% of the credit goes to (1) coderay, (2) syntax highlighting railscast, & (3) the new template designer of blogger.com, while the rest falls under some minor hackish tweaking on my part. Anyway, here's the fragment that customizes the blog template:
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
33
<style type='text/css'>
code, table.coderay {
background-color: #111111;
color: #E6E0DB;
overflow: auto;
display: block;
margin: 15px 0px 0px 0px;
padding: 0px 20px 15px 20px;
-moz-border-radius:10px;
-webkit-border-radius:10px;
}
table.coderay { padding: 0px 20px 0px 0px; }
table.coderay td.line_numbers { color: #444444; padding: 0px 5px 0px 8px; }
table.coderay td.code { padding-left: 5px; }
table.coderay .an { color:#E7BE69 } /* html attribute */
table.coderay .c { color:#BC9358; font-style: italic; } /* comment */
table.coderay .ch { color:#509E4F } /* escaped character */
table.coderay .cl { color:#FFF } /* class */
table.coderay .co { color:#FFF } /* constant */
table.coderay .fl { color:#A4C260 } /* float */
table.coderay .fu { color:#FFC56D } /* function */
table.coderay .gv { color:#D0CFFE } /* global variable */
table.coderay .i { color:#A4C260 } /* integer */
table.coderay .il { background:#151515 } /* inline code */
table.coderay .iv { color:#D0CFFE } /* instance variable */
table.coderay .pp { color:#E7BE69 } /* doctype */
table.coderay .r { color:#CB7832 } /* keyword */
table.coderay .rx { color:#A4C260 } /* regex */
table.coderay .s { color:#A4C260 } /* string */
table.coderay .sy { color:#6C9CBD } /* symbol */
table.coderay .ta { color:#E7BE69 } /* html tag */
table.coderay .pc { color:#6C9CBD } /* boolean */
</style>

Plus the help of the script ~/bin/code2html.rb:
1
2
3
4
5
6
7
8
9
10
11
12
#!/usr/bin/env ruby

require 'rubygems'
require 'coderay'

puts %|#{coderay.scan_file(ARGV[0]).html(:line_numbers => :table)}|.
gsub('coderay','coderay').split('<pre').map{|s|
!s.include?('</pre>') ? s.gsub("\n",'').squeeze(' ') : (
parts = s.split('</pre>')
[parts[0], parts[1].gsub("\n",'').squeeze(' ')].join('</pre>')
)
}.join('<pre')

As ~/bin is already in my $PATH, all i need to do to convert any code to the nice code blocks u see here is to run:

code2html.rb <PATH_TO_ANY_FILE>

Hmmmm .. not too bad rite ? Now, what is left is to set aside some time to do some cleaning up for the rest of this blog (sweat).

Labels