October 10, 2007
My Bold Prediction for 2008

  • Google will release the gphone
  • It will be cheaper than the iPhone (by a little)
  • It will NOT work on the regular carriers Verizon, At&T, etc.
  • Google will have their own service that will be faster and cheaper than the current cellphone service providers using their newly leased spectrum and their own hardware
  • The gPhone will be easily hackable
  • Google will release an API for creating applications
  • I will write at least one application for the gPhone
  • I will buy one as will everyone else
  • The default search engine wil be yahoo! (ok not really)
  • In short, with the release of this phone, google will ‘close the loop’. They will own every part of this technology and monetize it. It will be faster and cheaper so they will win and so will we (depending on how you look at it).

    ALL OF YOUR BASE BELONGS TO GOOGLE.

    -mike

Administrator posted at 4:08 pm in: News , tech

September 27, 2007
primospot gets press — and my account is suspended …

First, there is this in the NYPost:
http://www.nypost.com/seven/09262007/news/regionalnews/n_y__gets_a_parking_spot_com.htm

Then this great article on curbed.com:
http://curbed.com/archives/2007/09/26/cool_new_thing_legal_neighborhood_parking_spot_finder.php

If you look at the comments on curbed, it shows the whole story. Basically, I got so much traffic that my host, bluehost.com, decided to block my site. I had a shared (read cheap) account which I had been using to develop and show the site. I had hoped that I would have -real- visitors on the site one day, but was definitely not prepared for the onslaught that is response to press. The lesson learned is 1 visitor a day to thousands may not happen slowly.

Luckily I know people who have thier own servers and was able to move the site quickly (somebox). The site was down for a few hours, but is alive (by redirection) once again.

I got a lot of great suggestions from people using the suggestion form and have much work to do.

Thanks to everyone who blogged my site and was so helpful to me throughout this entire proccess. Now, back to work!

Mike

P.S. Primospot visitors
My to-do list:

  • Enable voting or bad data link so erroneous spots can be automatically deleted.
  • Finish up iPhone version
  • Have the map refresh as user moves away from initial search area
  • Make smaller markers for wider radius searches
  • Lots, lots more
Administrator posted at 7:27 am in: News

August 3, 2007
primospot.com goes beta!

I have been working hard on my latest project, please check it out:
http://primospot.com or http://beta.primospot.com

The idea history:
In a congested urban environment, parking can be a pain. I have been putting up with the alternate side of the street parking in NYC for some time now.
I heard rumor of people drawing maps of their neighborhood to know where best to park. Being the programmer that I am, instead of drawing a map, I decided to craft a google maps mash-up instead using my favorite language, rails. A few weeks later, primospot was born.

How it works:
Put in an address and search for the best FREE parking spot. The map markers are color coded for the best results. This means the green marked spots have the longest time remaining on them, red spots are about to run out, etc. This is not, currently, a way to find paid garages - it is for anyone to input and use an online map of the no-parking information for their ‘hood. If you run a search and the map is empty, then please add some parking spot information. You will need the times and days you -cannot- park. You click ‘Add Location’, input the days and times on the form and click ‘Validate’. After this, you can drag and drop the map marker to the correct location (fine tune) or click ‘edit’ to edit the title or day/time info. After you are happy with this, click ‘Save’. Next time you search for that address the new entry will show up for you — and everyone else using the site!

There is a ‘feedback’ button in the main navigation at the top. Use this to report an issues you have or good suggestions for the site. Please let me know if the site seems slow as this is my first experience with this web host and I am unsure of the load capabilities.

Thanks! and please don’t forget to digg the site or better yet blog about it to get the word out.
-Mike

Administrator posted at 2:29 pm in: News , tech , ruby , rails

June 29, 2007
Fixture Importing and Exporting

Ever wanted to import or export your database (or specific tables) to YAML ? Put the following code into you Rakefile or /lib/tasks as a new rb file and execute:

#rake db:fixtures:import
or
#rake db:fixtures:export

It supports setting the current environment or specifying tables, check the comments. This script currently puts the files in the doc directory, but you can decide where you want it and modify the file_base_path setting. Have fun and thanks to Ratan for the initial code which I modified for my uses. Handy for running tests on your development data or keeping files of ‘known good’ data while trying things out, etc.

#Rake task to populate the default data into the **current environment's database**.
#It can import data from .yml files. The files should be present under "test/fixtures/app_default_data/import" folder.
#Load specific tables using the environment variable "TABLE". Eg:
#=> rake db:fixtures:import TABLE=assessment_components,lookups (Note: There should not be spaces between commas)
#Specific environment using the environment variable "RAILS_ENV"
#=> rake db:fixtures:import TABLE=assessment_components,lookups RAILS_ENV=test
desc "Populates default data reqd. for the app from the fixtures into the current environment's database."
namespace :db  do
  namespace :fixtures do
      task :import => :environment do
	
        require 'active_record/fixtures'
        require 'rake'
        ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
        ## set directory to import
        file_base_path = File.join(RAILS_ROOT, 'doc') ## or File.join(RAILS_ROOT, 'test', 'fixtures')
        puts "importing from: " + file_base_path
	
        puts "the RAILS_ENV is " + RAILS_ENV
	
        if ENV["TABLE"] != nil
            files_array = ENV["TABLE"].to_s.split(",")
        else
            files_array = Dir.glob(File.join(file_base_path, '*.{yml}'))
        end
	
        files_array.each do |fixture_file|
            puts "\n Importing " + File.basename(fixture_file.strip, ".yml") + "..."
            begin
                  if fixture_file.downcase != 'schema_info'
                    Fixtures.create_fixtures(file_base_path, File.basename(fixture_file.strip, '.yml'))
                  else
                    raise   "Not willing to import schema_info!"
                  end
                puts    " Status: Completed"
            rescue
                puts    " Status: Aborted\n\n" + $!
            end
        end
        puts "\nTask completed!"
	
      end
    end
end
	
#Rake task to export data from tables in the current environment db to fixtures (YML format)..
#The files will be exported to "/doc" folder.
#Export specific tables using the environment variable "TABLE". Eg:
#=> rake db:fixtures:export TABLE=assessment_components,lookups (Note: There should not be spaces between commas)
#Specific environment using the environment variable "RAILS_ENV"
#=> rake db:fixtures:export TABLE=assessment_components,lookups RAILS_ENV=test
	
desc "Export data from tables in the current environment db to fixtures (YML format). "
namespace :db do
  namespace :fixtures do
      task :export => :environment do   
	
        ActiveRecord::Base.establish_connection(RAILS_ENV.to_sym)
        ## set directory to export
        file_base_path = File.join(RAILS_ROOT, 'doc') ## File.join(RAILS_ROOT, 'test', 'fixtures', 'export')
	
          puts "exporting to: " + file_base_path
        puts "the RAILS_ENV is " + RAILS_ENV
	
        if ENV["TABLE"] != nil
            table_names = ENV["TABLE"].to_s.split(",")
        else
            table_names = ActiveRecord::Base.connection.tables
        end
	
        table_names.each do |table_name|
        if table_name.downcase != 'schema_info'
                puts  "\n Exporting "  + table_name + "... "
                yml_file = "#{file_base_path}/#{table_name}.yml"
                i = "000000"
                File.delete(yml_file) if File.exist?(yml_file)
                File.open(yml_file, 'w' ) do |file_object|
                    begin
                        sql = "SELECT * FROM #{table_name}"
                        data = ActiveRecord::Base.connection.select_all(sql)
                        file_object.write data.inject({}) { |hash, record|
                        hash["#{table_name}_#{i.succ!}"] = record
                        hash
                        }.to_yaml
                    puts    " Status: Completed"
                    rescue
                        puts " Status: Aborted - Table #{table_name} does not exist"
                    end
                end
            end
        end
        puts "\nTask completed!"
	
    end
  end
end
Administrator posted at 1:28 pm in: ruby , rails

June 26, 2007
Using Containers for non-model Forms

With my new project (to be named soon), I needed a search form on the screen with different options:

address (text field)
and search radius (pulldown)

The typical way to handle this is with rails helpers in a form partial:

<% form_tag(:url => {:action => :results }) do %>
	<p><label for="address">Address:</label><br />
	<%= text_field_tag :address, 'some value or variable' %></p>
	
	<p><label for="address">Radius:</label><br />
        <%= select_tag :radius, '<option value="0.5">0.5m</option><option value="1">1m</option>' %></p>
	
	<%= submit_tag 'search' %>
<% end %>

Then in the (things_) controller, you would have something like so:

class SomeController < ApplicationController
 def search
      @radius = params[:radius] || '0.5'  ## default radius to '0.5' if not returned
      @address = params[:address] || '123 main st, 10001'  ## default address if not returned
  end
	
  def results
      ## default these values because there could be an error with the data
      @radius = params[:radius] || '0.5'  ## default radius to '0.5' if not returned
      @address = params[:address] || '123 main st, 10001'  ## default address if not returned
	
      ## manually check form data for problems, re-render search if problems
	
      ## if okay, do the search and render results view
      @things = Thing.find(:all, :conditions=>['address = ? and radius < ?', @address, @radius])
	
  end
end

There are some big problems with this:

  1. You have to seed the values for the field if there is an error on the form. If you dont, you will get blank values if you render an action (like search). So the view above would be altered like so:
    <%= text_field_tag :address, @address %>
  2. You now have to set the variables in the results method in the controller:
    @address = params[:address] || '123 main st, 10001' 

    This really clutters up your controller method, especially if you have lots of form items

  3. What if you ever want to store the searches in the database at some point in the future? Say you want to show ‘most popular searches’, etc. Again, more clutter in the controller. You would need to save these values into a model which will definitely not be pretty.

The best way I have found to solve this is to make a container for this form as if it was a real model and deal with it just as you would a regular form in rails. It really cleans things up.

The first step is to create the container class. It will look (and act in a way) just like a model, so the best place to put it is in your models folder, it will also automatically be usable in all controllers:
app/model/search_container.rb

class SearchContainer
   # a generic class to hold all search form data
   attr_accessor :address
   attr_accessor :radius
	
   def initialize(params={})
      @address = params[:address] || '123 main st, 10001'  ## default address
      @radius = params[:radius] || '0.5'
   end
	
  def self.radius_values
     return [['0.5m','0.5'],['1m','1']]
   end
end


Notes:

  • Notice the absence of ‘< ActiveRecord::Base’ in the class definition. This means you dont need a database table to store this information, but as far as the controller is concerned, it works just like a real model.
  • attr_accessor :some_variable lets you store a value in the class (like an active record object)
  • The initialize method can be used to set defaults
  • This is a handy place to store select (pulldown values) - self.radius_values
  • This is a re-useable class with defaults. You can easily use this on more than one form and it will always have the correct defaults (Dont Repeat Yourself).

The re-factored form partial using the container:

<% form_tag(:url => {:action => :results }) do %>
	<p><label for="address">Address:</label><br />
	<%= text_field :search, :address %></p>
	
	<p><label for="address">Radius:</label><br />
        <%= select :search, :radius, SearchContainer.radius_values %></p>
	
	<%= submit_tag 'search' %>
<% end %>

And the refactored controller method:

class SomeController < ApplicationController
   def results
      @search = SearchContainer.new
   end
	
   def results
      @search = SearchContainer.new(params[:search])
	
      @things = Thing.find(:all, :conditions=>['address = ? and radius < ?', @search.address, @search.radius])
   end
end

Looks much cleaner, and has the added benefits of:

  1. The select options for the radius are only ever in one place in the code.
  2. Default values are only ever in one place.
  3. You can save the searches easily by adding ‘< ActiveRecord::Base’ to the class definition of the search_container.rb model, then adding ‘@search.save’ results method in the controller once you have created a table to store them. You also might want to rename the class from ‘SearchContainer’ to ‘SearchOptions’ at this point since they are real database values.

I know this is obvious to some, but for me, this is the only way to do this sort of thing from now on.

Administrator posted at 12:19 pm in: ruby , rails

June 3, 2007
Baja Trip May 2007

by Suzannah Hill

lower baja map

Day 1:

Cabo San Lucas


Resort in Cabo
cheesy cabo resort

Immediately as we went through customs, we were bombarded by over zealous, sleazy tour and timeshare operators trying to sell tour packages or offer “discounted” rates on car and hotel. The catch: spend 2 hours listening to a timeshare presentation. Non, gracias! We were tired of the airport so rented a car and drove into town. Our rental was an economy car with four doors, four wheels, air conditioning and nothing else. Not even a radio. Economia for sure! I would advise (even for non-planners like us) to reserve a car from the States. It is signifcantly less expensive. We didn’t have a set agenda or reservations so we started searching for a hotel. We were looking for a low-key hotel with beach views, but apparently, this is not what Cabo offers. On the contrary, the majority of places are large mega resorts. We tried a few places and they were booked solid. Having only eaten a sandwich on the plane, we stopped at a small restaurant and kicked back with a pina colada, Modelo and beef and fish tacos. The owner brought out some really tasty chips and five small dishes containing

various salsas (cilantro, tomato and chipotle based to name a few). Yum.

We finally ended up at the Finisterra resort/hotel on the beach. It was nice and super-cheesy.

It was good to get off the plane, get to the beach and lie in a hammock with a boat drink, other than that this place seemed like a run-of-the-mill expensive resort with a swim-up bar and more staff than guests.

su hammock cabo mike drink hammock cabo

The really crappy part of this resort is you cannot swim in the ocean because of a strong rip-tide and the fear of drowning most sane people have. Our room was really big and luxurious, but lacked even a basic kitchen.
Cost: $230


wave cabo

mike run wave

The town is overrun with tourists and is like Times Square magnified by 100. On the outskirts of town is a Costco and its Mexican equivalent, City Club. The main strip is lined with restaurants, bars, and souvenir shops-all overpriced. As you walk on some of the side streets, it gets a bit less touristy. We ended up grabbing empanadas and fried shrimp at a little joint frequented by the locals. There was a karaoke area in the back, decked out with strobe lights and all. The night progressed, the lights dimmed and we were serenaded by the off-key sounds of a Mexicana belting out songs.

Day 2:

Todos Santos

We decided to drive up the west coast of baja and explore Todos Santos, a small artist enclave north of Cabo. We also learned that the town is home of Hotel California, made famous by the Eagles. The drive is like nothing we’ve seen before. Miles and miles of clay colored desert with cacti and various indigenous plant life sprouting from the ground. Along the route are road side stands with vendors hawking mexican souvenirs, mini-supermarkets selling convenience items, and small family run restaurants. There is also the occasional 10 foot high Modelo beer can that emerges like a beacon in the desert to signal that there is a rest stop/bar serving beer to weary travellers, just in case one needs a cold beverage…

huge modelo

We arrived in town and decided to find a place to sleep before the day progressed. Mike saw a tiny sign that said beach lodging. We turned off on a dirt road and off we went.

road to posada

After about 10 minutes, we came upon Posada La Poza.

lagoon posada jaccuzzi posada pool palms todo santos


mike terrace posada

It is a beautiful property situated in a lagoon with views of the pacific ocean. The proprietors are Swiss, the wife is an artist. The only vacancy was a suite with jacuzzi. While it sounded tempting, we were unsure if we wanted to spend so much denaro, especially after our Cabo resort extravaganza. Weary from driving, we mulled it over lunch on the roof top terrace.

I suppose that is how they suck you in. Sitting on the terrace overlooking the ocean, birds chirping in the background, well-manicured grounds with lush plants and vegetation, private swimming pool lined with palapas and chaise lounges. Not to mention the daunting journey on the dusty, dirt road back to town. Sold! I negotiated the room price to a mere $200. Shhh!! You didn’t hear it from me. The place was so inviting that we didn’t venture into town. We sat around drinking more boat drinks, swam in the salt water pool, took a dip in the salt water jacuzzi, napped and continued our fantasy land vacation.

mike hammock posada

There is a restaurant on the premise and we enjoyed a candlelit meal of shrimp risotto, sea scallops and beef filet. Then back to the jacuzzi before catching some zzzzz’s from our long, hard day.

In the morning after breakfast, we explored the beach. According to the proprietor, it was a short 5 minute walk around the lagoon. Perhaps her concept of time is different from our’s, but the trek was a bit longer and a little more arduous. She also failed to mention that you needed secure soled shoes instead of flip flops. Once at the beach, it was beautiful. It stretched for miles, the waves were crashing and all you could hear were the water and birds.

walk to beach su beach todos santos

While the water looks inviting, it is advised not to swim in it. Mike tested it out and the warnings were correct! We walked farther down the beach to the area that separated the lagoon and ocean. There was a dead baby dolphin that had its eyes picked out by vultures. And so came the end of our stay at La Poza. We toured Todos Santos and moved on to La Paz.

Day 3 and 4:

La Paz

The drive to La Paz cuts through the center of Baja. The terrain is arid. We drove for about an hour and a half or so and came to the city. La Paz is on the east side of Baja on the Sea of Cortez. After working our way through the slow, hot traffic we arrived at the Malecon, a walkway adjacent to the sea that runs for miles . We stopped to stretch our legs and lo and behold, a fish taco stand. Since one of my main goals was to eat fish tacos and drink margaritas and pina coladas the entire trip, I had to sample one. Plus it was only 10 pesos=$1. I ordered a taco de pescado and loaded it with all the fixins’ which were kept on a cart next to the stand (lime, salsa, jalapenos). Muy delicioso, un mas, por favor! We didn’t have a map of the city so after the fish taco adventure, drove out past the town. Right off the road side are public beaches. The farther you go, the nicer they get. Many of the beaches are littered with palapas, basically an umbrella with a thatched roof that offers shade from the scorching sun. The water is crystal clear and warm. You can walk out quite a distance before it gets progressively deeper. Our game plan for today was to find a hotel then come back to the beach, chill out, drink more boat drinks and swim until evening.

clear water la paz su boardwalk la paz su drink la paz sunset la paz

We wanted super low-key and for fun checked out the Hostel California. The doors to the room were painted cheery blue colors and the rooms were on a courtyard. However, upon closer look, it was scary. There weren’t door locks, only padlocks that served as locks. The actual rooms were the size of prison cells and had a bed, light and no windows. I’m outta there. We ended up getting a good recommendation from a local girl for Hotel Lorimar, a clean and tidy hotel with about 20 or so rooms. Being horribly scared of bugs, I asked the attendant to show us some rooms before we decided. There are two different room categories, old and new. The basic difference between the two are that the old rooms are a little bit more run down and lack screens for the windows. The are furnished modestly a la college dorm room. We opted for the new rooms. The price is right at 360 pesos per night (approximately $38 USD). The hotel, albeit small and on the budget end, offers some nice perks like laundry service. There is also a small courtyard area which some of the rooms face. With our night’s lodging secured, we headed to la playa, El Tesoro, to initiate the second part of our plan for the day. We settled under a palapa and stayed until the sunset. We were joined by families who carried picnic dinners with them and played dominoes into the night. On our drive back to town, the Malecon was packed with people strolling, rollerblading and running. What a scenic place to convene. It was rather late by the time we were ready for dinner. Our hotel is located in the market district and most of the vendors had closed up shop. We passed a taco stand on the corner of a street and decided to eat there. Throw caution to the wind and hope we don’t get food poisoning. No taco de pescado, but some tasty taco de carne, beef tacos for a whopping 5 pesos ($.50) with guacamole, salsa, chipotle, lettuce and tomato toppings. Unlike guacamole in the States, the Baja version is less chunky and more liquidy =mucho yuuuumy. We sat down on some chairs that lined a wall and enjoyed. While eating, we made the acquaintance of two backpackers, a Swedish guy and a Japanese guy, shared some stories and suggestions. Coincidentally, they were camping on the same beach with the dead dolphin in Todos Santos the night before. They were off to Mazatlan via the Baja ferry that connects to Mexico’s mainland. We said good night and headed off to search for a billiard bar for Mike. We were walking in a sketchy part of town, ahmm…burglar bars on the windows, and changed our minds about staying out super late. The town seems safe, but after a few drinks and speaking LIMITED spanish, searching for the hotel didn’t sound like the best idea. We finished our night at a local bar talking with a Mexicano who offered to take us by boat to the nearby islands of Espiritu Santo and Isla Partida for $100 USD each. Thinking that was on the expensive side, we went to bed. Overall, in contrast to Cabo, La Paz is much more welcoming, less commercialized with very friendly, helpful people. Although of all things, there is an Applebees restaurant on the main road…


tamales de mary front
tamales de mary
la paz city

One of the primary things we wanted to do in La Paz was snorkel, especially since there is such rich and diverse marine life off nearby Isla Espiritu Santo and Isla Partida. The same girl who suggested the hotel also said that instead of taking a tour through an agency, there were locals who hung out on the Malecon who would ferry us around for a minimal cost. We met Hector, who suggested we go on a tour with his friend, Captain Mike of Punta Baja in Playa Pichilingue. I don’t know if “captain” is the correct term since the boat we were in was only about 90 horsepower, had four rows of seats and a mini sun canopy. Included were a visit to Isla Partida to see the arch and sea lions, lunch on a private beach and snorkeling off of Isla Espiritu Santo at the low price of 490 pesos ($49 USD each). Sounded good. It turned out that it was one of the best $49 we’ve ever spent. We got our very own private tour. We started our journey from Pichilingue. As we navigated the clear calm waters out to Isla Partida, to the farthest tip of the island, we saw scores of fish. We arrived at l’arco (the arch), a huge stone structure that jutted out from the sea to form the shape of an arch. Along the rocks were sea lions basking in the sun. To our surprise, we were going to snorkel with the sea lions and swim under and around the arch. Mike got all his gear on and jumped right in. I suited up, climbed down the ladder and then clung onto it for about 15 minutes. I’ve snorkeled before, but it always takes me a bit to get used to being in the vast ocean. I don’t swim either so was petrified about being in almost 60 feet of water with only a little orange life vest around me. The two Mikes finally convinced me to go and threw me the round life preserver to use in addition to my life vest. It is an awesome experience to swim with the sea lions. At first it can be intimidating, but they swim around you and do not bother you. They get at arms distance, check you out, then swim away. They are so graceful in the water. In addition, the types of fish are absolutely amazing, small and large, brightly colored white, red, blue, yellow, stripes, crabs climbing on the rocks, and even lobsters. There were clusters of fish especially around and under the arch. We stayed here for an hour then boated to Espiritu Santo for lunch on the beach. It was in a protected area surrounded by rocky mountains on both sides so the water was extremely calm. Cpt. Mike had prepared some homemade ceviche which we gobbled up with fried tortillas. We then spent about an hour exploring the rocks and snorkelling. By the end of the trip I mustered up courage and ditched the round livesaver. It was like swimming in a big aquarium. On our way back to shore we passed over a shipwreck. We shared a beer with Cpt. Mike, who was an excellent guide and captain, on shore and ended our fabulous day. Unfortunately we have no evidence that we ever went on this trip since we left my camera at the hotel. We contemplated going on the tour again in a day or two if we were still in La Paz, possibly customizing it even more, the next time bringing our camera. We topped off our evening at a small local open air restaurant eating more delicious fish and beef tacos. There were large flying palmetto bugs climbing the walls. Lucky for me-I didn’t have my glasses on so couldn’t see well, they weren’t in our vicinity, and the restaurant was frequented by several other patrons. Otherwise, I would’ve been in trouble.

The following morning we walked around La Paz. We had a delicious breakfast at a tamale stand, Tamales de Mary. It was a one person operation, she served various types of tamales and frijoles (beans on the side). I had a rajas de rez con queso (filled with cheese and jalapenos) and elote (sweet, cornmeal tasting).

There are 7 beaches that dot the coast of La Paz. We had already seen most of them, but checked out the remaining two, La Playa Ballandra and Tecelote, afterwards. On our first night in La Paz, Mike had met a Canadian expat and mango/orange exporter, Dan Gallagher. While we were looking for a hotel, he had mistaken Dan’s office/apartment front for the reception desk of a hotel. Dan gave us great recommendations for visiting the rest of Baja.

We secured a map and plotted out our drive. We would head to the Sierra de La Laguna mountains and go out to the Eastern Cape, which is part of the biosphere and is supposedly very beautiful. On the recommendation of Gabriel, the attendant at Hotel Lorimar, we stopped at the Cactus Sanctuary a little ways outside of La Paz. We drove on a long road that seemed to go on forever. At first we thought it was a self-guided tour and just as we were about to turn around, we saw the entrance to the actual sanctuary. It was nice although beastly hot in the sun. There were a lot of cacti, big and small. The trail was marked by a white stone path that you were supposed to follow. The downside is that sometimes it split off into a couple of directions and everything looked a lot a like so you weren’t sure if you had already been to that area. We were wishing we had a breadcrumb trail to lead us out. It reminded me of the corn mazes in Pennsylvania. The park guide was a character, too. Very friendly and helpful, but a character. He kept talking to us about all different flora and fauna. Just as we would walk away he’d start up a new conversation. We signed the guestbook and noticed the last entry was over a week ago. The sanctuary is very isolated so perhaps we were his first human contact since then. Mike joked that prisoners could either go to jail, do manual road labor in the blazing 100+ heat or become the park guide at the cactus sanctuary. Hmmm…that would explain why we saw so many manual workers fixing the Baja infrastructure!

We continued on and worked our way through some quaint towns: El Triunfo, a former mining town, San Bartolo, which had a piano museum, and Santiago, a town situated among mango groves. We stopped by a road side stand and ate homemade tamales for lunch. These little stops are interesting. They are really “hanging a shingle right in front of your house” operations. Dan had called ahead to a friend of his in Santiago, who owned Hotel Palomar, but alas there was no room in the inn. His friend didn’t get the message and his place was booked for a month in advance. His hotel was on a mango grove. Despite not being able to spend the night, we enjoyed a pina colada and modelo and walked around the grounds. There were mango, avocado and orange trees everywhere. Santiago is a small, pretty town with a common square and it even has a zoo! We will go back one day!



santiago

With Hotel Palomar being the sole hotel in town, we decided to head to our next destination, Cabo Pulmo, about two hours away. We didn’t stop for dinner, but fortunately had a leftover tamale from lunch that we ate as a snack. We came to Los Barriles, a big surfing town, about an hour from Cabo Pulmo. Mike spotted ATV rentals($20 USD/hour) and before I knew it, we were driving ATVs through a sandy, dried out riverbed that extended for miles. At the very end, we came to the beginning of a small waterfall. The cliffs surrounded us on both sides and we drove through small streams of water that ran off from the main source. The waterfall was a short distance away, but we didn’t have the proper hiking gear on so didn’t go. Plus, the ATV riding was an unexpected diversion and we really needed to get to Cabo Pulmo.

It was getting quite dark and the road to Cabo Pulmo had turned from a smooth paved road to a dusty, rocky dirt road. We had been driving on it for awhile until we finally arrived at the town. It was TINY. We went to the first and only lodging we saw, Nancy’s “casitas”. Nancy, fondly named “raisin lady” by Mike, is a somewhat cranky, wrinkled white haired lady who had about 2000 too many sunburns. She wore a yellow cover up over a black bikini exposing her raisin-y shriveled skin. She showed us the casita and we took it. We dumped our stuff and searched out a fresh seafood dinner at an open air restaurant on the beach. I had wonderfully fresh garlic fish. Upon returning to the casita, this is when the nightmare began. By day, the casita is a quaint, little thatched roof apartment, by night it is a hot (fanless), mosquito and roach infested hell. It was a long, uncomfortable, steamy, sleepless night underneath the covers.

Day 5, 6 and 7:

Cabo Pulmo


pulmo foliage

Having not slept much, we were pretty much awake when the sun started coming up. Homemade breakfast at raisin lady’s restaurant. What the casita lacked, the breakfast of strong mexican coffee and huevos rancheros made up for! Cabo Pulmo is absolutely beautiful. It is unspoiled, national park on a coral reef. The town itself consists of a dive shop, a handful of little restaurants and as we discovered one other lodging besides Nancy’s, the Cabo Pulmo Resort which serves as both a dive shop, restaurant and rents bungalows, that is about it. Palm trees and tropical foliage are everywhere.

The town is solar powered. Some people have generators. But it isn’t on the grid. We stayed the next two nights in a self-contained bungalow. Night and day from the casita. Extremely nice, friendly people and great accommodations for about $70 USD. Low on cash, we drove an hour into Los Barriles to use the nearest ATM. When we got there, the power on just one side of the street was out. No one knew when it would be back up. We decided to go grocery shopping and stock up so in case we couldn’t get cash, we could cook our own meals for the next two days. One last try at the ATM-up and running. Wheeew. Back to Cabo Pulmo. The drive by day along the dirt road is exquisite, albeit bumpy. Amazingly our hunk of junk car maneuvered pretty well. Thanks too, to Mike’s many years of video game playing. We had one minor mishap when trying to avoid an oncoming car and went careening (hyperbole) into a sand bank. As the driver of the other vehicle passed us, he remarked that our car “must be a rental”! Otherwise, just rolling hills with glimpses to the azure sea; steer, cows, goats lounging by the side of the road; and the occasional jack rabbit scurrying across the street.

pulmo road pulmo car road pulmo road ocean drooling steer

We spent the rest of the day alone at one of the beaches except for the two feral dogs that kept scrounging for food. One even came up, sat down next to me and put his head in my lap. That was sweet, but he was a walking fleabag. We snorkeled off the shore and swam out near the rocks. Due to the coral reef, the fish were even more plentiful and diverse than at La Paz. Grey fish with yellow and white stripes, schools of blue, purple, red fish, puffers, white sea snake with black dots, large yellow chubby fish and a long, thin fish all whose names we don’t know. We walked to a rocky area on the beach and found a hermit crab, aka Hermie.

pulmo palapa pulmo beach rocks hermie the crab mike snorkel

I adopted him for a day and took him back to the bungalow. The afternoon went quickly. That evening we grilled and had dinner on the roof top terrace. Another spectacular event in itself, like being in a bird sanctuary. We watched bright yellow and red tropical birds playing games, buzzards reposing on the tops of the palm trees. Ended the evening watching the moon rise from the beach.


pulmo fish truck
pulmo fisherman

The next morning we had fresh pineapple and yogurt on the terrace. We walked to a little cafe and took a cup of coffee before heading to the 2nd beach. According to one of the dive shop guides, it is possible to snorkel around the mountain and rocks (about an hour) to a sea lion colony and snorkel back. We weren’t confident in our snorkeling and swimming skills so we decided to snorkel off shore instead from the 2nd location. The tide was rougher than the other beach so Mike swam out to the rocks and tested out the waters. There he saw a huge yellow pancake-like fish, a “puffer” fish, and many others. The wind was tossing him too close to the rocks, so he swam back to report about the huge variety in this area. The beach was right beside a small fishing village which was basically a few trailers and square cement structures on the sand. A funny sight was a woman lying on a bed on the sand watching tv and listening to the radio covered only by a sun canopy. I was craving fresh fish to grill and inquired with one of the fishermen sitting outside his house. He directed me to a blue truck. Another fisherman opened up the back door and inside were many different kinds of fish flopping around on the ice. I chose two red, snapper looking fish. They cost 20 pesos ($2.00 USD). Why not go straight to the source?

We had lunch, napped then went back to the first beach to snorkel some more. The water was definitely calmer. We made our way out quite far. The coral reef is deceptive. At certain points the water is deep, but then will get shallow. It looks like you could almost touch the coral. On this run, we were in a coral minefield trying to make our way back to shore. We kept swimming, some areas the coral was about a foot from us, but kept getting in the shallow areas. Finally, we found our way out and headed to shore. We explored another rocky area and found interesting marine life in a small pool of water left over from when the tide had last come in. There were tons of snails who clung to the sides of the rocks, a mini black crab waiting to eat the snails, and a tiny “chameleon like” fish who blended perfectly with the rocks. Mike went ahead of me and found a 20 foot cave that narrowed as you went farther in. Again, no pictures because we forgot to bring the camera on our rock trek. That evening, I grilled my filets marinated with a little lime juice, pepper and cilantro and enjoyed one of the freshest meals. Our last night we made our way to the beach to watch the moon. We found a spot on a dune and lay back. Because there isn’t a lot of city light, it was like being in a planetarium. There was a full moon and a multitude of stars against the dark sky, including the big dipper. It was so peaceful we almost fell asleep in the sand.


bungalow terrace dusk

We said goodbye to Cabo Pulmo and headed towards the airport. We went back through Santiago because I wanted to take some pictures. We had a small detour at the zoo. My camera was acting funny the entire trip and the battery died before I was able to photograph the town. As we were nearing the airport, we were getting hungry and stopped by a roadside family-run restaurant. It was the perfect meal to end the trip. Enchilladas con pollo y queso (chicken enchilladas with cheese) and filete con ajo (garlic fish filet). Both meals arrived with a side of rice, flour tortillas, frijoles and salad. Oh so yummy. As we were sitting, we saw a truck jam packed with bric-a-brac in the truck bed and hanging off both sides that the driver was selling. If only we had a working camera. Only in Mexico.

Baja is very alluring. We can’t wait to go back…umm…next week?

Additional trip photos at michaelhill.info.

su mike kiss

Administrator posted at 10:41 pm in: personal

May 24, 2007
Performance Testing a Rails Stack

Last night, a bunch of us had a group install - fest of a full rails stack (might have to view google cache) on our web servers.

Foz was around, and so was tomatocheese, sofajockey, and rathan. Thanks for everyone’s help in getting this up an running.

The basic idea was to take lighthouse.org, a rails ’static’ site using the radiant cms, from serving up pages using a single mongrel web server, to a full rails stack using apache and a mongrel clusters and the do some basic bang-the-drums (ApacheBench) benchmarking.

Our initial setup (SERVERA):
Debian 40r0
Ruby 1.8.5
Rails 1.1.6
Radiant 0.6.0
one Mongrel instance running ‘deamonized’ on startup (/etc/init.d) port 80

New setup:
ServerB:
Debian 40r0
Apache 2.2 + mod_proxy_balancer (5 balance members)
ServerC:
Inital Server(serverA) + mongrel_cluster (5 mongrel clusters)

Results / Metrics using ApacheBench:

Note: I ran ab several times for each and copied the average time that I was getting for each test case

  • raw connections per sec on the single mongrel server (SERVERA):

    #ab -n 100 http://SERVERA/
    	
    HTML transferred:       995800 bytes
    Requests per second:    11.16 [#/sec] (mean)
    Time per request:       89.59 [ms] (mean)
    Time per request:       89.59 [ms] (mean, across all concurrent requests)
    Transfer rate:          113.23 [Kbytes/sec] received
    	
    Connnection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0     1    1.4      0    10
    Processing:    42    88  117.0     51   895
    Waiting:       42    88  116.9     51   894
    Total:         42    89  117.1     52   895
    	
    Percentage of the requests served within a certain time (ms)
      50%     52
      66%     56
      75%     59
      80%     64
      90%    253
      95%    270
      98%    576
      99%    895
     100%    895 (last request)
    
  • raw connections per sec on the apache server (SERVERB):
     #ab -n 100 http://SERVERB/
    	
    Total transferred:      1017000 bytes
    HTML transferred:       995800 bytes
    Requests per second:    8.07 [#/sec] (mean)
    Time per request:       123.84 [ms] (mean)
    Time per request:       123.84 [ms] (mean, across all concurrent requests)
    Transfer rate:          82.12 [Kbytes/sec] received
    	
    Connnection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0     1    2.3      0    20
    Processing:    47   122  135.1     57   838
    Waiting:       46   122  135.2     56   837
    Total:         47   123  135.1     59   838
    	
    Percentage of the requests served within a certain time (ms)
      50%     59
      66%     73
      75%    115
      80%    263
      90%    289
      95%    405
      98%    566
      99%    838
     100%    838 (last request)
    
  • raw connections + 10 concurrent connections on the single mongrel server (SERVERA): here is where things start to get interesting!
    #ab -n 100 -c 10 http://SERVERA/
    	
    Total transferred:      1014400 bytes
    HTML transferred:       995800 bytes
    Requests per second:    8.08 [#/sec] (mean)
    Time per request:       1237.20 [ms] (mean)
    Time per request:       123.72 [ms] (mean, across all concurrent requests)
    Transfer rate:          81.99 [Kbytes/sec] received
    	
    Connnection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0     2    1.5      2    11
    Processing:    97  1209  652.0   1282  2703
    Waiting:       93  1209  651.9   1282  2702
    Total:         97  1211  652.0   1284  2707
    	
    Percentage of the requests served within a certain time (ms)
      50%   1284
      66%   1457
      75%   1807
      80%   1850
      90%   1874
      95%   2555
      98%   2693
      99%   2707
     100%   2707 (last request)
    
  • raw connections + 10 concurrent connections on the apache server (SERVERB): go baby, go!
    #ab -n 100 -c 10 http://SERVERB/
    	
    HTML transferred:       998510 bytes
    Requests per second:    18.44 [#/sec] (mean)
    Time per request:       542.30 [ms] (mean)
    Time per request:       54.23 [ms] (mean, across all concurrent requests)
    Transfer rate:          188.07 [Kbytes/sec] received
    	
    Connnection Times (ms)
                  min  mean[+/-sd] median   max
    Connect:        0     2    2.5      1    15
    Processing:    57   500  348.0    461  1572
    Waiting:       56   500  348.0    461  1571
    Total:         57   502  348.6    467  1581
    	
    Percentage of the requests served within a certain time (ms)
      50%    467
      66%    559
      75%    745
      80%    784
      90%   1089
      95%   1242
      98%   1276
      99%   1581
     100%   1581 (last request)
    

What’s Next: Seperate the clusters onto seperate machines and see how that affects the performance. Maybe rails stack benchmarking Part II post ?

Administrator posted at 12:50 pm in: tech , ruby , rails

May 23, 2007
The Current State Of Testing Ruby on Rails Applications

While attending railsconf 2007, every time I would meet someone new, I would ask them the same question.

“So, how are you testing your application? Which plugins/gems are you using to help you?”

The results were unexpected; Everyone I talked to had a different way of making tests for their rails app. Of course you might say, “but no two applications are the same, of course they need to be tested differently.”

Here are some of the different approaches I came across:

  • Test::Unit (rails default)
  • Zentest and autotest. Definitely check this out no matter what your setup is!
  • Mocha (stubba)
  • Rspec
  • Rails built in fixtures
  • Fixture Scenarios (cool, but buyer beware!)
  • Putting fixture data in the test (just creating the objects when you need them)
  • Making test helpers with the fixture objects in them

…and different combinations of the above. The one thing that is certain is nobody, I mean nobody, likes the way rails default fixtures works. Check out foz’s post on this: FozWorks: Validating Fixtures

What I quickly learned was the is no standard way of writing tests. Everyone has their own way that fits their particular needs. Some people need the tests to execute as fast as possible. Some people don’t care about how fast they execute, etc. It seems as there are currently favored (standard) way to go about testing, like mongrel as -the- web server.

Testing is still a voodoo art — good luck and post comments. I look forward to hearing from you.

Administrator posted at 10:01 am in: ruby , rails

December 12, 2006
We tied the knot!

Su and I got married on Nov 2, 2006! Thanks to everyone who came to the reception and for the fantastic gifts.
Check out the photoset:

mike and su getting ready for the recption

click the image above
or here

Administrator posted at 12:10 pm in: personal

June 23, 2006
Photoset - Ireland

We just got back from a trip in Ireland and the UK. The weather was great and the company was better.


image of beach in Donegal Ireland

click the image above
or here

Administrator posted at 1:36 pm in: personal