Changing life

Last post was made about 6 months ago. No blog post here means plenty happening in my everyday life.

I joined a Canadian startup company called Envisio and relocated my family from Melbourne Australia to Vancouver Canada.

It is a big move for my family, however I have good faith in the Envisio product, I truly believe it’ll take off in north America. More importantly, I really enjoy working with the guys at Envisio!

So yeah! I’m in a different country again after a good 14 years of my Melbourne life. I’m ready to continue exploring.

Published: 2013-09-13

Calculate next reporting date

It’s been a while since my last post. I’ve been hacking along though. Here’s an interesting puzzle I faced recently.

In the app, I have an model called Corporation. Each corporation has a reporting frequency, a start date and the timezone it’s in. The task is to calculate the next (and the last) reporting date for each corporation. It seems pretty straight forward, but the devil is in the details …

The trimmed down version of my implementation is below

class Corporation < ActiveRecord::Base

  REPORTING_FREQUENCY = %w(monthly bi-monthly quarterly half-yearly yearly)
  REPORTING_FREQUENCY_INCREMENTS = { 'monthly'     => 1.month,
                                     'bi-monthly'  => 2.months,
                                     'quarterly'   => 3.months,
                                     'half-yearly' => 6.months,
                                     'yearly'      => 12.months }

  def next_reporting_date
    now = Time.now.in_time_zone(time_zone).to_date

    return start_date if start_date > now

    reporting_date(now, start_date.day, start_date)
  end

  private

  def reporting_date(now, original_start_day, start)
    if original_start_day > start.day && start.end_of_month.day >= original_start_day
      start = start + (original_start_day - start.day).days
    end

    return start if start >= now

    reporting_date(now, original_start_day, start + reporting_frequency_increment_value)
  end

  def reporting_frequency_increment_value
    REPORTING_FREQUENCY_INCREMENTS.fetch(reporting_frequency)
  end

end

The only tricky bit is the first if block inside the recursive reporting_date call. It makes sure we’re not losing days when we cycle through months that have less days than the start_date.day value.

Hope I’m making sense here … and I’m sure there are existing algorithms out there doing what I want more elegantly.

Published: 2013-03-28

Change machine

Start of the year, some fun stuff.

I recently had some spare time and re-visited my first ever uni assignment. The problem it’s trying to solve is easy, given any amount of money in cents, figure out the minimium number of coins required. No need to say, the little Java program I wrote was crazily bad. So I rewrote it again in Ruby.

And here’s my solution after over 10 years of programming practice :)

module ChangeMachine

  class IdiotEncountered < StandardError; end

  AVAILABLE_UNITS = [10000, 5000, 2000, 1000, 500, 200, 100, 50, 20, 10, 5]

  def self.show_me_the_money(dollar_in_cents)
    raise IdiotEncountered, "You are an idiot, no such amount in AUS..." unless dollar_in_cents % 5 == 0
    dispense(dollar_in_cents)
  end

  def self.dispense(dollar_in_cents)
    return {} if dollar_in_cents == 0

    unit = AVAILABLE_UNITS.select{|u| u <= dollar_in_cents}.max
    {unit => (dollar_in_cents / unit)}.merge(dispense(dollar_in_cents % unit))
  end
end

puts ChangeMachine.show_me_the_money(37500).inspect
# => {10000=>3, 5000=>1, 2000=>1, 500=>1}

My Java version can be found here under the comments section.

Published: 2013-01-04

PostgreSQL memory size

I’m making a fresh OSX installation. After installing PostgreSQL using homebrew, the service cannot startup intermittently. The PostgreSQL server log says

FATAL:  could not create shared memory segment: Cannot allocate memory
DETAIL:  Failed system call was shmget(key=5432001, size=3809280, 03600).
HINT:  This error usually means that PostgreSQL's request for a shared memory segment exceeded available memory or swap space, or exceeded your kernel's SHMALL parameter.  You can either reduce the request size or reconfigure the kernel with larger SHMALL.  To reduce the request size (currently 3809280 bytes), reduce PostgreSQL's shared memory usage, perhaps by reducing shared_buffers or max_connections.
The PostgreSQL documentation contains more information about shared memory configuration.

Straight forward stuff, modify or create /etc/sysctl.conf and toss in the following

kern.sysv.shmmax=16777216
kern.sysv.shmmin=1
kern.sysv.shmmni=32
kern.sysv.shmseg=8
kern.sysv.shmall=65536

Apparently I have done this before from my previous OSX installations… Next time will be easier with this note jotted down here.

Published: 2012-11-10

What makes a good framework

The other night, I watched Yehuda’s talk, Ember.js, State of the Union. One thing Yehuda said strikes me. He briefly talked about framework’s internal modularity and how a framework should be presented to developers.

There’s no doubt a good framework needs to be modular, so that changes can be easily made and new features can be added in relatively easily. I see 2 types of modular framework out there.

  1. Modular frameworks that are branded to be opinionated, a.k.a, Rails. Despite its modular internals, from the outside, you use the framework as instructed, no more, no less. Out of the box, it solves a typical type of problem. However once you become confident and efficient with it, you have the power to ride the Rails with your own way, thanks to its modularity.
  2. Frameworks that are modular, and the framework provides the modules as building blocks. Things are then left to the devs to work out, a.k.a. Zend Framework. It’s super flexible, but it’s hard to figure out how to handle the beast. You need to do all the glue work yourself. Put the pieces together yourself. The steep learning curve often leads to mis-use, and yes that’s talking from self-experience.

So what makes a good framework? Back to what Yehuda said, it’s gotta be modular, with an easy and default way to interact with the framework. The framework needs to set sensible defaults out of the box.

Rails does this really well. Maybe one day I’ll outgrow Rails, but for now, I can’t be happier.

To back me up, just compare how Zend Framework and Rails handle building web forms (yes, that’s what we do on the web all the time…)

What one is better? You are the judge!

Published: 2012-09-07

Chrome's broken back button

Chrome is my primary browser because it’s fast and minimal. One thing surprised me today is its (in)ability to deal with content caches.

The issue I encountered is this.

  • I have a resource myapp.com/my_resource.
  • I first load the page in with a request of content type text/html. The page itself has some Javascript, which will issue an Ajax request to the same URL myapp.com/my_resource. The Ajax request is requesting the same resource URL, but with a different content type, application/json.
  • On the my_resource page, I click on another URL
  • Once I’m on the new page, I hit the back button(I’m lying here, I press the delete key). Chrome dumps out all the JSON data returned by the Ajax request instead of rendering the previous “text/html” page content.

The reason is when Chrome caches content, it discards HTTP headers. This means as long as the resource URL is the same, the Ajax request’s response automatically becomes the cache value for my myapp.com/my_resource URL. To me, this really breaks RESTful web apps’ state management.

Problem is tricky, fix is easy. Just toss in a random number as a postfix to the Ajax request URL (well, it’s not really a solution. The Ajax request will not get cached by the browser anymore…)

$.getJSON "/my_resource?#{new Date().getTime()}", (data) ->
  # blah blah

EDIT

Since I’m working on a Rails app, instead of hacking a timestamp to the Ajax URL, I can just make the URL .json

$.getJSON "/my_resource.json", (data) ->
  # blah blah
Published: 2012-09-03

ActiveRecord model responsibilities

While I’m drafting this post, I got pointed to this article, Fear Of The Class: Fat Model Kills Your Software Design, from a tweet. This article says 90% of the things I wanted to say here, so I’ll not repeat those.

One extra thing I want to point out is some madness I faced in recent weeks. And of course, it relates to the AR model responsibilities topic.

In Rails land, I accept the fact we can call to_json on a AR model instance and pump the output back as a JSON response. I occasionally use it when I’m just prototyping something, but I seriously believe calling to_json on AR model is wrong. to_json simply isn’t a responsibility to an AR model class. Handle it in the views with RABL, use a decorator/presenter, freedom is all yours!

As I dislike Rails giving all AR model to_json method, I’m hit by something much worse. In a central ORM lib at work, a recent change was made to automatically serialise boolean fields to JSON format upon data retrieval. So if someone needs just a true or false … too bad, ORM gives back JSON true and JSON false, convert it back to boolean yourself!!! When I read and noticed the change, it was a WTF moment. When I questioned the change and told to go and read on it, I wave white flag …

Published: 2012-08-24

RSpec integration tests with custom headers

While writing an integration test, I needed to pass a custom HTTP header to the GET request. Doing a quick scan in the Rails source (I’m using Rails 3.1.3) points me to here.

It looks like all I need is to include my custom HTTP header in a hash and pass it to the get call as the last argument.

Fairly straight forward, I came up with this

get "/api/xxxxx/xxxxx/xxxxx",
    { format: "json" },
    { authorization: "Token token=\"#{app.token}\"" }

As you can see, I trusted the doc, I used authorization as the header hash key. I was hoping it’ll be turned into HTTP_AUTHORIZATION. And you can guess, it didn’t, my request spec was failing badly, returning me HTTP 401 instead, not passing the initial authentication. It turned out that the Rails doc is lying to me. I had to fire the get call like this instead

get "/api/xxxxx/xxxxx/xxxxx",
    { format: "json" },
    { "HTTP_AUTHORIZATION" => "Token token=\"#{app.token}\"" }
Published: 2012-07-23

CKEditor and Rails

One reason I really enjoy working with Ruby/Rails is because of the Gems. When you want to integrate a Rails app with some 3rd party utilities, it’s pretty likely that you can find existing Gems doing just that for you (80-20 rule here of course).

I need to integrate CKEditor with my Rails app. Guess what? There’s a ckeditor gem for it! Just follow the VERY good readme to get it installed. For a Rails 3.2 app, you literally just need to add 2 lines or 3 lines of code to have it all set up …

Add it to your Gemfile, and bundle install it

gem 'ckeditor', '3.7.1'

If you want to handle uploads from the editor, stick the following into your ruotes.rb. I didn’t do this myself, because I’m only after text editing.

mount Ckeditor::Engine => "/ckeditor"

Next, in your app’s javascript manifest file, add the following line

//= require ckeditor/init

At this point, it’s done and working (this is the 80% rule)! However for what I needed (the 20%), I did some customisation.

I’m using the awesome simple_form, so I created a little helper method in my application_helper.rb

def rich_text_editor(form, attr)
  form.input(attr, as: :ckeditor, input_html: { class: 'string', customConfig: asset_path('ckeditor_config.js') }).html_safe
end

As you can see, I load a custom ckeditor_config.js. It basically gives me a custom tool bar. Oh! Don’t forget to add ckeditor_config.js to config.assets.precompile list in application.rb.

CKEDITOR.editorConfig = function( config )
{
  config.toolbar = 'MyToolbar';

  config.toolbar_MyToolbar =
      [
        ['Bold', 'Italic','Underline', '-', 'NumberedList', 'BulletedList'],
        ['UIColor','TextColor','BGColor'],
        ['Link', 'Unlink','Anchor'],
        ['Maximize', 'ShowBlocks','-','Source'],
        ['Paste','PasteText','PasteFromWord','-','SpellChecker']
      ];
};

Now, in any of my view files, I use the helper method like this

= simple_form_for @object do |f|
  = rich_text_editor f, :description

All good! Yes, all good on development… Deploy it to staging, it fails miserably. Why? Asset Pipeline again! For Heroku hosted apps (staging and production), I’m using an S3 asset_host for static assets. The CKEditor init script tries to load it from the app’s domain instead…

After reading the ckeditor init script, it’s very easy to fix! Rename the javascript manifest file to application.js.erb, so that we can use Ruby code. Make the manifest require self and add some voodoo to set the CKEDITOR_BASEPATH.

//= require_self
// ...
// your other requires, make sure require_self comes before requiring ckeditor/init
//= require ckeditor/init

(function() {
  <% if Rails.env.production? %>
    window['CKEDITOR_BASEPATH'] = "http://<%= ENV['FOG_DIRECTORY'] %>.s3.amazonaws.com" + "/assets/ckeditor/";
  <% end %>
}).call(this);

That’s it! Why I use ENV['FOG_DIRECTORY'] in the basepath? See my previous posts(1 and 2) for details.

Sweet, all good.

Published: 2012-07-15

Heroku Deploy Bash Script

Quick and short one. The Heroku hosted app I’m working on has a staging env. I need to quickly deploy from local to the staging Heroku remote repo a lot. Doing git push staging whateverbranch:master is fine, but just tedious to type every time. And since the app is at early development stage, I need to constantly deploy to staging from a local feature branch to just do the show-n-tell, a simple bash/zsh alias will not do the job (well, I don’t know, maybe it can …).

So… since I’m using RVM and a project .rvmrc anyway, I throw the following function into my project .rvmrc. With that, I can just do deploy staging, job done!

deploy() {
  local ref=$(git symbolic-ref HEAD 2> /dev/null) || return
  local current_branch=${ref#refs/heads/}

  echo "Deploying to Heroku: "
  echo "   - git push $1 $current_branch:master"
  git push $1 $current_branch:master

  echo "Running database migration: "
  echo "   - heroku run rake db:migrate"
  heroku run rake db:migrate
}

It’s quick and dirty, and once the app gets released I’m sure I’ll come back to modify it or move the deployment into a Rake task. Working just fine for now!

Published: 2012-07-14