Rails Model Annotation
January 30th, 2009
One of the things I like about datamapper over activerecord is that all the attributes of the model are listed in the model itself. I found something today that can help to bridge that gap in a small way.
Have a look at annotate-models you can install it as a gem
gem install annotate-models
annotate, you will then have something like this at the top of each model.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 |
# == Schema Information # Schema version: 20090130210328 # # Table name: profiles # # id :integer(4) not null, primary key # user_id :integer(4) # first_name :string(255) # last_name :string(255) # website :string(255) # blog :string(255) # flickr :string(255) # about_me :text # location :string(255) # is_active :boolean(1) # last_activity_at :datetime # created_at :datetime # updated_at :datetime # |
Merb Sample App
October 22nd, 2008
DataMapper CRUD
One of the confusing things about Restful resources is that the when changing a resource the operation must be a Post HTTP operation not a Get HTTP. This insures that HTTP Get operations are immutable. OK well how do you do a delete then? If you create a new merb application, merb-gen app omelet, cd omelet, merb-gen resource egg The controller already has the destroy action, it's just a matter of calling that with a POST command. There is a Merb form helper called delete_button that can help1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 |
%h1 Users %table %thead %tr %th Title %th{:colspan => 2} %tbody %tr - for user in @users %tr %td = user.login %td = link_to 'Show', url(:user, user) %td = link_to 'Edit', url(:edit_user, user) %td = delete_button(user) = link_to 'New', url(:new_user) |
Merb and Phusion Passenger
October 14th, 2008
I posted some of this information before, but it was more geared towards the Ruby Enterprise Edition and not about Phusion Passenger
I installed Ruby Enterprise in the /opt/ruby-enterprise-1.8.6-20080810/ directory which I linked to /opt/ruby-enterprise. The installation was easy and painless, the only thing you have to remember is that you'll have a new sparsely populated GEM directory, so you might want to go ahead and /opt/ruby-enterprise/bin/gem install <insert your favorite gems here>
I was using Apache and Mongrel to serve my Rails instances, but to really benefit from Enterprise Edition, I needed to switch to Phusion Passenger (aka mod_rails). This too was very easy, the only trouble I had was I had to tell the installer where my Apache 2 header files were export APXS2=/opt/apache2/bin/apxs did the trick.
Then you need to add the passenger_module from your Apache httpd.conf file with:
LoadModule passenger_module /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.0.3/ext/apache2/mod_passenger.so
PassengerRoot /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.0.3
PassengerRuby /opt/ruby-enterprise/bin/ruby
Almost done, I just had to take the bits about routing to the mongrel cluster out and I was running my Rails instances with mod_rails
For my Merb app I had to add a config.ru file in the root directory with the following information
1 2 3 4 5 6 7 8 9 10 |
Gem.path.unshift("/opt/ruby-enterprise/lib/ruby/gems/1.8") require 'rubygems' Gem.clear_paths require 'merb-core' Merb::Config.setup(:merb_root => ".", :environment => ENV['RACK_ENV']) Merb.environment = Merb::Config[:environment] Merb.root = Merb::Config[:merb_root] Merb::BootLoader.run |
Notice the bit about adding the correct GEM path for Ruby Enterprise Edition then clearing it out after loading rubygems, I'm not exactly sure why that is required, but it took me a while to figure it out
So that's it now I have multiple Rails apps and one Merb app running on a Slicehost VPS using mod_rails. To be honest though I have not seen a big reduction in memory but the configuration is much easier.
Github from behind a firewall
October 10th, 2008
Using github.com from behind a firewall
If you are like me you are slowly using github more and more, as some of the top upcoming frameworks like Merb and Rails are being hosted there.
If you are behind a firewall at work, you might not be able to clone a repository because the port used for the git protocol is 9418, so issuing a "git clone" command will timeout. You can change the protocol to http, so instead of git clone git://github.com/path/to/repo you would do git clone http://github.com/path/to/rep, sounds easy enough but it's slower when it works and many times it will not work. I have gotten output like this:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 |
walk 2707ebbbc5837619dcc51af43db18ac31380c4a5 walk 743917a6de6464dd2fa5e064f1881adba218cae6 walk 2a348104ddb2c1b2090a8ca80d21258846afd250 walk 8a9cbc1af1343bfd32ea4b473341dff364b67353 walk 1bc43720343856280ad6801562f75b3239ca4ce2 walk e9ea1557e703f2f238192d72bd2714b0af425b7c walk fbc886b9adecad2e6e9c9a13f67349cd21c01ffa walk c4dc40df63fc5cebd2f3b2cceb7c8ea20ac86776 walk 64db048595a07b70057b98731d6e957406bca913 walk 012e0629863b3ce4b98c7eebb3f5ef4ed6d7b1e8 walk 109ec6b85d66f959a83048af9e173f612b1d4009 Getting alternates list for http://github.com/sam/extlib.git Getting pack list for http://github.com/sam/extlib.git error: Unable to find abb467803fa74dfdc3740f31b4fde5544e6a4100 under http://github.com/sam/extlib.git Cannot obtain needed tree abb467803fa74dfdc3740f31b4fde5544e6a4100 while processing commit 109ec6b85d66f959a83048af9e173f612b1d4009. fatal: Fetch failed. |
I assume this is fetching each commit and processing it, but has problems
SSH Tunnel Solution
The solution is pretty simple if you have ssh access outbound from work to a machine that is not fire walled. You would setup a ssh tunnel with the following command ssh -L 9418:github.com:9418 (username)@(machine.domain) Then your clone command would be changed to git clone git://localhost/path/to/repo
Updated sake merb recipe to clone via tunnel
Edit your ~/.sake recipe and change all github.com instances to localhost
Ruby Enterprise Edition
October 8th, 2008
As I’ve added more web sites to my Slicehost VPS the amount of memory required to run each Rails instance started being a real factor. I started looking for a solution for the memory footprint, the first thing I tried was upgrading to 1.8.7 and while it was faster than 1.8.6 it also broke some stuff like Mephisto and did not reduce the memory footprint.
Then I found out about Ruby Enterprise Edition they claim it reduces memory consumption by 30%. It's setup to be installed in a different directory than the standard Ruby to not interfere with other production apps, so I gave it a try. Mine was installed in the /opt/ruby-enterprise-1.8.6-20080810/ directory which I linked to /opt/ruby-enterprise. The installation was easy and painless, the only thing you have to remember is that you'll have a new sparsely populated GEM directory, so you might want to go ahead and /opt/ruby-enterprise/bin/gem install <insert your favorite gems here>
I was using Apache (I know should be using nginx, but then I couldnt use mod_rails) and Mongrel to serve my Rails instances, but to really benefit from Enterprise Edition, I needed to switch to Phusion Passenger (aka mod_rails). This too was very easy, the only trouble I had was I had to tell the installer where my Apache 2 header files were export APXS2=/opt/apache2/bin/apxs did the trick.
Then you need to add the passenger_module from your Apache httpd.conf file with:
LoadModule passenger_module /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.0.3/ext/apache2/mod_passenger.so
PassengerRoot /opt/ruby-enterprise/lib/ruby/gems/1.8/gems/passenger-2.0.3
PassengerRuby /opt/ruby-enterprise/bin/ruby
Almost done, I just had to take the bits about routing to the mongrel cluster out and I was running my Rails instances with mod_rails
For my Merb app I had to add a config.ru file in the root directory with the following information
1 2 3 4 5 6 7 8 9 10 |
Gem.path.unshift("/opt/ruby-enterprise/lib/ruby/gems/1.8") require 'rubygems' Gem.clear_paths require 'merb-core' Merb::Config.setup(:merb_root => ".", :environment => ENV['RACK_ENV']) Merb.environment = Merb::Config[:environment] Merb.root = Merb::Config[:merb_root] Merb::BootLoader.run |
Notice the bit about adding the correct GEM path for Ruby Enterprise Edition then clearing it out after loading rubygems, I'm not exactly sure why that is required, but it took me a while to figure it out
So that's it now I have multiple Rails apps and one Merb app running on a Slicehost VPS using mod_rails. To be honest though I have not seen a big reduction in memory but the configuration is much easier.
Ruby on Rails content_for
April 24th, 2008
One of the mantras in the Rails community is DRY (Don't repeat Yourself), this is nothing new if your a software developer you should always look for ways to refactor your code to avoid copy and paste. Trying to maintain code with logic that has been copied and pasted to different locations is a nightmare, and one that unfortunately most of us have been exposed too.
In Rails the view part of MVC is handled by ActionView and the default templates are ERb. The views are further broken down into layouts and views. Layouts are called first for each controller then the view corresponding to the action. For the most part the layout is going to contain header elements for the xml, but what if you need some special javascript in one of you actions but not others.
You could just add it to the layout and say tough you are going to have the client load it no matter what, besides taking up extra bandwidth this can cause javascript errors for things like Google Maps where there is no associated div.
Rails gives you a better way though, you can use content_for to specify content associated with a particular yield command. For example if you wanted to use YM4R (Yellow maps 4 Ruby) to helps with your Google Maps mashup project, you could do something like this:
You would add a yield item to your layout.1 2 3 4 5 6 |
<head>
<%= stylesheet_link_tag :all %>
<%= javascript_include_tag :defaults %>
<%= javascript_include_tag "popup" %>
<%= yield :head %>
</head> |
1 2 3 4 |
<% content_for :head do %> <%= GMap.header %> <%= @map.to_html %> <% end %> |
1 2 3 4 |
@map = GMap.new("map_div") @map.control_init(:large_map => true,:map_type => true) @map.center_zoom_init([75.5,-42.56],4) @map.overlay_init(GMarker.new([75.6,-42.467],:title => "Hello", :info_window => "Info! Info!")) |
That's it, your layout stays DRY and your single view gets the Google Map.
Col. Poole's Bar-B-Q
April 6th, 2008
Once again it has been a while since I've posted, so I'm trying out a product called Mars Edit to see if it helps make the posting easier.
I couldn't think of a good topic right off the bat, so I thought I would go with one of my favorites, which is Barbecue. Barbecue is one of those things that vary by region, so just to be clear since I'm in the south we're talking about pulled pork.
There are many great Barbecue places in Georgia, but one of the most well known is Col. Poole's in Ellijay. If you are traveling up Hwy. 515 Col. Poole's is hard to miss, with the Hill of Pigs.
It's called the Pig Hill of Fame for a reason and many local politicians and radio personalities have their own pig on the hill.
In order to compete with the Hill's attention the building is a nice match of faux logs, yellow and pink florescent paint and a red tin roof.
Moving inside there is a large assortment of memorabilia to remind you of your trip.
Not to worry though the menu is simple and direct, the pork plate is excellent
The interior decorating follows the exterior's pattern with pictures and news paper clippings about the restaurant
The service is quick and you will not soon forget the excellent slow cooked pork
Walk across the USA
October 21st, 2007
I know I have not posted in a while, but I have been slacking, I have been busy developing some new sites. One of the sites is called Walk across USA, it is a completely new type of web site that is a combination of social networking, team building and fitness tracking. Here’s how I describe it on the site: A corporate contest designed to encourage exercise and friendly competition by taking a virtual walk across America on the Discovery Trail. Start a contest, form teams, track your individual steps with a pedometer and compete with your coworkers to see who can finish the Discovery trail first.
Here’s the rules we came up with, these are up to the administrator of the contest and are configurable in the Rails Application.
Random teams of 4 are created- This has been a mixed bag, there are some very competitive people getting mixed in with some not so competitive people, but that is part of the contest to get people better aquatinted along with getting in better shape.
Each person on the team will track their mileage with pedometer while the Omron pedometer is not required, its the only one I believe is accurate.
Each step will count for 3 feet – another mixed bag, the game tends to favor shorter people since their gate is smaller they get more steps. A future enhancement may have everyone measure their stride and calculate actual mileage.
The course will follow The American Discovery Trail . The trail goes through: Delaware, Maryland, West Virginia, Ohio, Kentucky, Missouri, Kansas, Colorado, Utah, Nevada and ends in California. The trail is about 5000 miles long. Adding some pictures and commentary on the trail is on the roadmap.
It is tough to get to more than 10,000 steps in a single day, although 10,000 steps a day is what you need to lose weight. As an incentive, there is a 1000 step bonus for each multiple of 10,000 steps you walk each day, i.e. 10,000 steps =1000 step bonus, 20,000 steps = 2000 step bonus. I think this has been a big win, I find myself constantly trying to get in another 500-1000 steps before bed to get the bonus and many of the other contestants say the same.
Here is some screen shots from the site:
Each contestant enters their steps for each day

The site will chart your progress

The site calculates actual steps vs. contest steps

The site aggregates individual results into team results

Team progress is shown as teams slowly make their way across the USA

Google Ruby Mechanize
July 19th, 2007
I’m still slowly working on the jargonfly site and I said I would post the source code as I went along so this is my first installment. Once someone registers a domain and builds a site, you need to get the word out about your new site, one way to do this is to use search engine optimization technique (SEO). SEO is a way of optimizing your site to make sure Google and other search engines equate your site to search terms related to your site. For example when someone is searching for Hiking trails in Georgia, Alabama, Tennessee, North Carolina or South Carolina I want Secret Falls listed, since it’s target audience is hikers in those states.
Using these SEO instructions and the ones from Google I found I was doing some things wrong. One of the biggest mistakes I was making was that my title for each page was the same, this is a huge problem but one that is easily corrected. I changed the title on each page to either take the name of the state or the name of the trail. It takes a couple of weeks for the change to show up in the Google search results, but slowly I started moving up from page 10 to page 3-4.
I wanted a way of tracking this progress so I put together the following script. It takes an Array of search terms and uses Ruby , Mechanize and Hpricot to find what position your site places for each search query. I plan to make this a feature on the jargonfly site where you can set this up, then run it on a regular basis and graph the results using ziya which I’m using on another site. I have one for Yahoo search too, but I need to merge them together and end up with one script that works on all the big search engines.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 |
require 'rubygems' require 'mechanize' require 'hpricot' # Added delay so I wouldn't get blocked from Google, not sure this would really happen but successive queries could trigger a bot alert delay=3 query=["Hiking Georgia","Hiking Alabama","Hiking Tennessee", "Hiking North Carolina", "Hiking South Carolina"] site="www.secretfalls.com" query.each do |q| position=0 agent = WWW::Mechanize.new agent.user_agent_alias = 'Mac Safari' page = agent.get("http://www.google.com/") search_form = page.forms.with.name("f").first search_form.q = q search_results = agent.submit(search_form) # puts search_results.body.class doc = Hpricot(search_results.body) while position<200 do (doc/"/html/body/div#res/div/div.g/h2.r/a.l").each do |link| position += 1 url = link.attributes['href'].gsub(/'/,'') if url.include?(site) puts "#{position} #{url} #{q}" position=1000 end end next_page=(doc/"/html/body/div#res/div#navbar.n/table/td.b/a").last.attributes['href'].gsub(/'/,'') sleep rand*delay page=agent.get(next_page) doc = Hpricot(page.body) end end |
Plane trip
June 23rd, 2007
I recently took a trip to Sweden, there was a connection through Philadelphia, so I turned my GPS on for that segment. I did try on some of the other segments but I was in the middle of the plane but even my new Garmin 60CSx was not capable of keeping a lock.
There are a couple of sites out there to translate your GPX files into a google map route, one of those is Walking Boss. I ran across this site because the author had written a ruby gem for processing gpx files in Ruby and I was looking for something like that for my Hiking Trails website.

This is a map of the trip, you can't show airport to airport because they want you to turn you electronics off for landing and takeoffs.
$2500 dollar investment
April 25th, 2007
I’m starting a new web project today and I’ve decided to do this one a little different. I’m going to document each step of the project on this blog and make the source code available too, so it’s kind of an Open Source Web 2.0 site.
I’ll be using Ruby on Rails to develop the site, which is one of the faster growing Database backed Web Application environments. If you have not read the book Beyond Java I would encourage you to read it, Bruce Tate has done an excellent job of explaining some of the problems Java is facing and how Ruby on Rails solves those.
The idea for the site is to make it easier for entrepreneurs to come up with nifty Web 2.0 domains themselves. The number of .com domains registered has skyrocketed to over 50 million as of last year, according to Domain counts but at the same time a .com domain is still the gold standard for your presence on the web. Trying to come up with an unregistered site is getting very hard and that’s where this new site will help. I also need to give credit to this site Domain Generator which got me thinking along these lines, the problem with this site is that there seems to be a fixed list of names and most are not available, I plan of fixing both of these issues with my site.
There are a couple of ways to find a good domain name, the first one is to make a word up like google.com, ebay.com or skype.com, which is feasible for some creative types out there unfortunately I’m not one of those… Or you could use foreign words like yugma.com or nexo.com, but many of these are taken and to me they are harder to remember. So that leaves us with another way which is to use compound words, like hotmail.com, fogcreek.com or livewire.com . You are not going to find these in the standard dictionary like other compound words such as newsstand, flowerpot or ladybug but they are easy to remember and they can be used to describe a concept also. They also have a nice feature for engineers in that they can be created by an algorithmic process.
The site I picked for this website is JargonFly.com (see compound word sites make sense), which is a site I registered a while back. This is also how the title for this article came up, because a couple of weeks ago a company made me a cash offer for the JargonFly.com domain and they were willing to pay $2500 dollars for it. I obviously didn’t sell, but it did motivate me to go ahead and get the site developed so I can generate revenue from it (hopefully much more than the $2500 I turned down).
Now I’ve got the idea, the domain, a machine to host it on and the framework I’ll use, now I have to figure out how to monetize the site. The obvious things that come to mind is to become an affiliate for an ICANN registrar and collect money for registering sites. The other thing is to have other advertisers such as how to form your own corporation, raising venture capital, etc, plus there is always adwords from Google. I will research those a little later, for now I need to get the site built.
That’s it for now, hopefully by next time I will have the framework laid out for creating the domain names and a way of verifying they are still available.
Freelance Switch
April 20th, 2007
I ran across this great site Freelance Switch. Its about making the switch from the corporate world to being a freelancer. The site design is incredible and it looks like they plan on it being more than a blog.
They have some really good articles on different types of clients and also some QA type articles.
It looks like the illustrations used in the blog come from I Stock Photos. I could really use more style on this site, so I will be looking into them to see if they have graphics I can use.
Working for the Man
April 6th, 2007
I ran across this article Working for the Man this morning and it really hit home. I’m not sure exactly why it is, but the younger generation (18-28) is much different about work ethic and attitude than the previous generation (29-45). I can look around and see some of the reason, when I’m driving home from work and see kids in the back of peoples SUV with the built-in DVD player playing the Disney movie, I know where the sense that everything must be entertaining comes from. One thing I can’t figure out is where the sense of entitlement came from, when I was growing up (way back in the day…) it was still taught that if you worked hard you could accomplish whatever you want, now it seems to be if you complain and whine enough you will get that raise you want. To be honest I’m sure my parents generation thought my generation didn’t have to work hard and compared to them we didn’t, I didn’t have to feed the animals before school and then work at my Dad’s school after work but I didn’t think anyone owed me…
I saw one of the comments towards the bottom and posted the following response, hopefully young people will realize the opportunities they have and go after them.
Your attitude is what is holding you back. I work for a company that was a startup, then got acquired by a mid-size company and not is getting acquired by a big multi-national and the hardest part of my job is finding good developers. By good developers I’m talking about the ones being described in this article, the ones that have a passion for what they do and see writing software as the same thing as creating a fine piece of furniture.
I find it interesting that so many people disagree with the fact that you need to learn the internals of the machine; I think that is absolutely essential. Most people don’t even realize the order of magnitude difference, between memory and disk speeds/network speeds. You can be a good object oriented developer, have the perfect base classes, perfect inheritance pattern and have a terrible product because you don’t know how the overall system works. Most people do not have the patience it takes top learn this level of detail, the interrupt level in daily life makes this difficult. If you can’t do a google search and get back the exact information you are looking for in 55 milliseconds, then people move on to the next thing. There use to be a time (BG) before Google, where any manual or book you got was treasured and squirreled away for the knowledge it possessed, I worry that Google searches are replacing that deep level of understanding most good developers had to build up….
Anyways you can still live in that small town and make good money developing software, but you do have to go after what you want. Start by trying to bid for some outsourced projects from Companies that can’t get everything done. Build up you contacts, write emails, send sample code, maybe even do a project for free to show people you can do it. It is not going to fall into you lap, but if you can make some mid level managers job easier by writing a test harness or a utility program, you will have people beating down you virtual door with work.
RoboGeo
March 25th, 2007
After I wrote the article about the Sony GPS-CS1KA GPS, I did a little more research and I’m not convinced that is the best way to go. The main intent of Geocoding your photographs, is to insert the GPS info into the EXIF headers. There are several programs that allow you to do this, from just plain editing the latitude and longitude into each picture, to pulling the GPS data from the time stamps of a back track log.
One of the main problems with the Sony unit is that it does not seem to be sensitive enough in urban areas. I would look at this review from digitalurban before making a decision.
Robogeo seems to be one of the more popular ones and it seems very full featured. It can directly access a Garmin GPS unit and can used GPX files generated by other GPS’s.
Another option if you are a little more technical and don't want to spend the money on Robogeo, is to use gpicsync. It's written in Python and will run on Windows and Linux. You still have to produce a GPX file so it's not as tightly integrated as Robogeo is.
You will still need a receiver capable of recording GPX files. I'm leaning towards the Garmin GPSMap 60CSx it uses the SiRF GPS chipset which is very accurate from everything I've read. It is quite a bit more than the Sony, but it's a full featured GPS. I do have an older Magellan Meridian Gold GPS unit, but when I downloaded back track information I did not see any time and dates associated with it.
Permalinks in Rails
March 15th, 2007
I was looking into different search engine optimization techniques (SEO) and one of the things they said were that search engines filter some links based on http get arguments. If you have a link like http://www.secretfalls.com/trails/show?1, it might not index that page. Well in Rails that shouldn’t be an issue, because the way the controller works, you get the identifier as part of the http URL, so the above example would be http://www.secretfalls.com//trails/show/1 which is better, but it would still be nicer to have http://www.secretfalls.com//trails/show/Hickey_Gap_Trail.
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 |
class HikingController < ApplicationController before_filter :common def common @states = State.find_states end def index @trails = Trail.find_trails end def show @trail =Trail.find(params[ :id ]) end def show_by_state @trails =Trail.find_by_state(params[ :id ]) end end |
I was going to do a big write up here, but like so many things in rails I found that someone had already doe exactly what I wanted. Take a look at SEO for Ruby on Rails This plugin acts_as_friendly_param is super easy and gives you nice seo friendly URL’s


