Showing posts with label efficiency. Show all posts
Showing posts with label efficiency. Show all posts

Monday, June 09, 2008

Launching apps in command line (Mac)

In most cases, to launch an application on a Mac is just a matter of using the awesome QuickSilver keyboard shortcut and type in what you want to open. But, sometimes it is useful to be able to launch/open an application in command line or terminal in a scripting context.

So, instead of going through all the typing $ /Application/MyFavouriteApp/Contents/MacOS/MyFavouriteApp in your terminal, you can do:

$ open -a MyFavouriteApp

This will open any applications in your /Applications folder by name.

Wednesday, December 26, 2007

Go to mysql command shell using rake

Tired of typing mysql -u foo -pbar -h db01.firewalled.com baz_development yet? Add to that when you have database environments galore like test, QA, selenium, staging, etc.

Here's a rake task for you. Just point it to a Rails environment and execute and you are in the corresponding mysql command prompt.

e.g.

$ rake mysql RAILS_ENV=qa

Loading mysql in RAILS_ENV=qa...
Executing: mysql -u foo -pbar -h localhost baz_qa_test

Reading table information for completion of table and column names
You can turn off this feature to get a quicker startup with -A

Welcome to the MySQL monitor. Commands end with ; or \g.
Your MySQL connection id is 1
Server version: 5.0.51 Source distribution

Type 'help;' or '\h' for help. Type '\c' to clear the buffer.

mysql>


Code:
desc "Loads mysql command prompt"
task :mysql do
puts "\n\nLoading mysql in RAILS_ENV=#{RAILS_ENV}...\n"

database_yml_path = "#{RAILS_ROOT}/config/database.yml"
database_yml = YAML.load(ERB.new(File.read(database_yml_path)).result)

raise "Could not find environment #{RAILS_ENV} in database.yml" unless database_yml[RAILS_ENV]

config = database_yml[RAILS_ENV]
username = config['username']
password = config['password']
database_name = config['database']
host = config['host'] || 'localhost'
port = config['port'] || 3306
socket = config['socket'] || '/tmp/mysql.sock'

raise "Failed. Setup requires a user and database for environment #{environment} in '#{database_yml_path}'.\n\n#{database_yml.to_yaml}" unless username and database_name

args = "-u #{username}"
args << " -p#{password}" unless password.to_s.strip.empty?
args << " -h #{host}" unless host.to_s.strip.empty?
args << " #{database_name}"

command = []
command << "mysql #{args}"

puts <<-EOS
Executing: #{command.join(' ')}\n

EOS

system command.join(' ')
end

Monday, December 17, 2007

Rid of those TextMate "ctags timed out!" error

If you use TextMate for your Ruby on Rails development, you must use the ctags bundle CTags.tmbundle. It gives you a keyboard shortcut CTRL-] to jump to files that defines the class/method your cursor is on. Similar to "go to file and line" in some IDE. Super handy.

Trouble is when your project gets large, it gets longer and longer to update the tmtags index file to a point where it exceeds the default 15 seconds timout and gives a "ctags timed out!" error.

What you can do is edit the file ~/Library/Application\ Support/TextMate/Pristine\ Copy/Bundles/CTags.tmbundle/Support/bin/tmctags and increase the timeout $CtagsTimeout value to something more reasonable. Problem solved.

p.s. CTags suffers from another shortcoming, and that is it cannot index ruby methods named ending with a ? or !. Anyone knows of a fix/workaround? Please comment if you do!

Friday, December 14, 2007

Why create database migrations, when you don't need to?

Rails out of the box supports database migration. It allows Rails programmers to be more Agile, do less database BDUF and instead change the database schema as the requirements change and the business wants it. Writing a migration is also as easy as running a command line script/generate migration and then executing it with rake db:migrate.

Database migration is useful for two reasons. Number one is to allow developers to change the database schema. This can be as simple as a single ALTER TABLE statement to add a new column. Number two, more importantly, is to migrate the all-important data exist in the database. But if your application is still under development for initial release, then migration may not be buying you too much good, because chances are no one cares how your table structure got to where it is now, and you may not have a whole lot of data.

We all use migrations feverishly probably because most of the Rails books/references/tutorials begins with: "Let's start by creating a database migration, in it we insert some data into the newly created tables, and learn how to do XYZ." Thus, your db/migrate folder is stuffed with migrations that does everything: create new tables; alter existing tables; create data for those tables; update data created from previous migrations; and perhaps all of the above, while without justifiable reasons on what those migrations are trying to migrate. In practice, it is quite time-consuming for a developer to run 200+ migrations every time he blows away a database, which is not uncommon. Not only that, sometimes you have multiple migrations that basically cancel out each other's changes as our customers change their minds back and forth. As a result, you could be creating migrations left and right when there may not be any real beneficiaries: a database loaded with data.

Sometimes your QA team may have their own data set that tests your app, and thus their loaded database is a beneficiary. While that is true, I prefer their data to be scripted and be freshly generated by ActiveRecord models (using create!) every time instead of keep migrating them, because as my application domain model expands, I want not just QA data but all datasets to be cleansed and validated by my model validations. There is no guarentee that after running a drop_column migration the QA dataset does not violate any business logic. Keeping all these data valid while database migrations are being rapidly created is very hard.

To take advantage of the fact that your development environment has nothing to lose until you have an initial release, while maximizing the benefits of keeping all your data valid (for all enviroments) the whole time while your app is under development, it's a simple steps 1-2-3:


Step 1:

Have one migration file, 001_release_one_schema.rb, that captures all database object creations. For example, all your create_table, create_index, views, triggers (*yikes*), etc. After this migration, your database should contain all database objects for your Rails app but in a "blank", data-less state.

$ cat db/migrate/001_release_one_schema.rb

class ReleaseOneSchema < ActiveRecord::Migration
def self.up
create_table "foos" do |t|
end

(... and many others ...)
end

def self.down
(... ... ...)
end
end


Step 2:

Create a rake task to populate all reference data that your application requires to run with. Reference data meaning all data that your application cannot change through its screens, but are essential for your app to run. For example, all currencies that are used to populate a drop-down on your app. A lot of drop-down lists data are reference data.
$ cat lib/tasks/data.rake

namespace :data do
desc "Loads a default dataset of both reference and user data into database."
task :load => [ :environment,
:configuration,
:reference_data,
:user_data ]

private

task :configuration do
ENV['DATASET'] ||= 'slim'
end

task :reference_data do
require "#{RAILS_ROOT}/db/data/reference_data/#{ENV['DATASET']}"
end
end

$ cat db/data/reference_data/slim.rb

@us_dollar = Currency.create! :name => "US Dollar"
@yen = Currency.create! :name => "Yen"
@euro = Currency.create! :name => "EURO"
... ... ...


Step 3:

Create a rake task to populate all user data that your app requires to run with. User data are data that a user can create/update within your application. They are also required for the Rails app to function properly the first day when it launches. For example, for your flashy Paypal application, the fees structure on how it charges its users. An application administrator is allowed to raise or drop fees in your app.


namespace :data do

private

task :user_data do
require "#{RAILS_ROOT}/db/data/user_data/#{ENV['DATASET']}"
end
end

$ cat db/data/user_data/slim.rb

Fee.create! :amount => 1_000, :currency => @us_dollar
Fee.create! :amount => 1_500, :currency => @yen
Fee.create! :amount => 2_500, :currency => @euro
... ... ...


There are several benefits of managing your database schema and data this way:
  • It is easier and faster to re-populate your entire database to the latest schema from scratch with data, since there are no extraneous migrations.

  • Faster to locate and update data needed for application. They are always in your dataset generation scripts.

  • No need to worry about outdated/removed ActiveRecord classes and declare them inside the migration file itself. They is no "legacy" ActiveRecord models.

  • All data are valid all the time because they are created through Model.create! sanitized by your model validations.

  • Easy to specify datasets to load by preference for DEV (slim, loaded), BA (story sign-off), QA (scenario-based), or demo (full) environments. e.g. rake data:load DATASET=slim RAILS_ENV=qa

  • No worries about broken/incomplete migrations. Fewer code, fewer trouble.

Now, after your Rails app goes to a 1.0 production release, you should switch this back to the normal Rails database migration style. I suspect your application users won't be too happy if you blow away their data every time you roll out a minor update or a major release... (or not?)

Wednesday, November 21, 2007

Stop tangling those iPod earbuds!

You have an iPod? If you ever use their white trademarked earbuds, chances are every time you pull them out of your pockets you spend 40 seconds of your life untangling those stupid wire. It adds up.

Ever notice there is a little sliding thing at the Y-split of your earbuds on the wire? I assume it is used to reduce the split between the two ear pieces when you are wearing them. If they are for that purpose I have never used them. But I did find a better use of it...

Next time when you are done using them, slide that thing all the way to the ear pieces. This will make your Y-splitted earbuds into essentially one straight wire, and thus reduce a lot of unnecessary tangling. Hopefully this saves you some annoying faces in untangling the thing (maybe that's why those Apple billboards have no face on them...)

Friday, January 05, 2007

Migrate Thunderbird mailboxes from Windows to Mac

When I moved from my Windows machine to a Mac I had a bunch of mail in my Thunderbird that I wanted to migrate over. These are emails going back to the days of the war in online email services. As it turns out it isn't as easy as copying the mailboxes over from Windows to my shiny Mac. MozBackup didn't work for me because it is only for Windows-to-Windows. I found a solution after some soul searching from Google... Turns out it's almost as easy as copying over your mailboxes...

1) Install the T-Bird extension MBoxInput
This is the beauty in open standard. Mailboxes in T-Bird are stored in MBox standard, therefore they are portable to whichever email client you wish to use. Install this onto your Mac T-Bird.

2) Copy your mailboxes from your Windows T-Bird profile folder to your Mac
They are in your %APPDATA%\Thunderbird\Profiles folder. I used my good-ole USB drive...

3) On your Mac, right click on your Folders menu, there will be a "Import/Export" item. Select it, and then choose the mailbox in your Profile folder/sub-folder you want to import (eg. Inbox)
If you have multiple email accounts set up, you can right click on the account before selecting Import/Export. The mail will then be imported into the appropriate account as a subfolder.

Sunday, September 24, 2006

Enhance your irb experience on Windows

You can extend the functionality of your irb on Windows by creating a file .irbrc in your %userprofile% directory. Put some Ruby code in there, and they will get loaded when you launch your irb, as well as your script/console. I have put in some code snippets in there to aid my irb experience.

(You may have issues trying to create a file with its name beginning with a period on Windows Explorer. Try to run the command "notepad .irbrc" in your cmd.exe)

Tab Completion

require 'irb/completion'
ARGV.concat [ "--readline", "--prompt-mode", "simple" ]
Do you miss intellisense? If you do this, then in irb, type in like "text".s[tab][tab] will give you a list of methods in String that starts with s.

Ruby Interactive (ri) reference in irb
def ri(*names)
system(%{echo | ri #{names.collect { |name| name.to_s }.join(" ")}})
end
Then you can type ri 'String.strip' to see the Ruby index. The argument has to be a string though.

Remember, on a Windows machine, you have to put "echo | " in front of your ri line or else your irb will just return 'false'. I know it's counterintuitive that it isn't at the end, but it works.

Clear screen
def cls
system('cls')
end
I always wanted clear screen...

Console messed up with long irb lines
If you have a line of Ruby code that is way too long, and you want to go back and make changes, on Windows console it is not very friendly as it will almost guarentee to mess up your edits and disorient your typings. The only way I Googled on how to fix this is to take away the "--readline" switch from the Tab Completion tip above, and replace it with "--noreadline". But then you lose Tab Completion of course. I haven't found a workaround for it yet, but in the mean time I will happily just use Cygwin bash shell =)

Tuesday, September 05, 2006

The most revolutionary usernames and passwords, ever

Haven't you written the authentication piece for your app? Isn't it annoying after it is implemented in your app, every time you try to access your app's functionality during development, you have to start logging in every time by typing in some dev-only user id with a fake password? Having a good set of tests helps alot in terms of not having to go through the app starting from login while new features are still undergoing development, but there are still many cases where you have to debug something starting from the first login page of your application.

Over time, I have developed one way to mitigate this nuisance, by creating a few dev usernames and passwords of the following pattern:

Users:
+ dave
+ fred
+ cat
+ red

Passwords:
+ create
+ database
+ case
+ ware
+ vase
+ card
+ garbage
+ beta

Now the question is, what is the pattern? Answer me in 10 seconds...

That's right, I can finish typing all of them with my left hand, while my right hand still holding my mouse and not have to switch from my mouse to my keyboard to type the password, then my mouse to hit the 'Login' button.

Did you get the pattern in 10 seconds?

Sunday, August 13, 2006

Time is money... Stop using your Quick Launch or Start menu

Do you have a list of 30+ icons of applications you use daily in you Quick Launch taskbar and you turned on its auto-hide feature? Do you try to actively manage your Start/Programs folders to make it easier for you to find and launch applications? Are you running out of keyboard shortcuts to launch your favourite applications? If you say yes to all these questions, chances are you are a power keyboard-driven user of your computer. It's simply a breeze without having to move your hands away from the keyboard and do everything on your computer.

To add more ammunition to you keyboard freaks, download and try Colibri. This is an application that lets you launch your apps by simply typing in a pattern that matches your apps' names! I mapped it to the F12 key on my laptop. When I want to launch Firefox, I press F12, then type in "fox", and hit enter and it is launched; When I want to launch MSN Messenger, I press F12, type in "mess", hit enter and it is launched...

It's pretty much similar to Google Desktop, but in GD after typing I have to use the up and down arrows multiple times to nav away from other doc types to get to app's exe. Colibri is strictly for app launching. If I type in "mess" for MSN Messenger, it will remember that you have used it to launch MSN Messenger, so next time rather than suggesting you to launch Y! Messenger it will default to MSN Messenger, while letting you to arrow down to select Y! Messenger should you want to.

I rarely use my Quick Launch or my Start menu anymore...

Bonus Tip 1: Did you know shift-F10 opens up your mouse right-click menu?
Bonus Tip 2: Turn on your "Begin finding when you begin typing" feature in your Firefox. I use this to "type-and-hit-enter" to surf the web =P

Wednesday, April 19, 2006

Checking duplicate Sql statements in Excel

In my current project we are doing database Continuous Integration (CI). This means that every developer will have their own database instance for development, and at every check-in the build server kicks off the CI cycle, which starts getting the latest source code, compile, rebuild the database from scratch through running SQL scripts, re-insert data (reference data) these tables should have, compile, test, etc. When done right, this allows the much-required freedom for developers to develop against the database without interfering other developers' databases, and significantly reduces the time it takes to ask the DBA's to modify the database table for you.

When you acquire from the customer/business analysts a new set of reference data that they would like you to insert into these database tables, I have seen in many cases where these new data conflicts with the data that already exists due to duplication (mostly human error). Since most of these reference data are scripted in text files and there are usually hundreds if not thousands of them, sometimes finding that one duplicating line is like trying to find a needle in a sea.



Fortunately in Excel there is a function to rescue: =COUNTIF(set, to_find).

Usage: Increment count if "to_find" exists in "set".

So to quickly find out which is the offending PK constraint INSERT line, you do this:
=COUNTIF(E3:E11, E3)



And as you see you will quickly find out where that awful INSERT statement is... Time to bug the customer =)

Friday, June 10, 2005

Want to whip up some quick UI Tree?

I had to produce for one of my clients some form of UI Tree to help them to focus on how various pieces of user interactions with the system is going to take place from a UI perspective. It went from paper bubbles to Visio-lizing it and client still don't like it. Finally, I stumbled across this product that saves the day.

It is basically a map of thoughts organized in a click-me-and-drill-down-as-you-go application. The point is, it proides a very easy drag-and-drop tree creating inetrface to do the job very quickly.

At the end of the day this did wow the people who saw it, and it is extremely easy to use. It got the job done. I am however interested in the many ways of people who create the so-called UI Tree how they do it.