Brandon Harris | Home

We are the Privileged 150k

The majority of the world dreams to make more than 100k a year. Yet, in the tech community, we refuse to train those dreamers. Instead we pine after "rockstars" and "ninjas".

I am happy to see the global tech community pay attention to our burgeoning tech community in Austin. The truth is, Austin has been part of the tech community as long as Silicon Valley has existed. I recently had lunch with a startup founder who eloquently pulled me through the trenches of his trek to his current successes. These include building one of the worlds first online credit card processing websites. Back then, they had to connect to FileMaker Pro as their database - oh the Humanity!

We have a great climate, a vibrant young population, kick ass night life, an awesome music festival, a party with a conference and great food. It really comes as no surprise that young ambitious entreprenuers would put Austin on the very short list of "cool" places to live.

For a while, the tech community has discussed a glut in talent required at new startups in Austin as well as Silicon Valley. Mostly, I am pointing to recent discussions on Hacker News.

It seems that the local newspaper has published a misleading article about the current situation as it applies to employers and their insatiable desire for top talent. According to the article, recruiters flew out to California and attempted to sway Silicon Valley development talent into a relocation to central texas. Oh, and money. A lot of money.

I am calling bullshit. There is no one in the development community telling stories of being offered 150k or anywhere near that number. This is a lame article meant to inspire the next generation of students to dive into the currently lucrative world of software engineering. Everyday it seems like we read about developers who cant write fizz-buzz in an interview and suddenly by magic surprise, the businesses are complaining about a lack of talent? I call it a lack of employee investment. If companies and startups spent their time finding sharp people and shaping them into what they are looking for, I submit that as a world society we would be in a better situation. However, it appears that middle to large startups on a "funded" and "limited" budget would rather spend money on a non-fortuitious business trip in an attempt to persuade a bunch of freeloading developers into moving to a place they have no interest in relocating to. I have an idea. How about training the people that you have right at home? Why not invest in the local community and increase your own technical capital instead of poaching?

We have a vibrant and healthy community. If you asked me, I could name a dozen top notch developers who are more than capable of making a businessmans dreams come true, and they are not demanding 150k a year. To put this into perspective, ONE of our local Ruby on Rails monthly meetups exceeds 70 people regularly. People are hungry to learn, and I bet everyone of those 70 could pass fizz-buzz - some with a little training.

In fact I find it far more common to run into a talented individual who is more in tune with performing social good than incurring self benefit. As a person who prescribes to capitalism, I find this rather interesting. Instead of demanding compensation, these people want a better way of life and they want to solve problems that would inevitably make the world a better place.

How's that food for thought? A skill that could land a 150k job, yet the fruits of their labor are given away for free and for the greater good. We [as developers] understand the privilege that we possess in a modern technical society. We understand that we can demand so much more. Most of us don't. We give our code away for free, we want to work from home, and we want to work in an environment that nurtures our good nature.

TL;DR; Who cares about the compensation amount when you are doing it wrong! Train your local pool and build your community. You invested in your company, now invest in the people and community around it!

Thank You for Visiting

Im assuming that as of the writing of this, you arrived here in search of Brandon Harris the wikipedia programmer.

If you happen to be interested in some of the topics that I occasionally post here, please feel free to subscribe or follow me on twitter.

Brandon did an AMA on Reddit

If you are looking to donate to wikipedia (please do!) this is the link that you are looking for

Thanks for visiting!

Rails Simple Page Caching

Memcache is great, and Redis is even better. But you are still bound to a database, and running services. We are so caught up in making everything dynamic, that I think we don't often realize that we are still serving up mostly static html. The good news is that Rails has static html caching built in, and I rarely notice anyone talking about it.

The scenario: You want to input your page content via an administrative interface, but this data rarely changes. Another way to look at it, the content only changes if you or someone who administers the site has a need to change it. Rails page caching is your friend.

Let's say you have this code:

 1 # application.rb
 2 config.action_controller.page_cache_directory = "#{::Rails.root}/public/cache"
 3 
 4 # routes.rb
 5 match '/:url' => 'pages#show'
 6 
 7 # Simple page class page.rb
 8 class Page < ActiveRecord::Base
 9 end
10 
11 #simple pages controller pages_controller.rb
12 class PagesController < ApplicationController
13   caches_page :show, :cache_path => lambda {|controller| controller.params}
14 
15   def show
16     @page = Page.where(:url => params[:url]).first
17     render :file => File.join(::Rails.root,"public","404.html") if @page.nil?
18   end
19 
20 end

Now, let's skip ahead real quick and write up a quick show template for this dynamic page.

1   -# show.html.haml
2   %h2= @page.title
3   = @page.body.html_safe

The good stuff occurs in the pages_controller.rb file. Line #13 states: "Cache pages for the show action, use the params for the file name". This is a little lazy on my part, since the params should only contain the :url, this will work. If there are more complex params, you will need to modify that singleton. Since we set the page_cache_directory to a cache folder in public, we can expect to see our generated files appearing in there.

The best part about this setup is that it works, and no plugins are needed. You will need to modify your webserver to look in the cache directory first, then proceed to the rails application.

What if you make changes? Wont you see the generated version instead of the updated version? In this case, yes. You will need to write a cache sweeper, a very trivial task. Here's a version of one that I found, but it may not be what you want. I am not making use of ActionController::Caching::Sweeping, because I have more global cache sweeping needs

 1 # config/application.rb
 2 config.active_record.observers = :cache_sweeper
 3 
 4 # app/models/cache_sweeper.rb
 5 class CacheSweeper < ActiveRecord::Observer
 6   # Add any other models that Page may depend on here
 7   observe Page
 8 
 9   def self.sweep_cache!
10     Dir.glob("#{ActionController::Base.page_cache_directory}/**/*.html") do |f|
11       File.delete(f)
12     end
13   end
14 
15   def after_save(*_)
16     self.class.sweep_cache!
17   end
18 
19   def after_destroy(*_)
20     self.class.sweep_cache!
21   end
22 
23 end

This good because it errors in favor of regenerating files when any change is made. This is bad if you are extremely worried about performance and don't like it when any of your users touches your database to regenerate a "dynamic" page.

If you are really concerned about page performance on mostly static sites, check out jekyll, this blog runs on it. Generate your pages once and never worry again. However, if you have requirements where people need to edit a page from your web app, rails caching is your free friend.

JSON Templates in Rails

Sometimes, you just don't want to do call the "to_json" message on an object. It could be that the object has a lot of attributes, the json needs are very simple, or you simply don't like the default structure.

Fortunately, there is a very easy solution: JSON templates. This is built in, and you might have not even known it.

In my case, I wanted to plot a bunch of people and their locations on a map. I had the following model:

1 class Person < ActiveRecord::Base
2   # ...
3 
4   def geo_location
5     [latitude,longitude].compact.join(",")
6   end
7 
8   # ...
9 end

I have the following controller:

1 class PeopleController < ApplicationController
2   respond_to :html, :json
3 
4   def index
5    @people = Person.find(:all)
6    respond_with(@people)
7   end
8   # ...
9 end

Now, create index.json.erb. I tried doing this with haml, but I really didn't like the way I had to handle the necessary whitespace. Your call if you want to use it.

1 [
2 <%- @people.each do |p| %>
3   {
4     "id": "<%=p.id %>",
5     "location": "<%= p.location %>"
6   },
7 <% end %>
8 {}]

There is a wart, the trailing {}. I didn't want to include any logic, as it would slow down this rather large dataset. The whole reason I am doing it this way is for speed. I have no need to display all the attribute data from the "people" table, I just need to plot a heat map. Suggestions are welcome, the side effect is that the last point that is attempted to be plotted, is ignored.

Matrox DualHead2Go, TripleHead2Go on Ubuntu, with ATI/AMD

I recently purchased a matrox dualhead2go digital edition off of ebay on a whim. I did this because I wanted to make use of some extra monitors sitting around the office. I have also come to the realization that I have grown up as a developer and I have enough confidence to look anyone straight in the eye and say – “Yes, I need 3 monitors”.

My current setup is a Dell XPS 1640 running Ubuntu 10.04, with a Radeon 3670 graphics card. Yeah, enter the wonderful world of linux graphics drivers.

My first attempt was to simply, plug it in and see what would happen, resulted in a mild success. I was able to have my laptop lcd set at a resolution of 1920×1080 and the two 1680×1050 monitors would only go up to 2560×1024. It looked warped, but it gave me a taste of what was possible.

After much configuring with xrandr —addmode, et. al ad nauseum, I came to the conclusion that the matrox just wouldn’t support a higher resolution than 2560×1024, even though the site claims that it will. Some searching prompted me to discover that you need to configure the device to support your desired resolutions using the matrox powerdesk tool. Windows and Mac users can rejoice, this exists for you both. Linux users, go get on that old Windows test box that you use for IE testing and configure this mutha.

Armed with the following resolutions 3360×1050, 3840×1080, I set to work on my dream display.

I hit another snag. I could crank the resolution on my laptop, or the two 22" monitors, but setting both to 11 caused really odd horizontal sync issues on my laptop. The text would be fuzzy and move from side to side. Clearly this wasn’t going to work using just Xrandr, and the Gnome Display tool.

This brings up another one of my errors. DO NOT USE THE GNOME DISPLAY TOOL after using the AMD/ATI Catalyst Control panel. The Gnome tool will nuke your xorg.conf file, and leave you scratching your head. Once you go FGLRX, forget that the Gnome display tool even exists, and trust yourself to learn the AMD/ATI Catalyst Control Panel as well as the aticonfig command line tool. If you are a complete badass and can handcraft your own xorg.conf file and modelines (why are you reading this?) skip ahead to the modeline cheats below.

I had clearly stepped into a limitation of the linux fglrx display driver, or so I thought. At one point, I had inadvertently nuked my xorg.conf file, so fglrx was no longer being loaded. (See cautionary statement above) I went through the relatively simple process of removing all traces of fglrx from my system. I reinstalled the proprietary drivers (because I also require dropshadows, and transparency, that’s how I roll) and set back to work.

Now the magic steps to make your mutliple display work:

1 Make sure you have the necessary modes available.
2 Add the modelines that you require to the display that you want them added to.
3 Set your resolution in the ATI/AMD Catalyst Control Panel

To see 1:

xrandr

Will display all the modes available for you devices.

I am going to cheat and give you the “magic” modelines needed by the Matrox DualHead2Go, TripleHead2Go:

DualHead:
2x 1680x1050:  ModeLine "3360x1050" 238.00 3360 3424 3488 3680 1050 1053 1061 1080 +HSync +VSync
2x 1600x1200:  ModeLine "3200x1200" 281.40 3200 3264 3456 3752 1200 1201 1206 1250 +HSync +VSync
2x 1920x1080:  ModeLine "3840x1080" 277.00 3840 3904 3968 4160 1080 1083 1092 1111 +HSync +VSync
2x 1920x1200:  ModeLine "3840x1200" 308.00 3840 3904 3968 4160 1200 1203 1213 1235 +HSync +VSync

TripleHead:
3x 1280x1024:  ModeLine "3840x1024" 254.31 3840 3856 3872 3976 1024 1025 1032 1066 +HSync +VSync
3x 1360x768:   ModeLine "4080x768"  200.38 4080 4104 4136 4200  768  771  779  795 +HSync +VSync
3x 1440x900:   ModeLine "4320x900"  320.10 4320 4400 4688 5712  900  903  915  934 +HSync +VSync
3x 1680x1050:  ModeLine "5040x1050" 326.66 5040 5104 5168 5376 1050 1053 1057 1066 +HSync +VSync

To add one of these to your display:

xrandr --newmode <Mode``Line>
xrandr --addmode DEVICE "AAAAxBBBB" 

Where DEVICE is the device name for your display, probably CRT1, DFP1, LVDS, etc. and the “AAAAxBBBB” is the name of the modeline that you copied from above. So in my case:

xrandr --newmode "3360x1050" 238.00 3360 3424 3488 3680 1050 1053 1061 1080 +HSync +VSync
xrandr --addmode CRT1 "3360x1050"

Then I popped open the AMD/ATI Catalyst Control Panel – Voila! that resolution showed up. I set all my monitors to their desired resolution and it worked.

To make you changes permanent add the xrandr commands to you .xprofile. I move around between monitors at home and at work, so I don’t make this too automatic. If you made it this far, you can probably google your way into a more automated setup. Will upload a pic tomorrow of the working setup.

Tags

  • e (1)