Wednesday, September 30, 2009

Using %\\ for strings instead of "" or ''


string = %\This 'string' is so "boomz"!\

Clicking on links in Webrat using XPath

If for some reason you wanna use XPath instead of CSS Selector to click on a link

# Cucumber step
And I follow "Edit" for "John Woo"

# Using Css Selector
within(%\...\) do
click_link(link)
end

# Using XPath
response.should have_xpath(%\//td[normalize-space(text())="#{name}"]/parent::tr//a[normalize-space(text())="#{link}"]/@id\) do |link_id|
click_link(link_id)
end

Monday, September 28, 2009

Problem with nested attributes for has one relation in form view

Scenario:

# app/models/teacher.rb
has_one :profile
accepts_nested_attributes_for :profile

# app/controllers/teachers_controller.rb
def new
@teacher = Teacher.new
@teacher.profile = Profile.new
end

If the following view give you error.

# app/views/teachers/_form.html.erb
<% form.fields_for :profile do |profile_form| %>
...
<% end %>

# Error in console
You have a nil object when you didn't expect it!
You might have expected an instance of ActiveRecord::Base.
The error occurred while evaluating nil.new_record? (ActionView::TemplateError)
On line #1 of app/views/teachers/_form.erb

1: <% form.fields_for :profile do |profile_form| %>

Then it means you don't have any fields for parent object

<%= form.text_field :login %>
<% form.fields_for :profile do |profile_form| %>
...
<% end %>

Sunday, September 27, 2009

Best built in Vim color theme for Rails


# Seems like Evening's the best
colorscheme Evening

Run windows maximized by default in Ubuntu

# Install maximus window manager which
# - runs windows as maximized
# - hides windows titlebar
sudo apt-get install maximus

# Toggle maximized (metacity)
ALT + F10

Saturday, September 26, 2009

Make Gnome Panel autohide 100%

Setting my netbook's top and bottom Gnome panel to autohide still leaves some pixels visible.

# Hide top panel completely
gconftool-2 --set --type integer /apps/panel/toplevels/top_panel_screen0/auto_hide_size 0

# Hide bottom panel completely
gconftool-2 --set --type integer /apps/panel/toplevels/bottom_panel_screen0/auto_hide_size 0

# Access configurations through GUI
ALT-F2 > "gconf-editor" > apps > panel > toplevels > top_panel_screen0 > auto_hide_size > 0

ref:
http://ubuntu-tutorials.com/2009/09/21/completely-hide-gnome-panel/

Friday, September 25, 2009

Rip video or audio from Youtube video


# Install youtube-dl to download video into flv file
sudo apt-get install youtube-dl
youtube-dl http://

# Install ffmpeg to do the conversions
sudo apt-get install ffmpeg

# Convert to mp3 audio
sudo apt-get install libavcodec-unstripped-52
ffmpeg -i input.flv -ac 2 -ab 128000 -ar 44100 output.mp3

# Convert to mpeg video
ffmpeg -i input.flv output.mpg

refs:
http://pblog.ebaker.me.uk/2009/01/rip-youtube-videos-on-ubuntu.html
https://lists.ubuntu.com/archives/universe-bugs/2009-January/041895.html

Using Irssi

Strangely I couldn't find a simple "howto" article on using Irssi except for this

http://carina.org.uk/screenirssi.shtml

# Connect to irc server
/connect irc.freenode.net

# Joining a channel
/join #linuxnus

# Parting a channel
/part

# Change nick
/nick

# Highlight keywords
/hilight

# Set away message
/away

# Cancel away status
/away

# Send private message
/msg

# Open up private chatroom
/query

# Closing windows
/wc

# Disconnect from server
/disconnect

# Exit irssi
/exit

% and # in Vim

# '%' represents current filename in buffer
# Eg. insert current file contents in Vim
:!!cat %

# '#' represents previous filename in buffer
# Eg. git commit current and previous file
:! git commit -m "Message for commit" % #

Thursday, September 24, 2009

Select last tab in Firefox

# Goto last tab
ALT + 9

# Goto first tab
ALT + 1

# Alternative longer method of going to last tab
ALT + 1, CTRL + PageDown

Insert shell output into Vim


# Insert date
!!date

# Insert directory listing
!!ls -l

How to use Git tags


# Lightweight tagging
git tag stable-1 1b2e1d63ff

# Annotated tagging
git tag stable-1 1b2e1d63ff -a -m "This is a explanation of this tag."

# Signed tags
git tag -s -m "Tagging release 2.0" v2.0

# List tags
git tag -l

# Pushing tags to repository
git push origin --tags

refs:
http://ariejan.net/2009/09/05/git-tag-mini-cheat-sheet-regit tag -l -n1visited/
http://book.git-scm.com/3_git_tag.html

Wednesday, September 23, 2009

Record & playback Screen session

It works like this:

script -t 2> demo.timing -a demo.session
Script started, file is demo.session

exit
Script done, file is demo.session

And later you replay your session like this:

scriptreplay demo.timing demo.session

Ref: http://www.linuxinsight.com/replaying-terminal-sessions-with-scriptreplay.html

Git fetch remote branches


# Fetch histories of all remote branches
git fetch remote

# Fetch histories of only remote master branch
git fetch remote master

# Rebase with remote branch
git rebase remote/branch

Aborting a Git rebase


# If for some reason your git rebase is failing, git rebase abort to the rescue!
git rebase --abort

Tuesday, September 22, 2009

Monday, September 21, 2009

Intel Core 2 Duo vs AMD Turion X2 Ultra

It seems Core 2 Duo outperforms in terms of speed, heat dissipation and battery life.

ref: http://www.ehow.com/about_5394981_core-duo-vs-turion.html

Sunday, September 20, 2009

Use rtcwake to "wake up" from sleep mode at a given time

Note that if you try this whilst in X, your laptop/pc will resume with X garbled. Therefore go into another Ubuntu session and execute the commands.

# Login to another session
CTRL + ALT + F1

# Put laptop to sleep and automatically resume after 10 seconds
sudo rtcwake -m mem -u -v -s 10

# After resume from sleep go back to original xsession
CTRL + ALT + F7

View difference between Ubuntu date and Bios clock


# Display date by Ubuntu
date

# Display date from Bios
sudo hwclock

Using Rsync to synchronize folders between machines


# The below will sync my Music folder on both my laptop and desktop
rsync --verbose --progress --stats --compress --rsh=/usr/bin/ssh \
--recursive --times --perms --links --delete \
--exclude "*bak" --exclude "*~" \
../Music/* jasonong-desktop:~/Music/


Ref: http://everythinglinux.org/rsync/

Installing PADevchooser gui for pulseaudio


sudo apt-get install paman paprefs pavucontrol pavumeter

Finding CPU info in terminal


cat /proc/cpuinfo

Friday, September 18, 2009

Find files & directories in terminal


# Simple method to find files recursively from path with which matches expression
find ./ -name "*.rb"

# find directories recursively which matches expression (directory type)
find ./ -name 'specs*' -type d

List of bash shortcuts

Taken from the following article

http://www.skorks.com/2009/09/bash-shortcuts-for-maximum-productivity/

* Ctrl + a – go to the start of the command line
* Ctrl + e – go to the end of the command line
* Ctrl + k – delete from cursor to the end of the command line
* Ctrl + u – delete from cursor to the start of the command line
* Ctrl + w – delete from cursor to start of word (i.e. delete backwards one word)
* Ctrl + y – paste word or text that was cut using one of the deletion shortcuts (such as the one above) after the cursor
* Ctrl + xx – move between start of command line and current cursor position (and back again)
* Alt + b – move backward one word (or go to start of word the cursor is currently on)
* Alt + f – move forward one word (or go to end of word the cursor is currently on)
* Alt + d – delete to end of word starting at cursor (whole word if cursor is at the beginning of word)
* Alt + c – capitalize to end of word starting at cursor (whole word if cursor is at the beginning of word)
* Alt + u – make uppercase from cursor to end of word
* Alt + l – make lowercase from cursor to end of word
* Alt + t – swap current word with previous
* Ctrl + f – move forward one character
* Ctrl + b – move backward one character
* Ctrl + d – delete character under the cursor
* Ctrl + h – delete character before the cursor
* Ctrl + t – swap character under cursor with the previous one
* Ctrl + ] - search forward for character
* Ctrl + Alt + ] - search backwards for character

Command Recall Shortcuts

* Ctrl + r – search the history backwards
* Ctrl + g – escape from history searching mode
* Ctrl + p – previous command in history (i.e. walk back through the command history)
* Ctrl + n – next command in history (i.e. walk forward through the command history)
* Alt + . – use the last word of the previous command

Command Control Shortcuts

* Ctrl + l – clear the screen
* Ctrl + s – stops the output to the screen (for long running verbose command)
* Ctrl + q – allow output to the screen (if previously stopped using command above)
* Ctrl + c – terminate the command
* Ctrl + z – suspend/stop the command

Bash Bang (!) Commands

Bash also has some handy features that use the ! (bang) to allow you to do some funky stuff with bash commands.

* !! - run last command
* !blah – run the most recent command that starts with ‘blah’ (e.g. !ls)
* !blah:p – print out the command that !blah would run (also adds it as the latest command in the command history)
* !$ – the last word of the previous command (same as Alt + .)
* !$:p – print out the word that !$ would substitute
* !* – the previous command except for the last word (e.g. if you type ‘find some_file.txt /‘, then !* would give you ‘find some_file.txt‘)
* !*:p – print out what !* would substitute

Make long multiple system commands in ruby more readable

# Instead of this long line of system command
system "pkill firefox & echo 'To Reboot: #{Time.now}' >> #{log_file} & echo #{PASSWORD} | sudo shutdown -r now"

# Have a readable array of the commands and join them into a string
system [
"pkill firefox",
"echo 'To Reboot: #{Time.now}' >> #{log_file}",
"echo #{PASSWORD} | sudo shutdown -r now"
].join(" & ")

Thursday, September 17, 2009

Adding digital signature to a Office document

Steps

- Take a picture of signature on a piece of paper
- Download into laptop
- Use Gimp to edit the image
- Make the signature black & white with "Destaturate" > "By Luminosity"
- Make improve contrast between signature & background by going into "Brightness & Contrast" & adjusting the brightness & contrast to a suitable level
- Then make the signature bolder & more obvious by going into "Brightness & Contrast" > "Edit these settings as levels" & adjusting to desired effect

Best way to edit pdf files in Linux

First convert pdf to a text file

sudo apt-get install poppler-utils
pdftotext file.pdf

The above will create a file.txt which you can then use OpenOffice to edit to your hearts content and save it back into a pdf file.

UPDATE

I've found another way to edit pdf file.

- Use gimp
- Split & merge using pdftk **

**
Can use gs command tool too
gs -q -sPAPERSIZE=letter -dNOPAUSE -dBATCH -sDEVICE=pdfwrite -sOutputFile=out.pdf in1.pdf in2.pdf in3.pdf ...

Annotate over PDF files using flpsed in Linux

Description

flpsed is a WYSIWYG PostScript annotator. You can't remove or modify existing elements of a document. But flpsed lets you add arbitrary text lines to existing PostScript documents (PostScript is a registered trademark of Adobe Systems Incorporated).

sudo apt-get install flpsed

Disadvantages

- Only text annotation
- Cannot add image files. --> digital signatures

Copy into global clipboard in Vim


# Yanking in Vim will only copy into Vim buffer
y

# Get into command history mode and copy into clipboard instead
q:
"+yy

Tuesday, September 15, 2009

An example .screenrc file


screen -t "bzr"
stuff "bzr diff | colordiff"
screen -t "misc"
screen -t "devsvr"
stuff "cd ~/google_appengine^M"
stuff "./dev_appserver.py -p 8084 ~/shared/appengine/conquer-on-contact/root/"
screen -t "update"
stuff "cd ~/google_appengine^M"
stuff "./appcfg.py update ~/shared/appengine/conquer-on-contact/root/"

#change the hardstatus settings to give an window list at the bottom of the
#screen, with the time and date and with the current window highlighted
hardstatus alwayslastline
hardstatus string '%{= kG}[ %{G}%H %{g}][%= %{= kw}%?%-Lw%?%{r}(%{W}%n*%f%t%?(%u)%?%{r})%{w}%?%+Lw%?%?%= %{g}][%{B} %d/%m %{W}%c %{g}]'
vbell on
defscrollback 1024
startup_message off
autodetach on
defutf8 on

Searching in Less


# Opening manuals in terminal will usually be piped with less

man git

# Search forward in less. n --> forward, N --> backwards
/keyword

# Search backward in less,
?keyword

# View help for less
SHIFT + h

Screen profile in Ubuntu


When you start Screen for the first time, you'll be presented with the Screen profile helper. Choosing a profile other than "plain" will give you an awesome bottom toolbar which you can toggle nice notifications.

If for some reason, you've chosen "plain" and want to change screen profile, enter the following in terminal

select-screen-profile -s ubuntu-black

Monday, September 14, 2009

Using single Screen session with multiple windows

You can do Vim "buffer-like" windows on a Screen session.

Create new window: CTRL + a, c
List windows: CTRL + a, "
Prompt to open window n: CTRL + a, '
Window info: CTRL + a, i
Create new window with "title": screen -t "title"
Kill window: CTRL + a, k
Kill all windows: CTRL + a, \
Set current window title: CTRL + a, A

Open window n: CTRL + a, n
Open next window: CTRL + a, CTRL + n OR CTRL + a, Spacebar
Open previous window: CTRL + a, CTRL + a OR CTRL + a, Backspace

Go into copy mode: CTRL + a, [
Select mode: CTRL + a, spacebar
Move: h, j, k, l, w, e, b
Copy: Enter
Paste: CTRL + a, ]

Page up: CTRL + a, [, PageUp
Page down: CTRL + a, [, PageDown

Detach session: CTRL + a, :detach OR CTRL + a, d

Execute shell commands in Vim

# :! to execute shell commands directly in Vim
:! git status

# % specifies current file
:! git commit -m "Added changes" %

Scrolling in Screen session

# To enable scrolling in Screen session you have to get into 'Copy mode'
CTRL + a + [
or
CTRL + a + ESC

# To scroll, use VIM methods

Left, down, up, right --> h, j, k, l,
Page up, page down --> Ctrl + f, Ctrl + b

Sunday, September 13, 2009

Status flags in Mutt

Taken from the online Mutt manual

http://www.mutt.org/doc/manual/manual-2.html#ss2.3

Status Flags

In addition to who sent the message and the subject, a short summary of the disposition of each message is printed beside the message number. Zero or more of the following ``flags'' may appear, which mean:

D

message is deleted (is marked for deletion)

d

message have attachments marked for deletion

K

contains a PGP public key

N

message is new

O

message is old

P

message is PGP encrypted

r

message has been replied to

S

message is PGP signed, and the signature is succesfully verified

s

message is PGP signed

!

message is flagged

*

message is tagged

Some of the status flags can be turned on or off using

  • set-flag (default: w)
  • clear-flag (default: W)

Furthermore, the following flags reflect who the message is addressed to. They can be customized with the $to_chars variable.

+       message is to you and you only
T message is to you, but also to or cc'ed to others
C message is cc'ed to you
F message is from you
L message is sent to a subscribed mailing list

List files with human readable filesize

# Keep forgetting this one
ls --help
...
-h, --human-readable with -l, print sizes in human readable format
(e.g., 1K 234M 2G)
...

# List files with human readable filesize
ls -lh

Pipe less with colors


# Normal pipe will not output ANSI colors
ruby twitpow.rb history | less

# There is an entry in "less --help" that says
-r -R .... --raw-control-chars --RAW-CONTROL-CHARS
Output "raw" control characters.

# Pipe less with ANSI colors!
ruby twitpow.rb history | less -r

Share screen session on iPhone

There's a screen package in Cydia. That means I can set up screen session on the iPhone terminal!

To set up screen session sharing follow my previous post.

http://objectliteral.blogspot.com/2009/09/share-terminal-session-to-remote-user.html

Possible applications:
- Remote paired programming where one will code on normal laptop while the other observes on the iPhone

Things to note:
- Must run screen session as root user on iPhone
- Might be better to ssh into iPhone from laptop to set up the session rather than setting it up straight from iPhone Terminal as the latter's much harder to type

Saturday, September 12, 2009

Share terminal session to remote user using screen

Taken from the following article.

http://ubuntuforums.org/showthread.php?t=299286

Case Scenario:

Assume user jsmith wants to share his terminal session with remote user bjones for training or troubleshooting purposes, but does not want to use VNC or other full-blown GUI remote control access.

Requirements:
- GNU Screen
- Local account on host computer for remote user (i.e. bjones requires local account)

1. Install screen
Code:
sudo apt-get install screen
2. Set the screen binary (/usr/bin/screen) setuid root. By default, screen is installed with the setuid bit turned off, as this is a potential security hole.
Code:
sudo chmod +s /usr/bin/screen
Code:
sudo chmod 755 /var/run/screen
3. The host starts screen in a local xterm, using the command screen -S SessionName. The -S switch gives the session a name, which makes multiple screen sessions easier to manage.
Code:
screen -S screen-test
4. The remote user (bjones) uses SSH to connect to the host computer (jsmith).
Code:
ssh bjones@jsmith.computer.ip.address
5. The host (jsmith) then has to allow multiuser access in the screen session via the command CTRL-A :multiuser on (all 'screen' commands start with the screen escape sequence, CTRL-A).
Code:
CTRL-A
:multiuser on
6. Next, the host (jsmith) must grant permission to the remote user (bjones) to access the screen session using the commadn CTRL-A :acladd user_name where user_name is the remote user's login ID.
Code:
CTRL-A
:acladd bjones
7. The remote user can now connect to the hosts 'screen' session. The syntax to connect to another user's screen session is screen -x host_username/sessionname.
Code:
screen -x jsmith/screen-test

Ruby Case statements

Some Ruby Case statement tips taken from the following article.

http://www.skorks.com/2009/08/how-a-ruby-case-statement-works-and-what-you-can-do-with-it/


Normal:
print "Enter your grade: "
grade = gets.chomp
case grade
when "A"
puts 'Well done!'
when "B"
puts 'Try harder!'
when "C"
puts 'You need help!!!'
else
puts "You just making it up!"
end

Multi-value:
print "Enter your grade: "
grade = gets.chomp
case grade
when "A", "B"
puts 'You pretty smart!'
when "C", "D"
puts 'You pretty dumb!!'
else
puts "You can't even use a computer!"
end

Regex:
print "Enter a string: "
some_string = gets.chomp
case
when some_string.match(/\d/)
puts 'String has numbers'
when some_string.match(/[a-zA-Z]/)
puts 'String has letters'
else
puts 'String has no numbers or letters'
end


Ruby metaprogramming toolbox

An article that lists and explains all the ruby metaprogramming techniniques.

http://weare.buildingsky.net/2009/08/25/rubys-metaprogramming-toolbox

What is Metaprogramming?

Metaprogramming is the writing of computer programs that write or manipulate other programs (or themselves) as their data, or that do part of the work at compile time that would otherwise be done at runtime. In many cases, this allows programmers to get more done in the same amount of time as they would take to write all the code manually, or it gives programs greater flexibility to efficiently handle new situations without recompilation. (via Wikipedia)

The following tutorial lists all the methods from the Ruby core that are useful for metaprogramming as well as demonstrates common usage scenarios you will find helpful to get started. In conclution, an example is presented showing how to develop a dynamic database class like ActiveRecord which automatically generates classes for database tables and populates each model class with getters and setters for its fields.

The Metaprogramming Tool Box

Ruby gives us many methods that help us generate code dynamically. Its important to familiarize yourself with them.

Getting, setting, and destroying variables

Getting, setting, and destroying constants (like classes)

Adding and removing methods

Running dynamic code

Reflection methods

Reflection is an important part of metaprogramming as it allows us to look at objects and peer at their contents and structure.

Evaluating strings and blocks

You may be familiar with the eval method which allows you to evaluate a string or block as ruby code. When you need to eval within the scope of a particular object you can use the instance_eval and module_eval (synonymous for class_eval) methods.

The instance_eval method works on the scope of an instantiated object.

[1,2,3,4].instance_eval('size') # returns 4

In the above example we passed instance_eval the string ‘size’ which is interpreted against the receiving object. It is equivalent to writing:

[1,2,3,4].size

You can also pass instance_eval a block.

# Get the average of an array of integers
[1,2,3,4].instance_eval { inject(:+) / size.to_f } # returns 2.5

Notice how the inject(:+) and size.to_f methods just float in the air with no receiving objects? Well because they are executed within the instance context they are evaluated as self.inject(:+) / self.size.to_f where self is the receiving object array.

Whereas instance_eval evaluates code against an instantiated object module_eval evals code against a Module or Class.

Fixnum.module_eval do
def to_word
if (0..3).include? self
['none', 'one', 'a couple', 'a few'][self]
elsif self > 3
'many'
elsif self < 0
'negative'
end
end
end
1.to_word # returns 'one'
2.to_word # returns 'a couple'

We can see how module_eval re-opened the existing class Fixnum and appended a new method. Now this in itself is nothing special as there are other ways to do this for instance:

class Fixnum
def to_word
..
end
end

The real advantage is to evaluate strings that generate dynamic code. Here we are using a class method create_multiplier to dynamically generate a method with a name of your choosing.

class Fixnum
def self.create_multiplier(name, num)
module_eval "def #{name}; self * #{num}; end"
end
end

Fixnum.create_multiplier('multiply_by_pi', Math::PI)
4.multiply_by_pi # returns 12.5663706143592

The above example creates a class method (or ‘singleton method’) which when called, generates instance methods which any Fixnum object can use.

Using send

Using send works much like instance_eval in that it sends a method name to a receiving object. It is useful when you are dynamically getting a method name to call from a string or symbol.

method_name = 'size'
[1,2,3,4].send(method_name) # returns 4

You can specify the method name as a string or a symbol ‘size’ or :size

One potential benefit of send is that it bypasses method access control and can be used to run private methods like Module#define_method.

Array.define_method(:ducky) { puts 'ducky' } 
# NoMethodError: private method `define_method' called for Array:Class

Using the send hack:

Array.send(:define_method, :ducky) { puts 'ducky' }

Defining Methods

As we just saw in the example above we can use define_method to add methods to classes.

class Array
define_method(:multiply) do |arg|
collect{|i| i * arg}
end
end

[1,2,3,4].multiply(16) # returns [16, 32, 48, 64]

method_missing

When included in a class, method_missing is invoked when the class instance receives a method that does not exist. It can be used to catch these missing methods instead of raising a NoMethodError.

class Fixnum
def method_missing(meth)
method_name = meth.id2name
if method_name =~ /^multiply_by_(\d+)$/
self * $1.to_i
else
raise NoMethodError, "undefined method `#{method_name}' for #{self}:#{self.class}"
end
end
end

16.multiply_by_64 # returns 1024
16.multiply_by_x # NoMethodError

How does attr_accessor work?

Most of us use attr_accessor in our classes, but not everyone understands what it does behind the scenes. attr_accessor dynamically generates a getter and a setter for an instance variable. Lets take a closer look.

class Person
attr_accessor :first_name
end

john = Person.new
john.first_name = 'John'

john.instance_variables
# returns ["@first_name"]

john.methods.grep /first_name/
# returns ["first_name", "first_name="]

We can see that attr_accessor actually created an instance variable @first_name as well as two instance methods, a getter and a setter, first_name and first_name=

Implementation

All classes inherit class methods from Module so we will put the mock methods here.

class Module
# First using define_method
def attr1(symbol)
instance_var = ('@' + symbol.to_s)
define_method(symbol) { instance_variable_get(instance_var) }
define_method(symbol.to_s + "=") { |val| instance_variable_set(instance_var, val) }
end

# Second using module_eval
def attr2(symbol)
module_eval "def #{symbol}; @#{symbol}; end"
module_eval "def #{symbol}=(val); @#{symbol} = val; end"
end
end

class Person
attr1 :name
attr2 :phone
end

person = Person.new
person.name = 'John Smith'
person.phone = '555-2344'
person # returns

Both define_method and module_eval produced the same result.

Example Usage: Poor Man’s Active Record

For those familiar with RubyonRails it is easy to see how one might go about implementing an ActiveRecord class which would look up field names in a database and add getters and setters to a class.

We could take it one step further and have the Model classes generated dynamically as well.

In this example we are going to generate a poor man’s ActiveRecord. The class will connect to the MySQL database, generate a dynamic class for every table it finds, and populate the classes with getters and setters the table fields they contain.

require 'rubygems'
require 'mysql'

class PoorMan
# store list of generated classes in a class instance variable
class << self; attr_reader :generated_classes; end
@generated_classes = []

def initialize(attributes = nil)
if attributes
attributes.each_pair do |key, value|
instance_variable_set('@'+key, value)
end
end
end

def self.connect(host, user, password, database)
@@db = Mysql.new(host, user, password, database)

# go through the list of database tables and create classes for them
@@db.list_tables.each do |table_name|
class_name = table_name.split('_').collect { |word| word.capitalize }.join

# create new class for table with Module#const_set
@generated_classes << klass =" Object.const_set(class_name, Class.new(PoorMan))

klass.module_eval do
@@fields = []
@@table_name = table_name
def fields; @@fields; end
end

# go through the list of table fields and create getters and setters for them
@@db.list_fields(table_name).fetch_fields.each do |field|
# add getters and setters
klass.send :attr_accessor, field.name

# add field name to list
klass.module_eval { @@fields << field.name }
end
end
end

# finds row by id
def self.find(id)
result = @@db.query("select * from #{@@table_name} where id = #{id} limit 1")
attributes = result.fetch_hash
new(attributes) if attributes
end

# finds all rows
def self.all
result = @@db.query("select * from #{@@table_name}")
found = []
while(attributes = result.fetch_hash) do
found << new(attributes)
end
found
end
end

# connect PoorMan to your database, it will do the rest of the work for you
PoorMan::connect('host', 'user', 'password', 'database')

# print a list generated classes
p PoorMan::generated_classes

# find user with id:1
user = Users.find(1)

# find all users
Users.all

Dir.glob to get filenames in directory


# Glob for filenames in path
Dir.glob('some/path/name')

# Use File.join for pathname which autocorrects for Windows
Dir.glob(File.join(File.dirname(__FILE__), 'some', 'path', 'name'))

Use File.join to state file pathname


# Straight naming of pathname for "file.rb"
require 'path/name/for/file'

# Using File.join. Advantage --> auto forward slash on windows
require File.join('path', 'name', 'for', file')

# Even better way which takes care of relative paths
require File.join(File.dirname(__FILE__), 'path', 'name', 'for', 'file')

Linux: './path/name/for/file'
Windows: '.\path\name\for\file'

# Full path instead of relative path
require File.expand_path(File.join(File.dirname(__FILE__), 'path', 'name', 'for', 'file'))

Linux: '/home/jasonong/path/name/for/file'
Windows: 'c:\users\jasonong\path\name\for\file'

Thursday, September 10, 2009

Highlight line in Vim

# Highlight line that cursor is on
SHIFT + v

# Highlight line and then tab it
SHIFT + v
>

Open shell in Vim

# Open shell inside vim to do shell operations
:shell

# Exit shell
exit

Use "p" instead of "puts Object.inspect"

@whatever = Whatever.blah

# Old way
puts @whatever.inspect

# Convenient way (achieve same thing)
p @whatever

# Can even print multiple
p @whatever, @another, @forever

Autocomplete in Vim

# Autocomplete string in buffer
CTRL + p

# Autocomplete line in buffer
CTRL + x + l

Tuesday, September 8, 2009

Better testing of form elements in Cucumber using form fieldsets


# Scenario:
# Sometimes too form elements --> messy!
# Also elements have same label names --> webrat won't know how to distinguish them
#
# Solution:
# Separate logical groupings of elements into fieldsets
# Cucumber test the fieldsets

# In feature file
When /../ do
Given I focus on XXX section
...
end

# In step definition file
Given /^I focus on "([^\"]*)" section do |section|
set_fielset_context(section)
end

Using a factory name that doesn't correspond to a model


# Model

class GradeScaleRange < ActiveRecord::Base
end

# Factory

# Normally case -> OK!
Factory.define :grade_scale_range do
end

# This will scream!
Factory.define :grade_scale_range_a do
end

# Correct it with class name
Factory.define :grade_scale_range_a, :class => 'grade_scale_range' do
end

# Although the below seems ok in documentation. It will spew "dup NilClass" error
Factory.define :grade_scale_range_a, :class => GradeScaleRange do
end

Use TightVNC viewer with Vino

Vinagre that comes with Ubuntu cannot be configured for compression, faster response etc. Need to use TightVNC viewer instead to connect to a vino desktop session

xtightvncviewer -depth 8 -compresslevel 9 -quality 0 -nocursorshape IP_ADDRESS:0

Monday, September 7, 2009

Batch remove/rename files in terminal


# Batch git remove files

for f in `ls *.feature`
do git rm ${f}
done

# Batch git rename files

for f in `ls *.feature`
do git mv ${f}
done

Installing Hamachi for remote desktop (VNC) over VPN

Install Hamachi on Ubuntu 9.04

1. To being we must turn on the ‘tun’ module to enable IP Tunneling support for the Linux kernel. Most do not have this setup by default.

$ sudo modprobe tun

2. Open the modules file and add ‘tun’ to the list

$ sudo vi /etc/modules

3. Your file should look similar to the example below.

# /etc/modules: kernel modules to load at boot time.
#
# This file contains the names of kernel modules that should be loaded
# at boot time, one per line. Lines beginning with "#" are ignored.

lp
rtc
tun

4. Save the file and exit out of vi, lets move on and verify that a tunneling node has been created. (*If you have compiled your own kernel you likely need to recompile it with IP Tunneling support if you receive an error with modprobe. This is not covered in this guide. And if you are unsure, you most likely did not compile yourself and you would definitely remember doing so.)

$ ls /dev/net/tun

5. You should recieve a response like the example below

/dev/net/tun

6. If you received something along the lines of “No Such File or Directory” you may need to manually create the node in step 6. If you received the same response as I did, jump to step 7.

$ sudo tuncfg

Jump back to Step 4 and you should now receive the correct response.
7. With our IP Tunnel node created, it is time to install Hamachi itself. First download the latest version. As of writing this guide, the latest version is 0.9.9.9-20

$ wget http://files.hamachi.cc/linux/hamachi-0.9.9.9-20-lnx.tar.gz

Expected output below

--2009-07-31 20:28:25-- http://files.hamachi.cc/linux/hamachi-0.9.9.9-20-lnx.tar.gz
Resolving files.hamachi.cc... 69.25.20.50
Connecting to files.hamachi.cc|69.25.20.50|:80... connected.
HTTP request sent, awaiting response... 200 OK
Length: 344866 (337K) [text/plain]
Saving to: `hamachi-0.9.9.9-20-lnx.tar.gz'

100%[====================================================================>] 344,866 448K/s in 0.8s

2009-07-31 20:28:26 (448 KB/s) - `hamachi-0.9.9.9-20-lnx.tar.gz' saved [344866/344866]

8. Extract our newly downloaded archive

$ tar zxvf hamachi-0.9.9.9-20-lnx.tar.gz

Expected output below

hamachi-0.9.9.9-20-lnx/
hamachi-0.9.9.9-20-lnx/Makefile
hamachi-0.9.9.9-20-lnx/LICENSE
hamachi-0.9.9.9-20-lnx/README
hamachi-0.9.9.9-20-lnx/LICENSE.tuncfg
hamachi-0.9.9.9-20-lnx/LICENSE.openssh
hamachi-0.9.9.9-20-lnx/LICENSE.openssl
hamachi-0.9.9.9-20-lnx/hamachi
hamachi-0.9.9.9-20-lnx/tuncfg/
hamachi-0.9.9.9-20-lnx/tuncfg/Makefile
hamachi-0.9.9.9-20-lnx/tuncfg/tuncfg.c
hamachi-0.9.9.9-20-lnx/tuncfg/tuncfg
hamachi-0.9.9.9-20-lnx/CHANGES

9. Navigate into the extracted directory

$ cd hamachi-0.9.9.9-20-lnx/

10. Start the installation

$ sudo make install

Expected output below

Copying hamachi into /usr/bin ..
Creating hamachi-init symlink ..
Compiling tuncfg ..
Copying tuncfg into /sbin ..

Hamachi is installed. See README for what to do next.

11. Run the tunnel

$ sudo tuncfg

12. This should complete the install, we will now configure the user permission in order for it to run correctly. Create a ‘hamachi’ user group

$ sudo groupadd hamachi

13. Add youself as a user to the ‘hamachi’ group. Be sure to replace your user name where appropriate.

$ sudo gpasswd -a YOURUSERNAME hamachi

14. Add the root user to the ‘hamachi’ group

$ sudo gpasswd -a root hamachi

15. Set the correct permissions for the tuncfg socket

$ sudo chmod 777 /var/run/tuncfg.sock

16. Change the ownership of the socket file

$ sudo chgrp hamachi /var/run/tuncfg.sock

17. That should do it for the permissions, Now onto setting Hamachi up & configuring it to start as a system service.

$ hamachi-init

Expected output

Initializing Hamachi configuration (/home/jasonong). Please wait ..

generating 2048-bit RSA keypair .. ok
making /home/jasonong directory .. ok
saving /home/jasonong/client.pub .. ok
saving /home/jasonong/client.pri .. ok
saving /home/jasonong/state .. ok

Authentication information has been created. Hamachi can now be started with
'hamachi start' command and then brought online with 'hamachi login'.

18. Start hamachi

$ hamachi start

Expected output

Starting Hamachi hamachi-lnx-0.9.9.9-20 .. ok

19. Set your computer’s nickname

$ hamachi set-nick "COMPUTERNICKNAME"

20. Login to the Hamachi network

$ hamachi login

21. To join an existing network (optional) “NETWORKNAME” and “PASSKEY” should be replaced with your network name and network password

$ hamachi join NETWORKNAME PASSKEY

22. To create a new network (optional) “NETWORKNAME” and “PASSKEY” should be replaced with your network name and network password

$ hamachi create NETWORKNAME PASSKEY

23. If you joined an existing network you must tell hamachi to then “go-online”. Be sure to replace NETWORKNAME with your relevant network name.

$ hamachi go-online NETWORKNAME

24. Check your hamachi status to verify everything is as it should be

$ hamachi

Expected outputhamachi -c /etc/hamachi start


Hamachi, a zero-config virtual private networking utility, ver 0.9.9.9-20

version : hamachi-lnx-0.9.9.9-20
pid : 5472
status : logged in
nickname : JasonOng

Known Issues

And that pretty much completes the install. Just some words of advice from some small issues that I’ve run into. I’ve found it best to create a network with a Windows computer. The windows client supports network messaging, where the OS X and Linux clients do not. This is important because if you later choose to move control to https://my.hamachi.cc , only the windows client will be able to receive the network message and reply to it. Allowing administrative controls to be transfered and managed from the website. OS X and Linux clients cannot do this at this point in time.

Install gHamachi GUI

First, visit the Hamachi forums and download the most recent version of the gHamachi frontend for either gtk 2.0 or gtk 1.2 (whichever you prefer).

gHamachi can be found here.

Second, simply unpack the gHamachi tarball, copy the binary to /usr/bin, and give it permission to run (chmod +x).

Code:

tar xfz gHamachi_gtk2.tar.gz
sudo mv ghamachi /usr/bin/
sudo chmod +x /usr/bin/ghamachi

Once that is done, the Hamachi GUI is completely installed.

Start the GUI like this:
Code:

ghamachi

Sunday, September 6, 2009

Formatting of date in bash terminal


$ date
Mon Sep 7 08:45:53 SGT 2009

$ date +'%m-%d-%y'
09-07-09

$ date +'%D'
09-07-09

$ date +'%H:%M%P'
08:49am

Ruby regular expression

I'm not a regular expression expert nor am I a fan of its cryptic syntaxes. Nevertheless it's a useful tool to have in your programming toolbox

# String to match
message = "3798536196 Sun 10:02pm Jason Ong jasonong: @nazroll Dude, any possibility of some Wave action via uStream on that day? :) "

# Match sequence
message =~ /[\s]?[\w]+:[\s]/

# String with matches highlighted
3798536196 Sun 10:02pm Jason Ong jasonong: @nazroll Dude, any possibility of some Wave action via uStream on that day? :)

A good place to test out your ruby regex dynamically is http://rubular.com/

A ruby cheatsheet with good regex reference. http://www.zenspider.com/Languages/Ruby/QuickRef.html

Saturday, September 5, 2009

Parse timestamp string to ruby Time object


# Require time to get parse() method
$ irb
>> require 'time'
>> true
>> Time.parse('Tue Apr 07 22:52:51 +0000 2009')
>> Tue Apr 07 22:52:51 0800 2009

Friday, September 4, 2009

Building a command line twitter client

Just to scratch my own itch.

I've been using twidge BUT...

- Needs me to leave my twitter password lying around in plain text config file
- Doesn't store my friends updates locally (at least for a week?)
- No easy way to RT, reply or even DM for that matter
- Doesn't display with colors (hard to read statuses)
- Doesn't display Name + Screen Name
- Not written in Ruby!

Hence I've started my own command line twitter client project using Ruby

Twitpow

Source:
http://github.com/jasonong/twitpow/tree/master

Screenshot:

Functions:
- Retrieve friend's statuses
  • - Keeps track of last status id on a ~/.twitter file
  • - Gets only statuses that are tweeted later than the last status id

# Get recent new tweets since last get
ruby twitpow.rb friends

- Retrieve a user profile

# Show profile for @jasonong
ruby twitpow.rb user jasonong


- Statuses are stored & searchable in a PStore file

# Get all stored tweets
ruby twitpow.rb history

# Get last 20 stored tweets
ruby twitpow.rb history 20

# Search for "jasonong" in stored tweets
ruby twitpow.rb history search jasonong

- Update a tweet!

# Tweeeeet!
ruby twitpow.rb update "I can haz send a tweeet!"


- Reply to friend's status

# Reply to friend's status with status_id = 31122333
ruby twitpow.rb reply 31122333

# Prompt to key in your reply
Reply to: 31122333 01:00pm Jason Ong jasonong: This is my status lah!
>> This is my reply!

# @screen_name is prepended to your reply
@jasonong This is my reply!

- Retweet a friend's status

# Retweet friend's status with status_id = 31122333
ruby twitpow.rb retweet 31122333

# Prompt to key in a message to prepend the retweet
31122333 01:00pm Jason Ong jasonong: This is my status lah!
>> Awesome my friend!

# Message and @screen_name are prepended to the retweet
Awesome my friend! RT@jasonong This is my reply!

Libraries Used:
- Httparty for REST api
- Highline for password prompt
- Term-Ansi for text color output

TODOS:
- Get replies
- Get DMs
- Get conversation threads
- Get user details
- Post updates
- Post replies
- Post retweets
- Post DMs
- Display status time
- Even better reply
- Even better retweet

Using ruby to output ansi colors in terminal


# Install ansi color gem
sudo gem install term-ansicolor

# Usage example
puts "#{user.name.red} #{user.email.blue.bold}"

Commandline password prompt in ruby


require 'rubygems'
require 'highline/import'

def get_password(prompt="Enter Password")
ask(prompt) {|q| q.echo = false}
end

password = get_password()

Thursday, September 3, 2009

Use nmap to scan for open ports


# Install nmap
sudo apt-get install nmap

# Scan for open ports
nmap IP-address (127.0.0.1 for localhost)

# Check if port is open
nmap -p port-no IP-address

How to use irssi


# Connect to irc server
/connect irc.freenode.com

# Join a channel
/join #hackerspacesg

# List users in channel
/names

# Switch to next window
CTRL + n

# Switch to previous window
CTRL + p

Tips to use mobileterminal on iPhone

Tips

Hide the Keyboard

Tap twice quickly on the screen to hide the keyboard. Repeat to bring it back.

Control Characters

You can send a control-C by pressing the "bullet" key (First press ".?123", then "#+=", then the circle on the middle right), then press the C key. This can be useful when you want to escape out of a long running program such as ping. Control-C can also be accessed with a short Up-Right and Control is a short Down-Right swipe, after which the cursor will turn highlight red, from here press any character q, x, c, A to complete or the delete button to exit Control mode.

Escape is control-[ or a short Up-Left swip, which may come in handy with vi. Tab is control-I or a short Down-Left swip (yay tab completion).

Swipe Controls

Swipe Type Direction Action
Short Up-Right Control-C
Short Down-Right Control-
Short Up-Left Esc
Short Down-Left Tab
Short up/down/left/right arrow keys (respectively)
Long Up None (functions as up-arrow)
Long Down Enter
Long Left None
Long Right None
Two Finger Up Config
Two Finger Down Hide Keyboard
Two Finger Left Page-Up/Next
Two Finger Right Page-Down/PREV

None of the Two Finger Swipes seem to work right in 2.0 firmware

Multiple Terminals

Terminal comes with four terminal windows. Tap on the battery icon to go right, tap directally on the time to go left, and tap on the carrier name (AT&T or iPod) to crash Terminal (or do a really quick killall Terminal depending on how you look at it).

Wednesday, September 2, 2009

Cucumber feature template

Feature:title

In order to [Business Value]
As a [Role]
I want to [Some Action]

Tuesday, September 1, 2009

Do not use Ruby's Enumerable find() method in Rails

According to ruby doc.


find enumObj.find {| obj | block } -> anObject or nil

Synonym for Enumerable#detect .


However if you ever try to use Enumerable#find in Rails, you'll get a "cannot find object without object id" error.

Better to use Enumerable#detect

The problem with using Rail's try() method


@jasonong Try not to use Rail's try() method; makes debugging
difficult coz error not thrown.

Git: creating, pushing & deleting remote branches

I work on multiple machines. Need temporary remote branches that I can sync them with.

# create remote branch from a local branch
git push origin LOCAL_BRANCH:refs/heads/REMOTE_BRANCH

# push commits to remote branch
git push origin LOCAL_BRANCH:REMOTE_BRANCH

# pull commits from remote brance
git pull origin REMOTE_BRANCH

# delete remote branch
git push origin :REMOTE_BRANCH

Hidden features of Ruby

http://stackoverflow.com/questions/63998/hidden-features-of-ruby

Blog Archive