Saturday, November 29, 2008

Rails conventions

Models (and therefore the underlying classes they create) are capitalized and singular. Each creates a table that is lower-cased and plural.
 ./script/generate scaffold Student name:string
rake db:migrate
Looking at db/schema.rb shows:
ActiveRecord::Schema.define(:version => 20081129213933) do

create_table "students", :force => true do |t|
t.string "name"
t.datetime "created_at"
t.datetime "updated_at"
end

end
The views and controllers are plural: app/views/students and app/controllers/students_controller.rb, but the model is singular: app/models/student.rb. Remember there is a hidden "id" field in each row of each table so don't create your own "student_id" field.

And from http://itsignals.cascadia.com.au/?p=7
Model Naming Convention

Table: orders
Class: Order
File: /app/models/order.rb
Primary Key: id
Foreign Key: customer_id
Link Tables: items_orders

Controller Naming Convention

Class: OrdersController
File: /app/controllers/orders_controller.rb
Layout: /app/layouts/orders.html.erb

View Naming Convention

Helper: /app/helpers/orders_helper.rb
Helper Module: OrdersHelper
Views: /app/views/orders/… (list.html.erb for example)

Blogging

I've been blogging for five years now. When i started, i didn't like any of the extant software so did what i do too often and wrote my own. I migrated to geeklog, and now here. I'll be posting some of the more relevant bits from the previous ones here as time goes by...

Bodum Santos/Pebo


I have a stovetop Bodum Santos (now Pebo) and like it. Its tons of fun at parties. Its best to use a course grind, and importantly to allow the brewing to take one minute. That is, after the water is in the top, turn down the heat but don't turn it off until the top has churned for a minute. This helps a lot when the coffee is "vacuumed" back down. Otherwise, the filter clogs easily. I do wish Bodum would come back out with their electric version, especially the smaller of the two versions...

Friday, November 21, 2008

Bash menu script

I long had a csh script that reads a '.choices' file in each directory, display the choices, and execute my choice. Well, i've migrated away from csh and no longer have it on many of my machines. So, i wrote the following:
#! /bin/bash -e

filename=".choices"

if [ "$1" == "-f" ]
then
    filename="$2"
    shift
    shift
elif [ ! -r $filename ]
then
    prefix=.
    while true
    do
        absolute=$(cd $prefix; pwd)

        if [ -r $absolute/$filename ]
        then
            filename=$absolute/$filename
            break
        fi

        if [ $absolute = "/" ]
        then
            echo "No .choices file found, exiting"
            exit 1
        fi

        prefix=$prefix/..
    done
fi

if [ "$1" != "" ]
then
    a=$1
    shift
    echo `sed -ne "$a,$a p" $filename` $*
    eval `sed -ne "$a,$a p" $filename` $*
    exit
fi

IFS=$'\n'

select CHOICE in `cat $filename`
do
    eval $CHOICE $*
    break
done
 

This wasn't as easy as it looks. Getting bash to create a single word for the select statement from lines in a file. Finding the right incantation for the IFS was the tricky part...

Thursday, November 20, 2008

Ubuntu live usb

Downloaded and installed the .deb from http://klik.atekon.de/liveusb/. Mounted via loop a distribution i had around:
sudo mount -o loop Desktop/ubuntu-8.04.1-desktop-i386.iso /cdrom
Ran 'liveusb' and it worked. Love that ubuntu...

Wednesday, November 19, 2008

Rails on Linux

yum install ruby
yum install ruby-devel
yum install rubygems
gem install rails
gem install mongrel
gem install sqlite3-ruby

Thursday, November 13, 2008

Broken Brother paper folder

I'm an gadget guy. Bought a cheap Brother paper folder a couple of years ago and recently it started eating paper instead of folding it. So, i torn it apart. Sure enough, the "rubber bands" that hold everything together had disintegrated. Happily, i had some electrical cable ties that fit. Works again. Here's a cheesy cell phone photo that shows the rubber bands and the new cable ties:

Trials with a Garmin eTrex Legend

I've had a Garmin eTrex Legend for quite a while now. It started acting quite flaky: powering down randomly, not displaying all the pixels, etc. Apparently I not alone in this. Found distructions at http://users.tpg.com.au/benj2005/gps/inside_etrex.htm and being who I am, went for it. Much better afterward. Then I wanted to upgrade the software and keep it updated. This has turned in to a much bigger pain. Was able to use the serial connection and a Windows machine to do the upgrade, but I don't do Windows very often and want to use one of my Macs. IOGear GUC232A USB->serial cable. Again, works with Windows, but not OSX 10.4. Grabbed the driver from http://sourceforge.net/projects/osx-pl2303/. The IOGear is recognized:

Steve-Beatys-Computer:~ beaty$ ls -l /dev/tty.*
crw-rw-rw- 1 root wheel 11, 2 Oct 2 14:33 /dev/tty.Bluetooth-Modem
crw-rw-rw- 1 root wheel 11, 0 Oct 2 14:33 /dev/tty.Bluetooth-PDA-Sync
crw-rw-rw- 1 root wheel 11, 10 Oct 4 08:33 /dev/tty.PL2303-0000103D

and I can connect to it via 'screen' and make the LED flash, but Garmin's WebUpdate doesn't see it. So it looks like i'll have to find a

Wednesday, November 12, 2008

Mounting a NTFS image in Linux using loop

I had a binary image, created by dd (its important to grab the whole disk, not just one partition):
dd bs=1M if=/dev/sdd of=tag1.bin
of a disk drive from a Windows box that i wanted to explore in Linux. Looking at the file gives:
$ file tag1.bin
tag1.bin: x86 boot sector, Microsoft Windows XP MBR, Serial 0xe475e475
With some help from http://jonmccune.wordpress.com/virtualization-stuff/ i did:
/sbin/fdisk tag1.bin
You must set cylinders.
You can do this from the extra functions menu.

Command (m for help): x

Expert command (m for help): p

Disk tag1.bin: 255 heads, 63 sectors, 0 cylinders

Nr AF  Hd Sec  Cyl  Hd Sec  Cyl     Start      Size ID
1 80   1   1    0 254  63 1019         63   16386237 07
2 00   0   0    0   0   0    0          0          0 00
3 00   0   0    0   0   0    0          0          0 00
4 00   0   0    0   0   0    0          0          0 00

The interesting bit is the "Start" column, which is where the first partition starts. One multiples by the sector size (512) to arrive at:
mount -o loop,offset=32256 tag1.bin /tmp/mount/

Tuesday, November 11, 2008

Headphones

I usually listen to music in headphones and i seem to have a decent set of ears, so sound quality means a lot. One cannot beat the audio-technica ATH-AD700 for the money. I found mine for ~$115 and they are stunning. Huge, but with glorious sound.

In a different category are my etymotic ER4S's. In-ear, sound blocking, great sounding. More expensive. Check out http://www.etymotic.com/ for more details. Oh yeah, and give serious consideration to the ety.com cell phone headset while you're there. Best one i've tryed, and i've tryed a bunch. A steal for $40.

In yet a different category, for beater/on the train listening, i use "Skullcandy Buds Inked" for less than $20 at Target.

An interesting coffee maker


I like coffee, good coffee that is. For ~$30 it's very hard to beat the Aeropress from Aerobie http://www.aerobie.com/Products/aeropress.htm Looks weird maybe, but makes great tasting coffee with little fuss or mess. Also good for camping...

Friday, November 7, 2008

I wanted to execute JavaScript in a Java program. Rhino looked like it would do the trick, but there is no DOM without a browser, and i wanted to run browser-less. I found a lot of discussion around this but none worked just right. Here is the incantation i used:
document = new Object ();
document.writeln = function (s)
{
if (s instanceof Array)
for (x in s)
document.writeln (s[x]);
else
java.lang.System.out.println (s);
}
document.write = function (s)
{
if (s instanceof Array)
for (x in s)
document.write (s[x]);
else
java.lang.System.out.print (s);
}

I imagine i could extend it to capture most of what a browser's DOM contains; maybe some day.
I also modified RunScript to read from System.in and inject the above code:
import java.io.FileReader;
import org.mozilla.javascript.*;

public class RunScript
{
public static void main(String args[]) throws
java.io.FileNotFoundException, java.io.IOException
{
String s = "document = new Object ();" +
"document.writeln = function (s)" +
"{ java.lang.System.out.println (s); };" +
"document.write = function (s)" +
"{ java.lang.System.out.print (s); };";

Context cx = Context.enter();
try {
Scriptable scope = cx.initStandardObjects();

Object result = cx.evaluateString (scope, s, "<prelude>", 1, null);

FileReader in = new FileReader (args[0]);

result = cx.evaluateReader (scope, in, args[0], 1, null);

System.err.println(Context.toString(result));

}
finally
{
Context.exit();
}
}
}

More practice with forms and php

First, carefully read http://www.w3.org/TR/html401/interact/forms.html and ask any questions you have. Here is a very simple form:
<html>
<head>
<title>A very simple form</title>
</head>
<body>
<form action="display.php" method="post">
<input name="string">
<input type="submit">
</form>
</body>

And here is a very simple php page to display the results:
<html>
<head>
<title>Display the result of a form submission</title>
</head>
<body>
The contents of the form submission are:

<?php
print_r ($_REQUEST);
?>

</form>
</body>

Save these two files and get them working on your machine. Given this, we can create a page for a simple calculator:
<html>
<head>
<title>A Simple Calculator</title>
</head>
<body>

<form action="calculator.php" method="post">
<input name="number1">
<select name="operator">
<option selected value="plus">+</OPTION>
<option value="minus">-</OPTION>
<option value="divided by">/</OPTION>
<option value="times">*</OPTION>
</select>
<input name="number2">
<input type="submit">
</form>

</body>
And the corresponding code to make it work:
<html>
<head>
<title>Calculator Results</title>
</head>
<body>

<?php
$number1 = (int) $_REQUEST["number1"];
$number2 = (int) $_REQUEST["number2"];
$operator = $_REQUEST["operator"];

echo $number1 . " " . $operator . " " . $number2 . " equals ";

if ($operator == "plus")
echo $number1 + $number2;
else if ($operator == "minus")
echo $number1 - $number2;
else if ($operator == "times")
echo $number1 * $number2;
else if ($operator == "divided by")
echo $number1 / $number2;
?>

</form>
</body>
Save these two files and get them working on your machine. As PHP is embedded in HTML we can have just one form to both create the form and evaluate it. This time, we'll submit the page to itself:
<html>
<head>
<title>A Simple Calculator</title>
</head>
<body>

<form action="calculator2.php" method="post">
<input name="number1">
<select name="operator">
<option selected value="plus">+</OPTION>
<option value="minus">-</OPTION>
<option value="divided by">/</OPTION>
<option value="times">*</OPTION>
</select>
<input name="number2">
<input type="submit">
</form>

<?php
$number1 = (int) $_REQUEST["number1"];
$number2 = (int) $_REQUEST["number2"];
$operator = $_REQUEST["operator"];
if ($operator == "")
$operator = "plus";

echo $number1 . " " . $operator . " " . $number2 . " equals ";

if ($operator == "plus")
echo $number1 + $number2;
else if ($operator == "minus")
echo $number1 - $number2;
else if ($operator == "times")
echo $number1 * $number2;
else if ($operator == "divided by")
echo $number1 / $number2;
?>

</body>
</html>
Save this file and get it working on your machine. Now, go back and redo the JavaScript coffee assignment first as two pages, then as one.

Things to consider when creating web applications.
  1. What data are needed?
  2. What operations are done on the data?
  3. What logic is needed to make sure the operations work on all possible data and create the correct results?

Wednesday, November 5, 2008

Blackberry on Ubuntu

retrieved barry-0.14.tar.bz from http://sourceforge.net/projects/barry. needed to add the g++ and libusb-devel packages in order to configure and make.