Install ImageMagick on Lion from source

I’ve had a lot of problems trying to install ImageMagick using brew. Use the following series of commands to install from source. Got this from Stackoverflow answer.

cd /tmp
curl -OL ftp://ftp.imagemagick.org/pub/ImageMagick/ImageMagick.tar.gz
tar -xzf ImageMagick.tar.gz
cd ImageMagick-[VERSION]/
./configure --prefix=/usr/local --disable-static --with-modules --without-perl --without-magick-plus-plus --with-quantum-depth=8 --disable-openmp --with-gs-font-dir=/usr/local/share/ghostscript/fonts
make
sudo make install

Post to Twitter

Simple Ruby on Rails app using Twilio API

Twilio created cloud telephony services made mainly for developers. I’ve been meaning to figure out how to use their service, and I had a chance to develop a Ruby on Rails app using Twilio app called Phonein. You can check out the source code here. It’s nothing fancy, and totally not optimized. I also used Twitter’s Bootstrap CSS/JS package.

While Twilio had a few samples for Ruby on Rails, it was kind of outdated and a few things were incorrect. I wanted to share what I did to use Twilio API to help you come up to speed quickly.

Basically my app is for home-care professionals, and it allows them to check in and out using client’s phone. For Twilio, the followings are its requirements.

  • Identify client by phone number
  • Identify home-care professional by 6-digit identification code
  • Check in the home-care professional at the client’s location
  • Read out tasks for the home-care professional
  • Check out the home-care professional from the client’s location

Twilio has its own markup language called TwiML, and in Twilio controller I created, TwiML is used to create views (or voices). I also created certain POST actions under Twilio controller that will receive input from phone (digits punched in by a person) and use it to look up information.

1. Answer incoming call

When you sign up with Twilio, you can configure destination URL Twilio will invoke when it receives an incoming call. For mine, it would be “http://phonein.herokuapp.com/twilios/incoming”. So, I have “incoming” action defined in “Twilios” controller.

Controller in app/controller/twilios_controller.rb

Just like a regular Ruby on Rails app, controller gets objects ready for the view. It looks up client using the incoming phone number. If client is not found, it says (instead of displaying) an error message and hangs up. If client is found, it asks user to enter a 6-digit code. @post_to object contains URL that will be invoked after user interacts with Twilio. In our case, it’s after user enters code.

class TwiliosController < ApplicationController      
  BASE_URL = "http://phonein.herokuapp.com/twilios"         
 
  def incoming          
    # Get client by phone number          
    client_phone = params['From'][2..params['From'].size]          
    @client = Client.find_by_phone(client_phone)               
 
    if @client.nil?               
      render :action => "no_client.xml.builder"
    else
      @post_to = BASE_URL + "/verify?client_id=#{@client.id}"
      render :action => "incoming.xml.builder", :layout => false
    end
  end
end

View in app/views/twilios/incoming.xml.builder

xml.instruct!
xml.Response do
  xml.Gather(:action => @post_to, :numDigits => 6) do
    xml.Say "Welcome to #{@client.name}'s residence. Please enter your 6 digit code."
  end
end

View in app/views/twilios/no_client.xml.builder

xml.instruct!
xml.Response do
  xml.Say "Client could not be found."
  xml.Hangup
end

2. Verifies home-care professional, checks in, and reads tasks.

Next, look up the home-care professional by the 6-digit code. The numbers user punched will be in ‘Digits’ parameter. If user is found but has not checked in before, it checks in the user and gives some options. If user has already checked in before, user is presented with a few options including an option to check out.

Controller in app/controller/twilios_controller.rb

In addition to incoming action.

class TwiliosController < ApplicationController   
 
  def verify     
    @client = Client.find(params[:client_id])         
    @agent = Agent.find_by_code(params['Digits'])          
    if @agent.nil?       
      # If no agent is found, say "no agent found" error message and hang up.       
      @post_to = BASE_URL + "/verify?client_id=#{@client.id}"       
      render :action => "no_agent.xml.builder"
      return
    else
      if @agent.checked_in?(@client.id) 
        @message = "You have already checked in."
      else
        @agent.check_in(@client.id)
        @message = "Now you are checked in."
      end
    end 
 
    # Default action is direction
    @post_to = BASE_URL + "/direction?agent_id=#{@agent.id}&client_id=#{@client.id}"
    render :action => "direction.xml.builder", :layout => false
  end
end

View in app/views/twilios/direction.xml.builder

xml.instruct!
xml.Response do
  xml.Gather(:action => @post_to, :numDigits => 1) do
    xml.Say "Welcome #{@agent.name}."
    xml.Say "#{@message}"
    xml.Say "Please press 1 to read the task. Press 2 to check out. Press 3 to hear about Yang. Or Press 4 to hang up."
  end
end

View in app/views/twilios/no_agent.xml.builder

xml.instruct!
xml.Response do
  xml.Gather(:action => @post_to, :numDigits => 6) do  
    xml.Say "Agent could not be found. Please enter your 6 digit code."
  end
end

3. Read tasks, check out or hear about Yang

In addition to incoming and verify actions.

This is where main messages are configured and played. Depending on the option user chooses, it will either 1) say the tasks again, 2) check the user out, 3) say a few things about Yang, or 4) just hang up.

class TwiliosController < ApplicationController   
 
  def direction         
    @client = Client.find(params[:client_id])     
    @agent = Agent.find(params[:agent_id])     
    @message = @client.task_list     
    @post_to = BASE_URL + "/direction?agent_id=#{@agent.id}&client_id=#{@client.id}"          
 
    # 1 to hear the tasks again, 2 to check out, 3 to hang up.     
    if params['Digits'] == '1'       
      render :action => "direction.xml.builder", :layout => false
    elsif params['Digits'] == '2'
      @agent.check_out(@client.id)
      @goodbye_message = "Thank you for your service today."
      render :action => 'goodbye.xml.builder', :layout => false
    elsif params['Digits'] == '3'
      @message = "Yang is the most awesome guy ever - both personally and professionally. He is pretty sexy, too."
      render :action => 'direction.xml.builder', :layout => false
    elsif params['Digits'] == '4'
      @goodbye_message = "Have a great day."
      render :action => 'goodbye.xml.builder', :layout => false
    end
  end
end

View in app/views/twilios/goodbye.xml.builder

xml.instruct!
xml.Response do
  xml.Say "#{@goodbye_message}"
  xml.Say "Good-bye."
  xml.Hangup
end

Have fun!

That’s it! My codes are so not refactored and optimized. I did it to see what I can do with Twilio app. I hope this gives you a tip of what you can do with Twilio API. Go bananas!

Post to Twitter

How to install Ubuntu on Chomebook (CR-48) and put parental control

I have had a couple of first-generation Chromebook (CR-48) for a while. I thought these would be pretty good portable computing devices to give to my kids. However, I wasn’t ready to do so unless there was some sort of parental control. As someone who spends a lot of time online, it’s too rough place for kids to roam around. I have known about their support for dev mode, and I decided to figure out which linux flavor would support CR-48.

First search attempt turned out Ubuntu, and since Ubuntu is known for better UI, I decided to give it a try. I also found out there is an excellent parental control guide on Ubuntu as well.

Install Ubuntu on Chromebook (CR-48)

There is no need to re-invent the wheel. Follow instruction here to put Ubuntu 11.04 on Chromebook (CR-48). It worked out like a charm.

Parental Control on Ubuntu

There is a great guide here, and I couldn’t get the Web Content Control to work. However, timekpr is pretty good. You should at least install that.

For filtering content, ProCon Latte Content Filter Firefox Add-on has been working pretty well.

So far, I have been happy with Ubuntu on CR-48. It’s slow and keypad doesn’t work too well, but I think kids are just happy to have their own laptops. :)

Post to Twitter

How to install KidsRuby on Mac OS X and Ubuntu

I have two kids, and I have been wanting to find ways to introduce my kids to programming. Especially for my son, who has asperger syndrome. I thought programming would be a good way to use his interests in logic and mathematics to good use.

I was so much in joy when I found KidsRuby. It’s an awesome project. I think Ruby is a great first language because of its elegance and object-oriented nature to the core.

Previously I had a hard time installing KidsRuby my Mac OS X, due to qt installation error. I was able to at least get it going by cloning their git repository. I had filed a bug for the qt installation error, and the author responded some time ago, but I hadn’t had time to verify it.

I finally had time to verify it, and it worked like a charm.

I also had converted two first-generation Google Chromebooks to use Ubuntu to give to my kids. And while I was familiar with Fedora, this was my first time using Ubuntu, and as new user, I had to search around the net to install Ruby and to install KidsRuby. I am close to finishing it, and I will describe it here.

Mac OS X

This one is pretty easy. Just download the installer dmg file from here, and follow the instruction. It will take a while, but it would be well worth it. You can find the KidsRuby folder in Application folder.

Ubuntu

Now, this one took a while. If you have Ruby installed already, you are good to go. If not, follow the direction below.

If Ruby isn’t installed

You can simply follow the direction from Ryan Bigg to install Ruby 1.9.3.

If Ruby is already installed

I am not sure which version of Ruby is supported, but this applies to Ruby 1.9.3.

The biggest problem I faced was the problem with ffi gem. I kept getting the following error.

Installing ffi (1.0.10) with native extensions
Gem::Installer::ExtensionBuildError: ERROR: Failed to build gem native extension.
 
        /usr/bin/ruby1.9.1 extconf.rb
:29:in `require': no such file to load -- mkmf (LoadError)
	from :29:in `require'
	from extconf.rb:4:in `'
 
Gem files will remain installed in /usr/share/kidsruby/ffi/ruby/1.9.1/gems/ffi-1.0.10 for inspection.
Results logged to /usr/share/kidsruby/ffi/ruby/1.9.1/gems/ffi-1.0.10/ext/ffi_c/gem_make.out
An error occured while installing ffi (1.0.10), and Bundler cannot continue.
Make sure that `gem install ffi -v '1.0.10'` succeeds before bundling.

After searching the net for a while, I realized that I needed to install “-dev” package as well. Since I am using 1.9.3, I had to install ruby1.9.1-dev.

sudo apt-get install ruby1.9.1-dev

After that you can clone the git repository and install necessary packages.

git clone https://github.com/hybridgroup/kidsruby.git
 
cd kidsruby
 
sudo apt-get install libqt4-dev
sudo apt-get install cmake
gem install qtbindings
bundle install

The bundle install part will take a while.

For the lesson part, I had a surprising result – my son totally lost interest very quickly, but my daughter was more into it. :)

KidsRuby on Ubuntu

Post to Twitter

Lean Startup in Education (Hacking for Education)

Today I have had the most productive conversation with my wife (which is shame because I think she has a lot of good insights and look at things from different view points). It was inside the car, while we were driving to Lawrence Hall of Science, which is an awesome place all around.

I had to leave my most current job abruptly, and knowing the reasons behind it, she asked me what’s the most important element angel investors look before making an investment. It was an easy question to answer – the team, of course. And she wholeheartedly agreed. She said she experienced exactly the same at her Korean school, where she teaches grade school kids, and at Korean American Community Center, where she worked before working at the Korean school.

The Korean school she teaches at is part of a church (I am an atheist, but I welcome all religions), and thus their curriculum is not directed or regulated by school district. She said she and a few other teachers like to try new ways of teaching kids. Their attitudes were just like those of tech startup founders. Failure is okay, since you will learn more from failures and apply it to the next new idea. However, she said there were other teachers who are very resistant to trying new things even if they are not the ones implementing or preparing the experiment. Not only do they waste time, they also put out the passion brought on my good teachers. So, she understood how important the team is. Not everyone in the team needs to be super smart, but it’s important for the team to be open to experiments, not be afraid of failures and support each other.

She said she saw the same thing at the Korean American Community Service. She worked there as an office manager until our first child was born. The community center reached the peak while she was there, because she said everyone was open to trying new things – services or classes or whatever – to serve the community better. And most of all, they had the full support from the head of the community center. She also said amazing thing about leadership. Good leadership is not about leading, but creating an environment for team members to innovate. You shouldn’t try to make everyone follow your views, thoughts or directions, but instead give team members freedom to experiment, learn from successes/failures and move  forward. I was like DANG! That’s the most insightful thing I heard from my wife (again, I should have more conversations with her) . :)

I told her that’s the exact operating principal for tech startups these days. I couldn’t believe we were in such unison! And it got me thinking about our education system.  Many people are concerned about our failing education system, and WE HAD THE ANSWER ALL ALONG! Apply “Lean Startup” principal to our education. Encourage teachers to take 20% of their time to innovate. It’s not possible without school district’s support, but if there is, it’s totally doable. And have Lighting Talk or Lesson Learned sessions with other teachers so that they could learn from others’ successes or failures. And pivot if an idea didn’t work out. Or perhaps we need an national website for teachers to share their experiments and lessons learned from them. I truly believe this HACKING FOR EDUCATION will save us, and put our great nation again in leading position.

Post to Twitter

Get WP-Syntax

I was just using blockquote, code and pre HTML tags for indicating codes in my blogs, but they just looked horrible!

But I just installed WP-Syntax, and it’s fantastic. Now, all the codes in my blogs should read much easier.

If you use WordPress and have lots of codes, you probably use some sort of markup tool already. If you don’t, get WP-Syntax.

Post to Twitter

Counting rows and modifying MySQL to work with Postgres or Heroku

Now I am moving on to Open Translation Project. I’ve done some translation work before, including one of Paul Graham’s essay – Why to not not start a startup. BTW, he finally made a link from the essay to my translation. I used Google Translate as base, but I couldn’t believe how bad the translation was. Yahoo’s Babel Fish was a little better, but not as much. That’s where I got the idea of creating this possibly massive project.

Anyhow, I wanted to find a way of selecting an article or blog that was translated the most. I had one model that stored basic information of original article/blog. Then its children are translations. So, I need to count rows of children with the same parent. In MySQL, I had the following statement in Rails.

@top_origs = OrigPost.find(:all,
                              :select => 'orig_posts.*, count(posts.id) as post_count',
                              :joins => 'left outer join posts on posts.orig_post_id = orig_posts.id',
                              :group => 'orig_posts.id',
                              :order => 'post_count DESC',
                              :limit => 5)

Continue reading

Post to Twitter

Duck Tape Programmer

I’ve first read Jamie’s response to Joel’s writing on him on Coders at Work. I didn’t think much of it, and then I had a chance to read Joel’s actual writing. It sort of coincided with another discussion I had with an aspiring entrepreneur I met yesterday. And I decided I like the term, duck tape programmer.

The aspiring entrepreneur I met had his opinion about certain Rails programmers, and that’s exactly who Joel described as “someone with a coffee mug”.  I don’t think it’s a matter of right or wrong, but about the whole approach towards programming. The entrepreneur said that he has met many smart programmers who can talk up the latest movement and fads in programming world, but when it’s time to deliver, they are stuck in their world, trying to come up with best looking code using the latest techniques. However, the kind of programmers most value to startups are those who just get things done.

Some of the cool things he said were,

Peter asked Zawinski, “Overengineering seems to be a pet peeve of yours.”

“Yeah,” he says, “At the end of the day, ship the fucking thing! It’s great to rewrite your code and make it cleaner and by the third time it’ll actually be pretty. But that’s not the point—you’re not here to write code; you’re here to ship products.”

My hero.

Duct tape programmers are pragmatic. Zawinski popularized Richard Gabriel’s precept of Worse is Better. A 50%-good solution that people actually have solves more problems and survives longer than a 99% solution that nobody has because it’s in your lab where you’re endlessly polishing the damn thing. Shipping is a feature. A really important feature. Your product must have it.

I think what Joel referred as duct tape programmers are hackers in Paul Graham’s definition. Just as I concur with Paul, I do with Joel on this. Hacker or duct tape programmer, I aspire to be the one who just gets things done.

I am going to buy that book, which has very similar cover as Founders at Work.

Sweet!

Post to Twitter