Be Genius

Fork Me
Mugshot

Hi, I'm Bodaniel Jeanes.

I'm a Ruby developer from Brisbane, Australia

I am a freelancer who hacks on awesome code. Follow me, recommend me, and link with me.

Iterative HTML5 - Turning a comma-separated list into a semantic list

In the process of going through the redesign of
http://mocra.com, I keep finding better ways to make the HTML more semantic.

Jack Chen and I have been turning the design into HTML over the last few days and we’ve been striving to be as semantic as possible by taking advantage of new HTML5 elements and by separating the content further from the design code with all the new CSS3 selectors.

Here’s an example of something we just did to make the HTML cleaner and more meaningful, whilst still maintaining the look and style.

Here’s what we are styling:

Usually your HTML (or HAML in this case) would look something like this:

%footer
  %aside
    = link_to 'Dr Nic Williams', 'http://drnicwilliams.com/'
    ,
    = link_to 'Bodaniel Jeanes', 'http://bjeanes.com/'
    ,
    = link_to 'Jack Chen', 'http://chendo.net/'
    ,                      
    = link_to 'Ryan Bigg', 'http://frozenplague.net/'

However, we can make this list of people more semantic by using an <ul> element and some CSS magic.

Here’s what the new HTML (HAML here) would look like:

%footer
  %aside
    %ul
      %li= link_to 'Dr Nic Williams', 'http://drnicwilliams.com/'
      %li= link_to 'Bodaniel Jeanes', 'http://bjeanes.com/'
      %li= link_to 'Jack Chen',       'http://chendo.net/'
      %li= link_to 'Ryan Bigg',       'http://frozenplague.net/'

And the CSS (Sass here):

body
  footer
    aside
      padding-top: 6px
      float: left

      ul
        list-style: none
        margin: 0
        padding: 0
      
        li
          display: inline
          
          &:after
            content: ","
            
          &:last-child:after
            content: ""

Using Fish shell's event system to behave like method_missing

Dr Nic’s latest post, “hash bang cucumber”, reminded me of a piece of hax I whipped up a few weeks ago with Ruby and Fish Shell.

Fish has an event system that allows you to register functions to be auto-run after or during certain events (such as when a particular environment variable is changed). One of this events is called fish_command_not_found. It is triggered whenever you type a non-existant command into the prompt.

With this in mind, you can trigger certain commands to run by matching what fish couldn’t manage to run automatically by catching this event.

For instance:

function __fish_method_missing --on-event fish_command_not_found
  method_missing $argv
end

funcsave method_missing

Given that function is created (simply paste the whole code block into your Fish terminal), I can now create a command called method_missing (or whatever you call inside your __fish_method_missing) and place it somewhere in your $PATH — I like ~/.config/fish/bin.

My method_missing binary is simply something like this:

#!/usr/bin/env ruby

command = ARGV.shift

def run(cmd)
  puts "Running #{cmd.inspect} instead"
  system(cmd)
end

case command
when /^git(@|:\/\/).*\.git$/
  run("git clone #{command.inspect}")
when /^(?:ftp|https?):\/\/.+\.t(?:ar\.)?gz$/
  run("curl #{command.inspect} | tar xzv")
else
  $stderr.puts "No default action defined in #{__FILE__.inspect}"
  abort
end

Each command you want to register just becomes a new when statement. For instance, to implement the functionality Dr Nic was trying to achieve, I simply modify the case block as such:

case command
when /^[a-z0-9_\-\/]+\.feature(:\d+)?$/
  run("cucumber #{command}")
# ...
end

The existing entries I have in my method_missing command will auto-clone the repository of a pasted Git URL and download and expand a URL for a tar file, respectively. Not too shabby, and dead easy to implement

Gotcha with Hash.new when providing a default value

For a project I am working on at the moment, I needed a Hash that returned a different default value, i.e. not nil. Specifically, I needed it to return another Hash, and for that internal Hash’s default value to be an Array, like so:

hash = # ...
p hash.class                              #=> Hash
p hash[:non_existant_key].class           #=> Hash
p hash[:another][:non_existant_key].class #=> Array

Naïvely, I threw this into my code, and went along my merry way: entries = Hash.new(Hash.new([])). A few days later, I came back to this code to finish it and realised that something was awry with the values I was getting out of the Hash. It took me a while to figure it out because the values were all integers being summed together and I was never looking or setting the values directly.

However, eventually I saw a pattern — many of the values were the same. For instance, given the following assignments, I should expect p entries[153][:monday] #=> [12.hours]:

entries[153][:monday]  << 12.hours
entries[153][:tuesday] << 3.hours
entries[87][:monday]   << 7.hours
entries[87][:tuesday]  << 2.5.hours

However, what I found was the following:

p entries[153][:monday]  #=> [12.hours, 3.hours, 7.hours, 2.5.hours]
p entries[153][:tuesday] #=> [12.hours, 3.hours, 7.hours, 2.5.hours]
p entries[87][:monday]   #=> [12.hours, 3.hours, 7.hours, 2.5.hours]
p entries[87][:tuesday]  #=> [12.hours, 3.hours, 7.hours, 2.5.hours]

# And in fact:
p entries[:any][:thing] #=> [12.hours, 3.hours, 7.hours, 2.5.hours]

Let that soak in for a second. Hash.new({}) uses the same instance of the internal Array as the default value for each of the inner-most keys. It also doesn’t set the key you want so p entries still printed {}. In retrospect, it is blatantly obvious that it does this, but the ramifications are still huge.

The way to get the intended effect is of course to use the block syntax of Hash.new which, while much uglier, definitely works as expected:

entries = Hash.new {|hash, key| hash[key] = Hash.new {|h, k| h[k] = [] }}
entries[153][:monday]  << 12.hours
entries[153][:tuesday] << 3.hours
entries[87][:monday]   << 7.hours
entries[87][:tuesday]  << 2.5.hours

p entries #=> {87=>{:monday=>[7.hours], :tuesday=>[2.5.hours]}, 153=>{:monday=>[12.hours], :tuesday=>[3.hours]}}

Wow. Obvious, but good to remember. I am sure most of you have had this issue before, but I think it is still worthy of mention…

Using Apache as a BasicAuth proxy to an internal resource

This article isn’t named ideally so if you have a better title, tell me.

This is the scenario: we have a simple HTTP resource on the internal network at Mocra. This resource is a closed source tool which is great except that it has one drawback — there are only two security modes: basic authentication on, or basic authentication off. There is only one username/password and you can’t control when or by whom it is required.

Now, my preferred behaviour here is to be able to give out multiple login/passwords and also to only require authentication outside of our local network. I set out to get this working.

I devised this solution a few months ago (which is why it’s using Apache at all) but I thought it might be of some use to someone. I created an Apache VirtualHost to act as a proxy between this resource and its clients. It looks like this:

<VirtualHost *:80>
  # This virtual host proxies requests for the internal resource
  ServerName external.resource.com

  # Set auth header to base64 encoded 'username:password' 
  # where username and password are the credentials for internal resource
  RequestHeader set Authorization "Basic dXNlcm5hbWU6cGFzc3dvcmQ="

  ProxyPass /resource_path/ http://192.168.1.123:1337/resource_path/
  ProxyPassReverse /resource_path/ http://192.168.1.123:1337/resource_path/

  <Location />
    Order allow,deny
    Allow from 192.168.1.0/24 # our local subnet
    Allow from 127.0.0.1 # duh
    Allow from 1.3.3.7 # our external router IP

    AuthType basic
    AuthName "Our Internal Resource"
    # where all the external login/passwords are
    AuthUserFile /var/www/.htpasswd 
    Require valid-user

    # this is the secret sauce that allows EITHER
    # local access or Basic Auth access
    Satisfy Any 
  </Location>

  RewriteEngine on
  RewriteRule ^/?$ http://external.resource.com:80/resource_path/ [R]
</VirtualHost>

Using fields_for can generate invalid HTML

Just a quick post so show you how fields_for form helper can cause invalid HTML when used in combination with accepts_nested_attributes_for in your views.

If you are for any reason editing/creating your child objects in a tabular form, your view might look something like this:

<% form_for(@todo_list) do |f| %>
  <%= f.label      :name %>
  <%= f.text_field :name %>

  <h3>To Do Items:</h3>
  <table>
    <thead>
      <tr>
        <th>To Do Item</th>
        <th>Due Date</th>
        <th>Done?</th>
      </tr>
    </thead>
    <tbody>
      <% f.fields_for :items do |item| %>
        <tr>
          <td><%= item.text_field :content %></td>
          <td><%= item.text_field :due_date %></td>
          <td><%= item.check_box  :done %></td>
        </tr>
      <% end %>
    </tbody>
  </table>
  
  <%= f.submit 'Save' %>
<% end %>

At first glance this looks fine. However, when the ToDoList model has accepts_nested_attributes_for :items, the fields_for helper also outputs a hidden field for each existing Item instance with it’s ID.

This means that we get the following HTML:

<form action="/to_do_lists/1" class="edit_to_do_list" id="edit_to_do_list_1" method="post">
  <div style="margin:0;padding:0;display:inline">
    <input name="_method" type="hidden" value="put" />
    <input name="authenticity_token" type="hidden" value="CE2jyRoewbwsqu4eX8AFWFqsgrMfCN35Jzy6b43MhsA=" />
  </div>
  <label for="to_do_list_name">Name</label>
  <input id="to_do_list_name" name="to_do_list[name]" size="30" type="text" value="Sup" />

  <h3>To Do Items:</h3>
  <table>
    <thead>
      <tr>
        <th>To Do Item</th>
        <th>Due Date</th>
        <th>Done?</th>
      </tr>
    </thead>
    <tbody>
      <input id="to_do_list_items_attributes_0_id" name="to_do_list[items_attributes][0][id]" type="hidden" value="1" />
        <tr>
          <td><input id="to_do_list_items_attributes_0_content" name="to_do_list[items_attributes][0][content]" size="30" type="text" value="arst" /></td>
          <td><input id="to_do_list_items_attributes_0_due_date" name="to_do_list[items_attributes][0][due_date]" size="30" type="text" value="2009-07-30" /></td>
          <td><input name="to_do_list[items_attributes][0][done]" type="hidden" value="0" /><input id="to_do_list_items_attributes_0_done" name="to_do_list[items_attributes][0][done]" type="checkbox" value="1" /></td>
        </tr>
      <input id="to_do_list_items_attributes_1_id" name="to_do_list[items_attributes][1][id]" type="hidden" value="2" />
        <tr>
          <td><input id="to_do_list_items_attributes_1_content" name="to_do_list[items_attributes][1][content]" size="30" type="text" value="arst" /></td>
          <td><input id="to_do_list_items_attributes_1_due_date" name="to_do_list[items_attributes][1][due_date]" size="30" type="text" value="2009-07-30" /></td>
          <td><input name="to_do_list[items_attributes][1][done]" type="hidden" value="0" /><input id="to_do_list_items_attributes_1_done" name="to_do_list[items_attributes][1][done]" type="checkbox" value="1" /></td>
        </tr>
    </tbody>
  </table>
  
  <input id="to_do_list_submit" name="commit" type="submit" value="Save" />
</form>

The keen eye will notice the hidden <input> tags that are direct children of the tbody:

    <tbody>
      <input id="to_do_list_items_attributes_0_id" name="to_do_list[items_attributes][0][id]" type="hidden" value="1" />
        <tr><!-- clip! --></tr>
      <input id="to_do_list_items_attributes_1_id" name="to_do_list[items_attributes][1][id]" type="hidden" value="2" />
        <tr><!-- clip! --></tr>
    </tbody>

This is not a valid place for an <input> tag.

I’ve put an example project demonstrating this on my GitHub

Creating new Postgres User and DB

This post is mostly a reminder for me in the future. However, others may find it useful also.

I love Postgres but more often than not I get frustrated and confused trying to get authentication working with a new database. By looking through the Deprec source code, I pulled out these two lines of code and so far they haven’t failed me:

su - postgres -c "createuser -P -D -A -E $DBUSER"
su - postgres -c "createdb -O $DBUSER $DBNAME"

Of course, replace $DBUSER and $DBNAME with your desired username and database name, or define them as shell variables. The $DBUSER creates that user as the owner of the database (so it has permission to read/write etc).