Thursday, December 24, 2009

Scanning for badblocks in a a harddisk

Just bought a new harddisk, did scanning of badblocks with:

sudo badblocks -svwf /dev/sdc1

Amazingly, for 320GB, it takes 30:33:41.35 hrs to complete.

Thursday, December 10, 2009

Adding Webrat Matchers to Culerity

If u are using culerity, and somehow u missed the webrat matchers, eg. has_xpath(), here's what u can do:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
require 'webrat/core/xml'
require 'webrat/core/matchers'

module WebratLike

include Webrat::Matchers

def response
html = $browser.html
def html.body ; to_s ; end
html
end

end

World(WebratLike)
end
end

Enjoys !!

Wednesday, December 9, 2009

Testing of Clicking of Checkbox

We have checkboxes registered for onchange event handler. In testing using blueridge, to simulate checking of a checkbox, the following more ideal approaches, sadly, don't work:
1
2
$("input:checkbox:first").change(); #1
$("input:checkbox:first").click().change(); #2

But the following works:
1
$("input:checkbox:first").attr('checked', true).change();

Bitten once.

Sunday, November 29, 2009

Fetching plain ruby code on the fly

Last weekend, zan showed me howto use parsetree & ruby2ruby to dynamically extract a method definition in plain ruby code:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
%w{rubygems ruby2ruby parse_tree}.each {|lib| require lib }

class Hello

def self.hello
puts "class says hello"
end

def hello
puts "instance says hello"
end

end

extract_code = lambda do |klass, method|
sexp = ParseTree.translate(klass, method)
Ruby2Ruby.new.process(Unifier.new.process(sexp))
end

instance_method_code = extract_code[Hello, :hello]
puts instance_method_code
# >> def hello ; puts("instance says hello") ; end

To get the class method:
1
2
3
4
metaclass = (class << Hello ; self ; end)
class_method_code = extract_code[metaclass, :hello]
puts class_method_code
# >> def hello ; puts("class says hello") ; end

It is even possible to extract the entire class definitions:
1
2
3
4
5
puts extract_code[World, nil]
# >> class World < Object
# >> def hello ; puts("instance says hello") ; end
# >> def self.hello ; puts("class says hello") ; end
# >> end

There are probably tonnes of code stuff you can do with the above capability. One immediate use case i can think of is appending new instance/class methods to another class:
1
2
3
4
5
6
class World ; end
World.class_eval instance_method_code
World.instance_eval class_method_code

World.hello # yields: class says hello
World.new.hello # yields: instance says hello

Another is that we can store the method definition somewhere (db, file, ...), redefine, distort, assault, murder, arson the existing class, and later just rollback the damages:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
cache = {'Hello.hello' => extract_code[Hello, :hello]}
File.open('/tmp/original_methods', 'w') {|f| Marshal.dump(cache, f) }

class Hello
def hello ; puts "instance is murdered" ; end
end

puts Hello.new.hello
# >> instance is murdered

# Do lots of other bad stuff, and to undo the damages:

cache = File.open('/tmp/original_methods', 'r') {|f| Marshal.load(f) }
Hello.class_eval = cache['Hello.hello']

puts Hello.new.hello
# >> instance says hello

Thursday, November 26, 2009

Ways to create symbol on the fly

To convet a string to a symbol on the fly:

# Method 1:
1
2
3
type = "elective"
course = "#{type}_course".to_sym
# >> :elective_course

# Method 2:
1
2
3
type = "core"
course = :"#{type}_course"
# >> :core_course

Wednesday, November 25, 2009

Customizing ur STI column name

To me, at least, :type is a very generic & commonly in use attribute name when doing modelling, and i don't see a good reason for activerecord to use it for STI (single table inheritance) support. To use my preferred naming strategy, i did the following inside RAILS_ROOT/config/initializers/active_record.rb
1
ActiveRecord::Base.set_inheritance_column :sti_type

Dynamically defining class method

There is this concept of metaclass in ruby. If we wanna dynamically define a class method, we need to play with metaclass:
1
2
3
4
5
6
7
8
9
10
11
12
class Human
def self.say_hello
puts %\class says 'hello'\
end
end

message = 'hello world'
meta_klass = (class << Human ; self ; end)
meta_klass.send(:define_method, :say_hello) { puts %\class says '#{message}'\ }

Human.say_hello
# >> class says 'hello world'

Dynamically defining instance method

To dynamically define an instance method in ruby:
1
2
3
4
5
6
7
8
9
10
11
class Human
def say_hello
puts %\instance says 'hello'\
end
end

message = 'hello world'
Human.send(:define_method, :say_hello) { puts %\instance says '#{message}'\ }

Human.new.say_hello
# >> instance says 'hello world'

ActiveRecord: Bitten by :something & :something_id

I must have came across this previously, but i've forgotten all abt it, and today, i got bitten hard as a punishment for being forgetful. Let's same i have the following models:
1
2
3
4
5
class Father < ActiveRecord::Base ; end

class Son < ActiveRecord::Base
belongs_to :father # and yup, we have a :father_id in sons table
end

During creating of sons, both the following strategies work:
1
2
3
father1 = Father.create(:name => 'Papa Jones')
son1 = Son.create(:father => father1) # strategy 1
son2 = Son.create(:father_id => father1.id) # strategy 2

But during update, only strategy 1 works:
1
2
3
father2 = Father.create(:name => 'Papa Tommy')
son1.update_attributes(:father => father2) # strategy 1
son2.update_attributes(:father_id => father2.id) # strategy 2, this DOESN'T work !!

DON'T FORGET !!!

Tuesday, November 3, 2009

Nested Step Definitions: Passing Table as Arg

From within a step definition, it is possible to pass a table to another step using the following technique:
1
2
3
4
5
6
7
8
Given /^I have just entered the results for "([^\"]*)"$/ do |identifier|
Given %\I follow "Enter Results" for "#{identifier}"\
And %\I enter the following class test results:\, table(%\
| # | Name | Score|
| 1 | John Tan | 99.0 |
| 2 | John Hoo | 80.0 |
\
)
end

Here's the step definition that does processing of the table (nothing unusual actually):
1
2
3
4
5
Given /^I enter the following class test results:$/ do |table|
table.hashes.each do |hash|
# blah blah
end
end

Sweet :]

Thursday, October 29, 2009

Finding the position of an element

To find the position of element <b>col_d</b> in the following xml:
1
2
3
4
5
6
7
<a>
<b>col_a</b>
<b>col_b</b>
<b>col_c</b>
<b>col_d</b>
<b>col_e</b>
</a>

U can probably use the following xpath:

count(//b[normalize-space(text())="col_d"]/preceding-sibling::b)+1

But it doesn't work for me in nokogiri, so what i did was:
1
2
doc = Nokogiri::XML(above_xml_string)
doc.xpath('//b[normalize-space(text())="col_d"]/preceding-sibling::b').count + 1

That's all !!

Wednesday, October 28, 2009

Finding Common Elements in Ruby Arrays

To find common elements in ruby arrays, use '|'. Eg.

%w{a b c d} | %w{c d e f}

# yields:

['c', 'd']


To find common elements in 2 dimensional array:

a1, a2, a3 = %w{a b c d}, %w{c d e f}, %w{d e f}
a = [a1, a2, a3]

a[1..-1].inject(a[0]) do |x, y|
x | y
end

# yields:

['d']


That's all !!

Getting the nearest xpath ancestor

Given the following xml fragment:
1
2
3
4
5
<a>
<a>
<b/>
</a>
<a>

To find the nearest ancestor <a/> w.r.t <b/>, i use:

//b/ancestor::a[1]

That's all !!

Tuesday, October 27, 2009

Renaming a screen window

To rename a screen window, just do:

'Ctrl+a' & 'Shift-a'.

Smart click_button

In previous post, i've mentioned abt webrat's smart click_link(), and do u know that click_button() is also quite smart, meaning:
1
<input type="image" alt="Update" />

Works as well if we do:
1
click_button("Update")

Nice ?!

Monday, October 26, 2009

Smart click_link()

WOW, just found out image within <a/> tag (see below):
1
2
3
<a class="image" href="...">
<img src="..." alt="Back"/>
</a>

Actually work for the following pair of:
1
2
# Step
Given I follow "Back"

&:
1
2
3
4
# Step definition
Given /^I follow "([^\"]+)"$/ do |link|
click_link(link) # plain vanilla webrat
end

Cool !!

Sunday, October 25, 2009

Workaround for Webrat's have_xpath()

I have the following xpath:

//td[normalize-space(text())='Peter']/parent::tr//label[normalize-space(text())="Present"]/@for

It is valid, yet webrat's have_xpath() kept complaining that it cannot find it. As a workaround, i did something like this in my cucumber:
1
2
hdoc = Nokogiri::HTML(response.body)
(field_id = hdoc.xpath(the_above_rejected_xpath)).first.should_not be_nil

That's all.

Webrat's have_xpath() in diff modes

have_xpath() behaves slightly differently in :selenium & :webrat mode.

From webrat's doc, we have:

Webrat::Matchers#have_xpath(expected, options = {}, &block)

And

Webrat::Selenium::Matchers::have_xpath(xpath)

If u are a xpath fan like me, there is no way u can conveniently switch between the 2 modes without getting bitten.

2 Way to Fetch a Node's Attribute Value

There are at least 2 ways to fetch a node's attribute value using xpath:

# Method 1

//a/b/@c

# Method 2

//a/b/attribute::c

Saturday, October 24, 2009

Fixing Gnome Tooltip

I've accidentally screwed up my gnome's config, as a result, all tooltips in my gnome desktop appear as meaningless black blocks. After some playing round & trial & error, i fixed the problem by replacing the following lines in ~/.gconf/desktop/gnome/interface/%gconf.xml:
1
2
tooltip_fg_color:#000000000000
tooltip_bg_color:#000000000000

With the more meaningful:
1
2
tooltip_fg_color:#000000000000
tooltip_bg_color:#ffffffffffff

That's all !!

Wednesday, September 16, 2009

m1's 3g mobile broadband on ubuntu jaunty

It turns out that getting M1's 3G mobile broadband (with Huawei's E1550) to run on ubuntu jaunty seems easier than expected, here's what u can do to get it running:

1. Since usb-modeswitch is not yet available from the ubuntu repositories, download *.deb from http://www.debian.org/distrib/packages (the 'testing' distro is good enough)

2. Download the latest usb_modeswitch.conf from http://www.draisberghof.de/usb_modeswitch/ and replace the /etc/usb_modeswitch.conf generated by the above *.deb

3. Update /etc/usb_modeswitch.conf to uncomment the section section corresponding to the brand & model for ur usb stick (for my case, it is Huawei E1550)

4. Run "sudo usb_modeswitch", and waited for a few seconds

5. Right click on the desktop's NetworkManager to select "Edit Connections"

6. Select "Mobile Broadband" tab to add a new M1 connection (the rest is pretty intuitive)

And that's all :]

Labels