map_by_method now increasingly more niftier-er.

Posted by Dr Nic on October 26, 2006

Recap on map_by_method magic:

>> p.account.transfers.map_amount # amount method mapped to all Transfers
=> [1878.35, 433.0, 433.0, 433.46, 433.46, 433.46, 433.46, 433.46, 300.0, 300.0]
>> p.account.transfers.map_date.map_to_s # date method mapped to all Transfers, and the Dates mapped into strings
=> ["2003-05-27", "2003-06-23", "2003-06-27", "2003-07-04", "2003-07-11", "2003-07-18", "2003-07-25", "2003-08-08", "2003-09-25", "2003-10-03"]

But if you want the amount and date methods mapped at the same you’ve been plain out of luck, and forced to use the uglier block syntax:

>> p.account.transfers.map {|t| [t.amount, t.date]}

Due to demand-by-inspiration (that is, I just thought of it), you can now use _and_ to join method names together, thusly:

>> p.account.transfers.map_date_and_amount
[[#<Date: 4905573/2,0,2299161>, 1878.35],
 [#<Date: 4905627/2,0,2299161>, 433.0],
 [#<Date: 4905635/2,0,2299161>, 433.0],
 [#<Date: 4905649/2,0,2299161>, 433.46],
 [#<Date: 4905663/2,0,2299161>, 433.46],
 [#<Date: 4905677/2,0,2299161>, 433.46],
 [#<Date: 4905691/2,0,2299161>, 433.46],
 [#<Date: 4905719/2,0,2299161>, 433.46],
 [#<Date: 4905815/2,0,2299161>, 300.0],
 [#<Date: 4905831/2,0,2299161>, 300.0]]
>> p.account.transfers.map_date_and_amount.map_map_to_s
[["2003-05-27", "1878.35"],
 ["2003-06-23", "433.0"],
 ["2003-06-27", "433.0"],
 ["2003-07-04", "433.46"],
 ["2003-07-11", "433.46"],
 ["2003-07-18", "433.46"],
 ["2003-07-25", "433.46"],
 ["2003-08-08", "433.46"],
 ["2003-09-25", "300.0"],
 ["2003-10-03", "300.0"]]

Note the dubious/amusing use of map_map_to_s to apply to_s to the inner arrays. That is, map_to_s is mapped to each inner array.

Want this extended map_by_method magic? Version 0.5 of map_by_method is ready via gem install map_by_method now (or direct download)

Bonus use

Make simple arrays for drop-down lists based on id and a string name field of a list of objects.

>> User.find(:all).map_id_and_firstname
=> [[1, "Glenda"], [2, "Brenda"], [3, "Yas"], [4, "Osborne"], [5, "Gary"], [6, "Anthony"], [7, "Jackie"]]

Debugging use

Some of my Transfer rows had amounts of zero. This was just stupid, but as the initial data was being migrated from a variety of sources I needed to figure out where it was coming from.

“I wonder which account owner(s) this erroneous data comes from?”

> zero_transfers = Transfer.find(:all,:conditions => ['amount < 10 and amount > -10'])
> zero_transfers.map_from_account.map_owner.map_name
["Brenda",
"Brenda",
"Brenda",
"Brenda",
"Brenda"]

And I now knew which files to start cleaning up before re-importing all the data again.

Data investigation in the console/irb becomes almost fun.

Congratulations to Mr Dilbert – Scott Adams

Posted by Dr Nic on October 24, 2006

That he writes the funniest, most relevant cartoon strip around is secondary to the man himself, and his life journey.

A year and a half ago he lost his voice. Statistically, he had a 0% chance of getting it back. Let’s all agree: That’s quite low.

Today his voice returned. Incredible story.

53 cheat sheets and growing

Posted by Dr Nic on October 19, 2006

I said previously that errtheblog’s cheat app would have 100s+ of cheat sheets.

After a month and a half, they are now half way. There is still more cheating to be done.

> require 'map_by_method'
> require 'hpricot'
> require 'open-uri'
> doc = Hpricot(open("http://cheat.errtheblog.com/b"))
> cheatsheets = doc.search('div.content/ul/li').children.map_inner_html.flatten
=> ["ascii", "assertions", "assert_select", "balloon", "bash", "belongs_to", "blogs",
"callbacks", "capistrano", "cheat", "database_yml", "deprecated", "environments",
"exceptions", "firebug", "google_mail", "google_reader", "gruff", "has_and_belongs_to_many",
"has_many", "has_one", "http_status_codes", "iomodes", "jedit_ruby_editor_plugin",
"link_to_remote", "markaby", "markdown", "matz_bot", "microformats_helper",
"migrations", "mocha", "nonsense", "prototype", "rails_console", "rails_edge", "rdoc",
"readline", "regex", "rjs", "rspec", "ruby", "scrapi", "sprintf", "sti", "strftime", "svn",
"tempfile", "textmate_rails", "tld", "validations", "vim", "vim_goodies", "wmii3"]
> puts "#{cheatsheets.length} cheat sheets and counting..."
53 cheat sheets and counting...

By the way, they celebrated when they hit 42.

Create and deploy command line apps with RubyGems

Posted by Dr Nic on October 18, 2006

RubyGems have many things going for them: they are a local, central repository for all external libraries, they have explicit versioning, you get inter-gem dependency checking, default integration with the RubyForge gem server, and the ability for you to run your own gem server. For free. Neat.

Hidden in the back, in no way obvious as to its existence nor how to use it, is my favouritest feature: command line executables that are platform-neutral.

Write your executable inside a gem, and regardless what platform the gem is deployed to they will be able to execute the application.

Examples of gems with command line applications

rails has the rails app to generate scaffolding for a new application, camping has its camping app as its runtime server, and cheat has the cheat app to retrieve and cache the cheat sheets.

Whilst rails and camping gems come with libraries of code and complementary test suites, cheat has nothing but its cheat app. The gem exists to deploy a command line application that is written in Ruby.

Create your own command line app in Ruby

Install the latest version of newgem (minimum v0.5)

gem install newgem

Create a new gem:

> newgem -b hello_world,print_date my_fun_apps
creating: my_fun_apps
creating: my_fun_apps/CHANGELOG
creating: my_fun_apps/README
creating: my_fun_apps/lib
creating: my_fun_apps/lib/my_fun_apps
creating: my_fun_apps/lib/my_fun_apps.rb
creating: my_fun_apps/lib/my_fun_apps/version.rb
creating: my_fun_apps/bin
creating: my_fun_apps/bin/hello_world
creating: my_fun_apps/bin/print_date
creating: my_fun_apps/Rakefile
creating: my_fun_apps/test
creating: my_fun_apps/test/all_tests.rb
creating: my_fun_apps/test/test_helper.rb
creating: my_fun_apps/test/my_fun_apps_test.rb
creating: my_fun_apps/examples
creating: my_fun_apps/setup.rb
NOW - update my_fun_apps/Rakefile with gem description, etc

The new -b app[,app2] parameter generates the scaffolding for two executables – hello_world and print_date. If you need more apps in a gem after running newgem scaffolding, its very simple, as shown below.

In bin/hello_world put:

puts "Hello world"

In bin/print_date put:

puts Time.now

And build and install your gem:

> rake package
(in C:/InstantRails/ruby_apps/my_fun_apps)
rm -r .config
  Successfully built RubyGem
  Name: my_fun_apps
  Version: 0.0.1
  File: my_fun_apps-0.0.1.gem
mv my_fun_apps-0.0.1.gem pkg/my_fun_apps-0.0.1.gem

> gem install pkg/my_fun_apps-0.0.1.gem
Attempting local installation of 'pkg/my_fun_apps-0.0.1.gem'
Successfully installed my_fun_apps, version 0.0.1
Installing RDoc documentation for my_fun_apps-0.0.1...

or simply use the install task to do both jobs (on unix machines):

> rake install

Note: If you get a build error it may be because you don’t have the ability to generate the tar file version of the gem. Change p.need_tar = true to p.need_tar = false near the end of the Rakefile and run the above lines again.

And presto! You have two new command line applications:

> hello_world
Hello world

> print_date
Wed Oct 18 12:05:56 W. Europe Daylight Time 2006

Adding more executables to a gem

Two step process:

  1. Create a new text file in the bin folder with the name of the application, and fill it with Ruby goodness. Perhaps investigate SimpleConsole for advanced console coding wizardry.
  2. In the Rakefile, add the application name to the BIN array, at the top.

And then repackage and install.

Deploying for communal usage

That’s another topic for another day.

Hint: get a new RubyForge account and Request New Project, and I’ll try to finish the article before RubyForge administrators accept your proposal.

How to make rails scale – get a Sun BlackBox

Posted by Dr Nic on October 18, 2006

Here is the answer to the question “does Rails scale?” that you’ve been getting at parties lately: