Saturday, February 23, 2013

Gotchas during Chapter 8 of the Ruby on Rails tutorial

During the Ruby on Rails tutorial, I encountered several errors during Chapter 8. Luckily, I solved quite a few of them and learnt a few things about debugging along the way.

Problem: Cannot create users
The first thing that caught me was the error regarding creation of users. I could not create the user.

Code: app/controllers/sessions_controller.rb

def create
    user = User.find_by_email(params[:session][:email])
    if user && user.authenticate(params[:session][:password])
      sign_in user
      redirect_to user
    else
      flash.now[:error] = 'Invalid email/password combination' # Not quite right!
      render 'new'
    end

Reading the logs, I saw this message on the line where "find_by_email" is called. I was extremely puzzled as to why this message occurred.

Error message:
SELECT "users".* FROM "users" WHERE "users"."email" = NULL LIMIT 1

Why it happened:
You can't access the values of "email" and "password" through params[:session][:email].

The sessions hash looks like:

utf8: 
authenticity_token: 1D72gydJcrOzGslhOnfAotmkEUtghtQmOhEZRQGWpiw=
sessions: !ruby/hash:ActiveSupport::HashWithIndifferentAccess
  email: 'user@example.com'
  password: 'foobar'


Solution:
You can access the email and password values of the params through 2 methods:

params["sessions"]["email"]
params[:email]

Updated code:
def create
    user = User.find_by_email(params["sessions"]["email"])
    if user && user.authenticate(params["session"]["password"])
      sign_in user
      redirect_to user
    else
      flash.now[:error] = 'Invalid email/password combination' # Not quite right!
      render 'new'
    end

Problem: Cannot authenticate users in authentication_pages_spec.rb
As Postgresql is case-sensitive, we need to make sure the emails are downcased.

      before do
        fill_in "Email",     with: user.email.downcase
        fill_in "Password",  with: user.password
        click_button "Sign in"
        save_and_open_page    # useful to see the page that is generated
      end
The original code was 
user.email.upcase

Saturday, August 25, 2012

My personal evolution - Going from "mono" to "stereo"

One of the biggest personal revelations I have made in the past few months was how much I lacked in empathy. It is almost like I have lived the last 27 years of my life behind a transparent sheet of almost impermeable glass that lets words and images through, but not the emotional nuances.

During a conversation, I tend to focus almost exclusively on the thought process of the person. "What made that person reach that conclusion?" That explains why I am often confused by the irrational way people seem to jump to conclusions, which kind of throws me into an increasing confusion feedback loop trying to understand their thought process even more. I have subsequently made my own life easier by applying the assumption with caveats that most people are irrational and not aware of how they think anyway. This similarly applies to myself.

My friend has commented that I have a highly developed sense for seeing how systems should be designed and the logical way processes should be structured. However, at the same time, I have an almost defunct ability to guess how people will react to my words and actions. This is in contrast to another person whom I work with, who is often able to think 3 - 5 steps in advance during conversations about how to guide the negotiation process forward. 

Luckily, I am now fully aware of this deficiency. Now, it is in the realm of "what I know I don't know". For the past few days, I have been more aware of the pauses in speech, people's facial expressions, the tone of voice and body language. It has been an interesting experience, albeit a bit overwhelming, as there are now more bits of information to process in parallel. I have also been looking for resources to beef up my lack of understanding. Lastly, I think I am only learning to be more human (although.. in a relatively more structured way than most people) =)

I wonder how many people are like me, who are unaware that they are seeing without feeling, in their daily lives?


Friday, July 27, 2012

Trying to solve a dysfunctional team?

You might witness teams that do not function well or even be part of teams that are badly broken. If you ever wanted to solve it, you might need to first identify the root causes. I've found the following framework useful:

The 5 Dysfunctions of a Team
http://flpbs.fmhi.usf.edu/pdfs/Five%20Dysfunctions%20of%20a%20Team.pdf

Bullet points:

  • Absence of trust
  • Fear of conflict
  • Lack of commitment
  • Avoidance of accountability
  • Inattention to results

Sunday, July 8, 2012

Doing it again.. (draft)


I will because the feeling of paying someone for a honest day's work and thanking them for a good job is awesome.

Because surprising your employees is sometimes way better than delighting your customers.

I will first understand the industry's in and outs..

I will aim to find an easy insertion point, then slowly wedge the rest of the business in.

I will focus on building a business, not starting a startup.

I guess I will never stop, it's just too much fun =)


Sunday, June 17, 2012

Questions I have no answers for

Am I making full use of my time?
Are the choices I am making the best?
Am I learning as much as I possibly can?
What do I need to learn?
What are the problems that I should choose to solve?
What are the changes I can bring to healthcare and the environment?
Who do I need to team with?
What are the mistakes I have made?
What are the right decisions I have made?
If I had 5 more years of experience, how would the decisions I make change?
What are the things I think I know?
What are the things I don't know I need to know?
What are the fundamentals I need to learn?

Saturday, May 12, 2012

Solved: Missing JDK - Error with Ant (Java build tool)

I ran into 2 errors while trying to build ZXing mainly due to the fact that I only installed the Java 6 Open JRE but I was missing the JDK (looked at /usr/lib/jvm/java-6-openjdk).


Unable to locate tools.jar. Expected to find it in /usr/lib/jvm/java-6-openjdk/lib/tools.jar

...... /zxing-2.0/javase/build.xml:41: Unable to find a javac compiler;
com.sun.tools.javac.Main is not on the classpath.
Perhaps JAVA_HOME does not point to the JDK.
It is currently set to "/usr/lib/jvm/java-6-openjdk/jre"

Problem solved by installing the JDK from Ubuntu Software Centre.

You can also use: sudo apt-get install openjdk-6-jdk

Platform: Ubuntu 11.10

As a side note, I find it very useful to document all the major installations done on this blog mainly to aid my fallible memory.

Tuesday, April 10, 2012

Error: Piggyback SSL on Heroku - jetty.ssl.keypassword

I was using PiggyBack SSL (Heroku seems to have automatically enabled it for all apps recently) and I came across this error.. 
"jetty.ssl.keypassword "

Background: I am running a Clojure app (Noir) on heroku for testing. The app starts fine but the error message about the ssl keypassword made the app crash when I make a GET request to a https address under heroku.

Fix: I removed the ssl-port option for jetty options. It does not seem like it's needed.
However, if you have your own SSL certificate (not using PiggyBack), then you should set your own.

(def prod-settings 
  {:mode                  mode
   :ns                    'helen
   :session-cookie-attrs  {:max-age 3600
                           :secure  false}
   :jetty-options         {:port      (Integer. (get (System/getenv) "PORT" "8080"))}})
;; Removed ssl-port because heroku keeps requiring ssl password
;; Heroku's ssl-port is 443, no need to supply keystore or ssl password if using PiggyBack SSL

Friday, March 23, 2012

Collection naming problems with MongoDB - Do not include hyphens

Problem: Wrongly named collections in MongoDB will cause exceptions

Why the problem occurs:
I found most of my tips from this article.
http://blog.shlomoid.com/2011/08/how-to-fix-erroneously-named-mongodb.html

Collection names should begin with letters or an underscore and may include numbers; $ is reserved. Collections can be organized in namespaces; these are named groups of collections defined using a dot notation.

You can create collections with names that include hyphens. As explained in the article above, the db.runCommand for creating a collection can look like:

db.runCommand({"create":"test-col"});
However, since the javascript console will interpret collection names with hyphens in them as subtracting letters, you will get errors.

You need to be in to your admin db (and you might need to login first, might not for local)
> use db1
> db.auth(user, pass)
> use admin
> db.runCommand ({renameCollection: "db1.test-col", to: "db1.testCol"})

If that does not work, you might need to repair your database using mongod.
http://www.mongodb.org/display/DOCS/Durability+and+Repair

For my Clojure web app, I tried to keep to a naming convention for my data (using hyphens for spaces) and my functions (using underscore for spaces) but I got a gotcha with Javascript (I think this will happen when using ClojureScript too). 

Thursday, January 26, 2012

Setting up self-signed SSL certificates for your Jetty instance (experiments with Noir and Clojure)

Hi everyone,
  Recently, Heroku has included support for Clojure (fantastic!) and I have been testing it out with Noir. There are several good tutorials on how to get started with Noir (a route-based website development framework with Clojure) and MongoDB (congomongo) on Heroku: http://thecomputersarewinning.com/post/clojure-heroku-noir-mongo http://devcenter.heroku.com/articles/clojure
  Interestingly, Heroku has also enabled free SSL (PiggyBack SSL), which is useful for testing apps. Free hosting, database and SSL, why wait? =)

  This is to document my steps in setting up a self-signed SSL certificate on your own machine for development purposes (Jetty, not Apache). I thought I would be done in 2 hours.. but I ended up taking 2 days. Sigh.. hopefully, this will help someone else.

  There are 2 ways to do this. You can either use keytool or both keytool and openssl. I used openssl and keytool. In hindsight, keytool seems to be easier (thank you Brenton - http://formpluslogic.blogspot.com/2010/08/securing-clojure-web-applications-with.html) and less problematic than using openssl to create the necessary files, then using keytool to import the files.

  FYI, I'm using Windows 7 (you will need to change the commands and paths accordingly), Noir 1.2.2, CongoMongo 0.1.5-SNAPSHOT, Clojure 1.2.1. The 2 programs that you need are OpenSSL ("../GnuWin32/bin/openssl.exe") and Keytool (which you can find in "../Java/jre6/bin/keytool.exe").
OpenSSL - http://devcenter.heroku.com/articles/csr (download the proper version for your system)

  As an overview, you will need to do the following steps:
Install openssl
Use OpenSSL ("../GnuWin32/bin/openssl.exe") to:
  • generate a private site key (site.key)
  • strip the password from site.key for automatic loading when uploaded to a server
  • generate a self-signed signing request (site.csr) (might need it for Heroku)
  • generate a self-signed certificate (sitex509.crt - in x509 format for loading into the keystore)
  • combine the self-signed certificate (sitex509.crt) and site key (site.key) and export it in pkcs12 format (site.pkcs12)
Use keytool ("../Java/bin/keytool.exe") to:
  • import the file site.pkcs12 into the keystore (sitepkcs12.keystore)

I tripped up along the way for many of these steps, so I will include the error messages too for reference.

Install the appropriate version of openssl for your operating system.

OpenSSL
You might need to enter some pass-phrases or passwords. I suggest that you write them down these up, just in case.


Generate a private site key (site.key)
$ openssl genrsa -des3 -out site.key 2048


Make a copy of site.key and strip the password, so that it can be auto-loaded when uploading to a server
$ copy site.key site.orig.key
$ openssl rsa -in site.orig.key -out site.key


Generate a self-signed signing request (site.csr) (might need it for Heroku)
Error: could not find openssl.cnf in the config
You will need to find a copy of the openssl.cnf. I used the one that was in "GnuWin32\share\openssl.cnf". If you are using Linux or OSX, you should be able to find your version. Btw, the version of openssl.cnf that I used was dated 2005 and it still seems to work.
$ openssl req -new -key site.key -out site.csr -config "..\GnuWin32\share\openssl.cnf"
You will need to key in the information requested (please refer to http://devcenter.heroku.com/articles/csr for an explanation). Please fill the proper info for "Common Name", it should be the secure domain or sub-domain. I suggest that you save this info, as you will need to enter the exact same info for the certificate. You can also skip entering any info for the "extra" attributes.
For example,


  Country Name (2 letter code) [AU]:SG
  State or Province Name (full name) [Some-State]:SG
  Locality Name (eg, city) []:Singapore
  Organization Name (eg, company) [Internet Widgits Pty Ltd]: myapp
  Organizational Unit Name (eg, section) []:
  Common Name (eg, YOUR name) []:localhost
  Email Address []:


  Please enter the following 'extra' attributes
  to be sent with your certificate request
  A challenge password []:
  An optional company name []:


Backup your site.csr.

Generate a self-signed certificate (sitex509.crt - in x509 format for loading into the keystore)
$ openssl req -new -x509 -key site.key -out sitex509.crt -config "..\GnuWin32\share\openssl.cnf"
Enter the same info as above.
Error: not in x509 format..
The certificate needs to be in x509 format or keytool will not be able to import it into the keystore as it cannot recognize it.

Backup your sitex509.crt.

Combine the self-signed certificate (sitex509.crt) and site key (site.key) and export it in pkcs12 format (site.pkcs12)
$ openssl pkcs12 -inkey site.key -in sitex509.crt -export -out site.pkcs12

Backup your site.pkcs12.


Keytool
Copy the file site.pkcs12 to your "..\Java\jre6\bin\" directory


Make sure you have full control (write, read-access) to the Java directory
Error: I had an error initially as I could not write to the Java directory. Go to the folder settings and enable the permissions. For Windows 7, you can add "Everyone" to the users and set "Full Control" for "Everyone".


Import the file site.pkcs12 into the keystore (sitepkcs12.keystore)
$ keytool -importkeystore -srckeystore site.pkcs12 -srcstoretype PKCS12 -destkeystore sitepkcs12.keystore

Double-check the keystore.

$ keytool -list -v -keystore sitepkcs12.keystore

Backup your sitepkcs12.keystore.

Noir

Copy all the files (site.key, site.csr, sitex509.crt, sitepkcs12.keystore) to your Noir project directory ("../myapp/").
I think only the keystore file is needed.
Error: javax.ssl does not .. correspond .. cipher.
You need to convert both the key and the cert (in x509) to pkcs12 format and import them into the keystore. Then, place the keystore in your Noir project folder.

Change your jetty settings
You will need to pass the settings (jetty-options as a map) to Jetty (remember your password!). In server.clj, for example,

(defn -main [& m]
  (let [mode      (keyword (or (first m) :dev))
        port      (Integer. (get (System/getenv) "PORT" "8080"))
        ssl-port  (Integer. "443")]
    (def myappserver (server/start ssl-port
                       {:mode           mode
                        :jetty-options  {:port      port
                                         :ssl-port  ssl-port
                                         :join?     false
                                         :ssl?      true
                                         :keystore "sitepkcs12.keystore"                    
:key-password  "abcdef"}
                        :ns             'myapp
                        :session-cookie-attrs  {:max-age 3600
                                                :secure  true}}))
    (users/db-init)))


Apologies for the weird formatting, please adjust accordingly for your app.

Go to https://localhost:443/myapp and http://localhost:8080/myapp to test.

Wednesday, November 30, 2011

Ask yourself daily how you are making someone's life better

Today, I learnt a very important lesson about startups. After 1 year of hitting walls together and self-reflection, I have arrived at a definition of a startup (not the definitive one, just my personal understanding). The startup process is a daily journey of pain and joy trying to honestly answer the all-important question for your customers: "How are you making my life better today?"