Wednesday, April 10, 2013

Managing Rails Environment Variables is the pain in the ass

Managing Rails Environment Variables is the pain in the ass


I have quite a few heroku apps that have sandbox, staging and production environment.
and I have to manage lots of environment variables, e.g. Facebook, AWS, TWILIO, octopus database URL etc.

figaro gem really help:
https://github.com/laserlemon/figaro


Environment variables in ONE place with figaro


figaro gives you a yaml file which stores all the environment variables for all environments:

    config/application.yml


Updating Heroku environment variables in one command


the powerful bit comes when you update your heroku instances environment variables

    rake figaro:heroku

this rake task save you time to run those heroku config:set xxx=yyy --app abc-staging


Not committing this file to public !


like handling other confidential data files in git repository, this file is ignored (included in .gitignore) and never being committed to git repository.
while sharing the file structure without sharing the secrets.
I recommend using a ".sample" approach.

copy the config/application.yml to config/application.yml.sample
and then commit this .sample file to git repository for your teammates to follow


Thanks laser lemon and thanks figaro !

Sunday, March 24, 2013

Pronunciation of "route"

Occasionally, I often heard two different versions for the pronunciation of "route"("root" vs "rowt"), mostly from computer networking context. It got me to google which one is "correct".

Firstly, "root" +1 from Hong Kong Yahoo dictionary...
http://hk.dictionary.yahoo.com/dictionary?p=route

Then, it appears a typical pronunciation difference between British and American...
http://www.howjsay.com/index.php?word=route&submit=Submit

While some people suggest that there is a little historical factor... one more party French... hmm...
http://ph.answers.yahoo.com/question/index?qid=20100511082156AAuZ6VL

Interesting responses:
"I say root. Personally, I cringe when I hear someone pronounce it rowt."
"I say root. I hate when people say rowt. They all must die."

Conclusion: 

Monday, March 18, 2013

iphone Personal Hotspot suddenly disappeared and I fixed it accidentally

Suddenly Gone

I had been using the Personal Hotspot on my iPhone since day one. But just now, the Personal Hotspot was gone ! disappeared ! missing !


I suspected that it was some changes on firmware update ... but the version stayed the same. version 6.1.2

I tried the following:
- Switch it off and on again
- "Settings" > "General" > "Reset" > "Reset Network Settings"

didn't work.

Fix

then at last I found the settings in 
- "Settings" > "General" > "Cellular" > "Personal Hotspot"
after I switched it on, the "Settings" > "Personal Hotspot" appeared again.

WEIRD!

Sunday, March 3, 2013

hotcocoa/mappings/appkit/box.rb:3:in `block': uninitialized constant CGRectZero (NameError)

Where does this error coming from?

So... after playing with RubyMotion, I start picking up MacRuby !
my goal was to build up some desktop utility apps and interactive desktop application taking various of gesture capturing input devices.

First, I tried out the hello world in XCode and it works fine. Then I tried writing Macruby apps without XCode. After I install macruby on rvm and run the Macruby apps generated by hotcoca, I saw this error:

hotcocoa/mappings/appkit/box.rb:3:in `block': uninitialized constant CGRectZero (NameError)


Troubleshooting in irb ?

Spent quite a lot of time checking documentation and setup instructions. When I tested the missing dependencies in irb, I found out that only those related to Cocoa UI are missing. So I load the cocoa framework explicitly and it works:

framework 'CocoaGraphic'
CRRectZero

Solve that in hotcocoa project

inside my application.rb, I load the framework explicitly before loading the hotcocoa gem:

begin
  # for OSX 10.8
  framework 'CoreGraphics'
rescue
end
framework 'Cocoa'

require 'rubygems' # disable this for a deployed application
require 'hotcocoa'



Tuesday, January 29, 2013

Refactoring "if nil?"

Very often we have checking against nil value like this:

if products.nil?
  products.first.total_amount
else
  0.0
end


There is a cleaner way to achieve the same result:

products.first.try(:total_amount) || 0.0

Wednesday, December 19, 2012

Possible reasons that your apn_on_rails may not work

There were several times that user reported that the Push Notification not working. That's always my first response: "It should be working. No way it is not working. I just fixed it few days ago, and it was working !"

I found the need to share all the errors I saw, and also as a checklist reference for my future projects.

1. I was using the wrong fork of http://github.com/XXX/apn_on_rails 

  There are bugs in the master github repository PRX/apn_on_rails. And in some forks, you should put the .pem file path as the configatron.apn.cert, while in some other branches, configatron.apn.cert is actually asking for file content:

    configatron.apn.cert = File.join(Rails.root, 'config', 'certs', 'apn_dev.pem')
    configatron.apn.cert = File.read(File.join(Rails.root, 'config', 'certs', 'apn_dev.pem'))

  There are some more other fixes loosely exist in some forks and I have no idea which one is the best, so ... I forked one more for myself. https://github.com/3dd13/apn_on_rails


2. apn push token I collected from 2 mobile apps are the same

I was setting up two mobile apps push notification by one backend server, and user is using both mobile apps. I knew that I had to use two different .pem cert file to push to the two different apps, but sometimes one of them was not working and sometimes it pushed messages to the wrong mobile apps.

After tracing all the code, finally, I found out that the apn_token from the 2 mobile apps I collected are actually the same. And the APN::Device instance did not create with the correct app:

    device = APN::Device.find_or_create_by_token(apn_token)

so this is my fix:

    device = APN::Device.find_or_create_by_token_and_app_id(self.apn_token, apn_app.id)


3. I submitted the apn token with incorrect format

I solved this issue few months ago, but recently after I rewrite some code and this bug dragged me crazy ... once again.

the apn push token you collected from mobile is in this format:

    00ea74e76a873e8e9c14c2dd2afe3b42abb35148e94042811e2b6985072641f2

but actually, apn_on_rails is expecting this:

    00ea74e7 6a873e8e 9c14c2dd 2afe3b42 abb35148 e9404281 1e2b6985 072641f2

I wrote a method to convert that:

4. I setup the staging with production push cert with sandbox apn host

One of my early chore was setting up apn push cert, so to do it quick (and dirty), I was using development .pem cert file on both my dev machine and so-called production. But later when I was switching the production cert to the real production cert, It did not work.

At that moment of time, what drove me crazy was that no error was thrown and the "sent_at" attribute of the APN::Notification is correctly updated.

So, we keep checking everything again and again, generating certs for several times, restarting servers, clearing up database records. AND ... the real bug is actually the incorrect configatron.apn.host

gateway.push.apple.com should be used for production, and gateway.sandbox.push.apple.com should be used for development


5. Used production for staging (on heroku) Procfile

Push messages are sent out in worker threads (by sidekiq), and workers are started using Procfile:

    worker: bundle exec sidekiq -e production -C config/sidekiq.yml

obviously, this Procfile won't work for staging or development machine, the correct one should be:

    worker: bundle exec sidekiq -e $RACK_ENV -C config/sidekiq.yml


6. Errno::ENAMETOOLONG File name too long

There were something like that in the log

    Errno::ENAMETOOLONG
    WARN: File name too long - Bag Attributes

actually, this is not an error, just a warning. However, it fills up my logentries page which makes it hard to debug.

This one was caused by some strange bug (perhaps not a bug, but I don't understand why). It is related to the configatron.apn.cert path issue I was talking about.

In the same function, configatron.apn.cert was treated as both path and file content. If you want to know the details, check out the commit I made to fix it:
https://github.com/3dd13/apn_on_rails/commit/0b60b26b38540d0c59a6cd21068d6b2f9a6cf139


Tuesday, November 27, 2012

Deploying single ruby script to heroku


I need a simple ping service which notifies me (via email) when my web application is down. I can write a simple ruby script to achieve that without much problem.


However, I also want this script to be run regularly and hosted on the internet for FREE. the following is my attempt on using Heroku and Heroku's Scheduler add-on.
(Heroku's scheduler can run every 10mins, 1 hour or 1 day)


only 2 files are needed: health_check.rb and Gemfile.
Source Code:
https://gist.github.com/4153156

Directory Structure:


OK, actually 3 files.
- health_check.rb is a ruby script which calls Net::HTTP and sends email using Net::SMTP
- Gemfile is an file which tells Heroku that this is a ruby application
- Gemfile.lock is the file being generated after running bundle install

that's it. go ahead and push it to heroku:
git push heroku master


and then add Heroku Scheduler to your project.
you can do it by logging in to heroku.com or via command line


add a scheduler job with ruby command line:


DONE.