Step By Step of Creating a Ruby Gem

Step By Step of Creating a Ruby Gem

I’m going to create a ruby gem to handle the accents in a string. The gem will replace all the accents to it’s corresponding ascii character. And will achieve this by extending the class String to provide an instance method #accent_to_ascii.

For example:

require 'accent_to_ascii'
"Thìs ìs ā strìng wïth āccēnts".accent_to_ascii
#=> "This is a string with accents"

The initialtive is that those non-ascii codes in the string sometime is not compatible with systems, we need clear them up. But it’s too crude to just remove them with something like gsub(/[^\x20-\x7e]/, ''). And there are a lot of names are with accents in American. So replace those accents with the corresponding ascii characters is a better solution. ( Will make them happy 🙂 )

So in this article will create a gem accent_to_ascii to do this specific task.

Let’s get started:

Steps (story in short)

  1. Create the files for the gem. It’s as simple as just running: bundle gem accent_to_ascii. This will create the gem files from templates into directory ./accent_to_ascii. I prefer the rspec option for testing.
  2. Develop the gem functionality.
    1. Update the gemspec file accent_to_ascii.gemspec with information of the gem.
    2. Write tests in the spec/accent_to_ascii_spec.rb (Test first right?)
    3. Write the core methods in the lib/accent_to_ascii.rb to make tests green
  3. Publish it into, if you already have rubygems account, this is simple as just run rake release

Now let’s diving into the details of the above steps:

1. Gem Creation

Create gem is as simple as just a line of command:

$ bundle gem accent_to_ascii

By running this command, the bundler will create the gem in the directory accent_to_ascii as:

$ tree accent_to_ascii
├── Gemfile
├── LICENSE.txt
├── Rakefile
├── accent_to_ascii.gemspec
├── bin
│   ├── console
│   └── setup
├── lib
│   ├── accent_to_ascii
│   │   └── version.rb
│   └── accent_to_ascii.rb
├── pkg
│   └── accent_to_ascii-0.1.0.gem
└── spec
    ├── accent_to_ascii_spec.rb
    └── spec_helper.rb


The accent_to_ascii.gemspec is the description file of this gem, we can modify it first.


The lib/accent_to_ascii/version.rb defined the version of the gem.

module AccentToAscii
  VERSION = "0.1.0"

The version is defined with a Major.Minor.Patch style:

  • The Major version is for updates will break the backward compatibility;
  • The Minor version is for updates with backward compatibility;
  • The Patch version is for bug fixes with backward compatibility.


This is the test file, we modify this file with the expected behaviors of the gem and make it green by developing the code.


This is the main code file.

2.1 Update the gemspec file

Just provide the informations in the TODO section, and I make it as:

# coding: utf-8
lib = File.expand_path('../lib', __FILE__)
$LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
require 'accent_to_ascii/version' do |spec|          = "accent_to_ascii"
  spec.version       = AccentToAscii::VERSION
  spec.authors       = ["uniEagle"]         = [""]

  spec.summary       = %q{Rubygem to replace accents in string into the corresponding ascii chars}
  spec.description   = %q{Replace the non ascii accents in a string}
  spec.homepage      = ""
  spec.license       = "MIT"

  spec.files         = `git ls-files -z`.split("\x0").reject do |f|
  spec.bindir        = "exe"
  spec.executables   = spec.files.grep(%r{^exe/}) { |f| File.basename(f) }
  spec.require_paths = ["lib"]

  spec.add_development_dependency "bundler", "~> 1.13"
  spec.add_development_dependency "rake", "~> 10.0"
  spec.add_development_dependency "rspec", "~> 3.0"

2.2 Write the tests

The in the test file /spec/accent_to_ascii_spec.rb, added several tests to reflect the expected behavior of this gem:

require "spec_helper"

describe AccentToAscii do
  it "has a version number" do
    expect(AccentToAscii::VERSION).not_to be nil

  it { expect("São Paulo".accent_to_ascii).to eq "Sao Paulo" }
  it { expect("Tẽst".accent_to_ascii).to eq "Test" }

  it "does not change original string" do
    str = "São Paulo"
    expect(str.accent_to_ascii).to eq "Sao Paulo"
    expect(str).to eq "São Paulo"

  context "hungarian accents" do
    specify { expect("fejlődő".accent_to_ascii).to eq "fejlodo" }
    specify { expect("FEJLŐDŐ".accent_to_ascii).to eq "FEJLODO" }
    specify { expect("fű".accent_to_ascii).to eq "fu" }
    specify { expect("FŰ".accent_to_ascii).to eq "FU" }

  context "accent_to_ascii!" do
    let(:str) { "São Paulo" }

    it "changes original string" do
      expect(str.accent_to_ascii!).to eq "Sao Paulo"
      expect(str).to eq "Sao Paulo"

And of course, if you run rake, almost all the tests will fail:

$ rake
... some test errors ...
Finished in 0.0024 seconds
9 examples, 8 failures

2.3 Write some real code and make the tests green

The file /lib/accent_to_ascii.rb is the target file. I just made it as the following:

require "accent_to_ascii/version"

module AccentToAscii
    'E' => [200,201,202,203],
    'e' => [232,233,234,235,7869],
    'A' => [192,193,194,195,196,197],
    'a' => [224,225,226,227,228,229,230],
    'C' => [199],
    'c' => [231],
    'O' => [210,211,212,213,214,216,336],
    'o' => [242,243,244,245,246,248,337],
    'I' => [204,205,206,207],
    'i' => [236,237,238,239],
    'U' => [217,218,219,220,368],
    'u' => [249,250,251,252,369],
    'N' => [209],
    'n' => [241],
    'Y' => [221],
    'y' => [253,255],
    'AE' => [306],
    'ae' => [346],
    'OE' => [188],
    'oe' => [189]

  def self.accent_to_ascii(string)
    string.tap do |s|
      ACCENTS_MAPPING.each { |letter, accents| replace(s, letter, accents) }


  def self.replace(string, letter, accents)
    packed = accents.pack('U*')
    regex ="[#{packed}]", nil)
    string.gsub!(regex, letter)


class String
  def accent_to_ascii(string =

  def accent_to_ascii!

Special thanks to the Github project accentless, reused the ACCENTS_MAPPING in that project.

Then the tests are green now:

$ rake
  has a version number
  should eq "Sao Paulo"
  should eq "Test"
  does not change original string
  hungarian accents
    should eq "fejlodo"
    should eq "FEJLODO"
    should eq "fu"
    should eq "FU"
    changes original string

Finished in 0.00283 seconds
9 examples, 0 failures

3. Package and Publish

If you already have rubygems account registered and configured well, it’s just as simple as a single command:

$ rake release

Or, just sign up in the, then run the following command:

$ gem push pkg/accent_to_ascii-0.1.0.gem

The first time run this command will ask you input your account information for

And for the following up changes, just update the version and run rake release.


[Engineering Lunch Series] Step-by-Step Guide to Building Your First Ruby Gem

Official Guide of Publish Gems onto

How to Deploy iOS Applications into Any Device out of Apple Store – Using dropbox

This is the previous article about how to do this on self managed host.
But we can take the advantage of Dropbox to do this, will be more convenient.

  1. Upload the signed ipa file to dropbox, and get the link of the ipa. It will be something like:

Replace to to modify it as:
  1. Create manifest file as:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "">
<plist version="1.0">
                <string>YOUR APP BUNDLE IDENTIFIER</string>
                <string>YOUR APP NAME</string>

Please replace the ipa path, image path and bundle identifier, app name in this file.
The ipa path is what got from step 1.
And update this manifest file to Dropbox. And similar to ipa file, get the manifest file link from something like:


Please notice the postfix ?dl=0 also removed.

  1. Create a install html page using this manifest link:
<a href="itms-services://?action=download-manifest&url=">

Please replace the manifest link and YOUR APP NAME.

Then open the install.html in Safari and enjoy!

Faster Dock in Mac OSX

This makes the animation faster

defaults write autohide-time-modifier -float 0.15;killall Dock
defaults delete autohide-time-modifier;killall Dock

This makes the delay of show/hide Dock faster:

defaults write autohide-delay -float 0; killall Dock
// and also the restore:
defaults delete autohide-delay;killall Dock


Leetcode: Palindrome Number


Leetcode link for this question
Determine whether an integer is a palindrome. Do this without extra space.


This is the previous post on this question
This is easy question, just find the most left digit and then compare each digit from left-right ends to center.


C++ code accept by Leetcode, which exclude negative number like -121 as palindrome

class Solution {
    bool isPalindrome(int x) {
        if(x < 0)
            return false;
        int highDigit = 1;
        while(x / highDigit >= 10)
            highDigit *= 10;
        int lowDigit = 1;
        while(highDigit > lowDigit){
            int high = (x / highDigit) % 10;
            int low = (x/lowDigit) % 10;
            if(high != low)
                return false;
            highDigit /= 10;
            lowDigit *= 10;
        return true;

C++ code for who consider negative number like -121 also as palindrome

class Solution {
    bool isPalindrome(int x) {
        int highDigit = 1;
        while(x / highDigit >= 10 || x / highDigit <= -10)
            highDigit *= 10;
        int lowDigit = 1;
        while(highDigit > lowDigit){
            int high = (x / highDigit) % 10;
            int low = (x/lowDigit) % 10;
            if(high != low)
                return false;
            highDigit /= 10;
            lowDigit *= 10;
        return true;

Leetcode: String to Integer (atoi)


Leetcode link
Implement atoi to convert a string to an integer.


This is the previous answer to this question

The complexity of this problem is how to handle edge cases.
For int, standard as 32-bit length, has a max value of (1<<31) - 1 and a min value of (1<<31).
When read each digit from string, need check if the result will be overflow.
And another situation is that the leading blank spaces, and possibly has + or -.


class Solution {
    const int max = (1<<31) - 1;
    const int min = -max - 1;

    inline bool willOverflow(int sign, int base, int digit) {
        static const int maxTenth = max / 10;
        static const int maxDigit = max % 10;
        static const int minTenth = - (min / 10);
        static const int minDigit = - (min % 10);
        if(sign == 1){
            return (base > maxTenth || base == maxTenth && digit > maxDigit);
        } else {
            return (base > minTenth || base == minTenth && digit > minDigit);

    // The test case only allow "    -123" like this, after hit sign or digit, can not take any invalid or blank char.
    int myAtoi(string str) {
        if (str.size() == 0) return 0;
        int sign = 1;
        bool gotNumber = false; //allow blank space before number
        bool gotSign = false; // allow <= 1 sign
        int result = 0;
        for(int i = 0; i < str.size(); ++i) {
            if(!gotNumber && str[i] == ' ') continue; 
            if(!gotNumber && !gotSign && (str[i] == '+' || str[i] == '-')){
                sign = str[i]=='-' ? -1 : 1;
                gotSign = true;
                gotNumber = true;
            if(str[i] < '0' || str[i] > '9')
                return result * sign;
            gotNumber = true;
            int digit = str[i] - '0';
            if(willOverflow(sign, result, digit))
                return sign == 1 ? max : min;
            result = result * 10 + digit;
        return result * sign;

Leetcode: Contains Duplicate II


Contains Duplicate II
Given an array of integers and an integer k, find out whether there are two distinct indices i and j in the array such that nums[i] = nums[j] and the difference between i and j is at most k.


It’s strait forward to using dictionary on this question. First run, save position of each number in the dictionary; Second run, check the dictionary to see if there is another duplication in this array and check the position of it.
But there is a situation that need take into consideration, that the array may contain the duplication multiple times. To deal with this, just checking in the first run, to see if the last position (if any) is close enough.


C++ code

class Solution {
    inline int abs(int v) {
        return v < 0 ? -v : v;
    bool containsNearbyDuplicate(vector<int>& nums, int k) {
        map<int, int> dict;
        for(int i=0; i<nums.size(); ++i) {
            if(dict.find(nums[i]) != dict.end()) {
                if(abs(dict[nums[i]]-i) <= k)
                    return true;
        for(int j=0; j<nums.size(); ++j){
            map<int,int>::iterator it = dict.find(nums[j]);
            map<int,int>::iterator endit = dict.end();
            if(endit != it){
                int i = it->second;
                if(i != j && abs(i-j) <= k)
                    return true;
        return false;

Remapkey by Microsoft

Official remapkey.exe by MS. To edit the hardware keys to any keys you want.
Especially useful of Mac users on windows.
I always remap the “command” key to “control” and “control” to “command”. Then all the frequently used shortcuts like:

Cmd Windows Key Mac key
copy control + c command + c
paste control + v command + v
cut control + x command + x
select-all control + a command + a
save control + s command + s
new-tab control + t command + t
new-file control + n command + n

will remain the same as Mac OS.


Take my usage as example, swap the Command and Control:
Remapkey Usage

Open Remapkey.exe with Admin permission, then drag the left control on the above to the left windows in the bottom; and drag the left windows on the above to the left control at the bottom.
Then click the save and quit button.
It require a restart of windows, then enjoy!

Here is the software download: from

Leetcode: Integer to Roman


Integer to Roman
Given an integer, convert it to a roman numeral.
Input is guaranteed to be within the range from 1 to 3999.


Just handle each digit in the number.
For numbers from [0, 9], they are mapping to:
0 – ‘ ‘
1 – ‘I’
2 – ‘II’
3 – ‘III’
4 – ‘IV’
5 – ‘V’
6 – ‘VI’
7 – ‘VII’
8 – ‘VIII’
9 – ‘IX’

The patten is that for digit in [0,3], repeat ‘I’ digit times;
for digit == 4, ‘IV’
for digit in [5, 8], put digit-5 times ‘I’ after ‘V’;
for digit == 9, ‘IX’

Then from 10 – 90, using ‘X’, ‘L’, ‘C’ instead of ‘I’, ‘V’, ‘X’. So if we store all the available chars in an array, it just move the base index += 2 each time we handle next digit.


C++ Code

char* intToRoman(int num) {
    char chars[] = {'I', 'V', 'X', 'L', 'C', 'D', 'M', 'C', 'D'};
    char * result = malloc(100);
    if(num <= 0 || num >= 4000)
        return result;

    int tail = 100;
    int charBase = 0;
    while(num != 0)
        int digit = num % 10;
        char temp[3];
        int templen = 0;
        if(digit <= 3)
            for(int i = 1; i <= digit; ++i)
                temp[i-1] = chars[charBase];
            templen = digit;
        else if (digit == 4)
            temp[0] = chars[charBase];
            temp[1] = chars[charBase + 1];
            templen = 2;
        else if(digit <= 8)
            temp[0] = chars[charBase + 1];
            templen = 1;
            for(int i = 6; i <= digit; ++i)
                temp[i-5] = chars[charBase];
                templen += 1;
            temp[0] = chars[charBase];
            temp[1] = chars[charBase + 2];
            templen = 2;

        //copy temp to result
        tail = tail - templen;
        for(int i = 0; i < templen; ++i)
            result[tail + i] = temp[i];

        charBase += 2;
        num /= 10;

    //move result to start
    for(int i = tail; i < 100; ++i) {
        result[i-tail] = result[i];
        result[i] = 0;

    return result;

LeetCode: Reverse Integer

Previous Post

This is the previous post on same question.


LeetCode Link
Reverse digits of an integer.
Example1: x = 123, return 321
Example2: x = -123, return -321


Careful about the overflow. For ruby, it’s not a problem. For c++, need more consideration.


Ruby Code

# @param {Integer} x
# @return {Integer}
def reverse(x)
    sign = x >= 0 ? 1 : -1
    x = x.abs
    y = 0
    int_max = 2 ** 31 - 1
    while x > 0 do
        digit = x % 10
        y = y * 10 + digit
        if y > int_max
            y = 0
        x /= 10
    y * sign

C++ Code

class Solution {
    int reverse(int x) {
        int sign = 1;
        if(x < 0) {
            sign = -1;
            x = -x;
        int int_max = (1 << 31) - 1; //notice the priority of << is lower than -
        int dime = int_max / 10;
        int tail = int_max % 10 + (sign == 1 ? 0 : 1);

        int y = 0;
        while(x > 0){
            int digit = x % 10;
            if(y > dime || (y == dime && digit > tail)){
                return 0;
            y = y * 10 + digit;
            x /= 10;
        return y * sign;

LeetCode: ZigZag Conversion

Previous post

This is the old post on this question, using another method.


Leetcode Link
The string “PAYPALISHIRING” is written in a zigzag pattern on a given number of rows like this: (you may want to display this pattern in a fixed font for better legibility)

P   A   H   N
Y   I   R

And then read line by line: “PAHNAPLSIIGYIR”
Write the code that will take a string and make this conversion given a number of rows:

string convert(string text, int nRows);
convert("PAYPALISHIRING", 3) //should return "PAHNAPLSIIGYIR".


This question is simple, one method is that build strings for each row, and for each char in the string, determine the target row of the position based on the total row count, and append it to the target string. Then concat all the strings together in the last.


The fast ruby version

# @param {String} s
# @param {Integer} num_rows
# @return {String}
def convert(s, num_rows)
    result = []
    tail_size = num_rows > 2 ? num_rows - 2 : 0
    group_size = num_rows + tail_size

    s.length.times do |i|
        in_group_position = i % group_size
        target_row = if in_group_position < num_rows
            num_rows - 1 - (in_group_position - num_rows)
        result[target_row] ||= ""
        result[target_row] << s[i]


Screen Shot 2016-05-04 at 16.20.51

Require Administration Permission in VS 2013

C++ Project

  1. Right click the Project, click Properties
  2. Navigate to Linker
  3. Navigate to Manifest File
  4. Edit the UAC Execution Level to requireAdministrator

C# project:

Edit the properties\app.manifest, modify the permission node as the one in the specifications there.

Debug with UAC:

Start the VisualStudio with Administrator permission, and you can debug the projects need UAC.

Distribution Items Equally in View with Auto-Layout in iOS

Taking this layout as example, we want to place 2 buttons in the view, and need them distributed in the view equally in the view.
Screen Shot 2016-02-27 at 21.57.16

So there are 3 spaces:
1. from superview left to center of “Previous” button;
2. from center of “Previous” button to center of “Next” button;
3. from center of “Next” button to right edge of superview.

If those 3 spaces are equal, then we achieved the goal.
It’s simple to do this with automatic layout in iOS:
Create 2 constrains:
Screen Shot 2016-02-27 at 21.58.19
1. from “Previous” button center to tailing of superview, with constant 0 and multiplier 3:1;
2. from “Next” button center to tailing of superview, with constant 0 and multiplier 3:2.

All set, enjoy!

Manage User Group in Mac

List all users

dscl . list /users
dscl . readall /users

List all groups

dscl . list /groups
dscl . readall /groups

Check members under a group

members () { dscl . -list /Users | while read user; do printf "$user "; dsmemberutil checkmembership -U "$user" -G "$*"; done | grep "is a member" | cut -d " " -f 1; };
members $group_name_you_want_to_check

Check groups a user belongs to

groups $user_name

Add user to a group

sudo dseditgroup -o edit -a $user_name_to_add -t user $group_want_add

SSH Timeout and Non-password Login

There are some inconveniences login via ssh.


The first thing is timeout, the sshd always drop connections after certain idle time interval by default, it’s really annoy if you are not care this secure consideration.
We can disable this timeout mechanism by adding the following configs into sshd configuration file.

# File: /etc/ssh/sshd_config
ClientAliveInterval 30 
TCPKeepAlive yes 
ClientAliveCountMax 99999

Non-password Login

We also can login via public keys instead of entering the password every time. Just run the following commands:

# Generate the ssh keys:
ssh-keygen -t rsa
# Copy the public key into hosts' authorized_keys
cat ~/.ssh/ | ssh user@ "mkdir -p ~/.ssh && cat >>  ~/.ssh/authorized_keys"

We can then turn off the password login to secure our hosts:

# Edit: /etc/ssh/sshd_config
PermitRootLogin without-password


Formatting DateTime in Rails

  • There are some useful params with Time#to_s
[14] pry(main)> time = u.created_at
=> Thu, 13 Nov 2014 14:21:01 UTC +00:00
[15] pry(main)> time.to_s(:long)
=> "November 13, 2014 14:21"
[16] pry(main)> time.to_s(:short)
=> "13 Nov 14:21"
[17] pry(main)> time.to_s(:default)
=> "2014-11-13 14:21:01 UTC"
[18] pry(main)> time.to_s(:db) #this will put it into the UTC time zone
=> "2014-11-13 14:21:01"
[19] pry(main)> time.to_s(:number)
=> "20141113142101"
[20] pry(main)> time.to_s(:long_ordinal)
=> "November 13th, 2014 14:21"
[21] pry(main)> time.to_s(:rfc822)
=> "Thu, 13 Nov 2014 14:21:01 +0000"
> time.utc.strftime('%FT%TZ')
=> "2016-03-18T18:33:09Z"
  • And for custom formatting, there is a very good post for it:

Burn bootable ISO file into U-Disk in Mac OSX Yosemite

1 Open DiskUtil and format your u-disk with FAT format

2 Open Terminal, run diskutil list, you’ll get following output:

$diskutil list
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:      GUID_partition_scheme                        *500.3 GB   disk0
   1:                        EFI EFI                     209.7 MB   disk0s1
   2:       Microsoft Basic Data BOOTCAMP                100.0 GB   disk0s2
   3:       Microsoft Basic Data DATA                    250.3 GB   disk0s3
   4:                  Apple_HFS Mac                     149.0 GB   disk0s4
   5:                 Apple_Boot Recovery HD             650.0 MB   disk0s5
   #:                       TYPE NAME                    SIZE       IDENTIFIER
   0:     FDisk_partition_scheme                        *7.7 GB     disk1
   1:                 DOS_FAT_32 UNTITLED 1              7.7 GB     disk1s1

So remember the disk position of your u-disk, as in the example above, it’s /dev/disk1

3 Run following command in terminal:

sudo dd if=/Users/unieagle/Downloads/Windows10_TechnicalPreview_x64_ZH-CN_9926.iso of=/dev/disk1 bs=8192

You can drag your iso file into terminal after input sudo dd if=, it will fill the path of iso file for u automatically.

4 Wait about 40′, and u will get the info in terminal:

532494+1 records in
532494+1 records out
4362192896 bytes transferred in 3034.644407 secs (1437464 bytes/sec)

This indicate success. So enjoy your bootable u-disk from ISO file.

If you got error message dd: /dev/disk1: Resource busy in the step 3, try to UNMount your udisk partition in DiskUtil and redo step 3.


[Solved] Install Nokogiri on Yosemite with Ruby 2.1.3

Updated to Yosemite and got the following problem while run bundle install with ruby 2.1.3:

An error occurred while installing nokogiri (1.6.1), and Bundler cannot continue.
Make sure that `gem install nokogiri -v '1.6.1'` succeeds before bundling.

The solution is:

gem install nokogiri -v '1.6.1' -- --use-system-libraries=true --with-xml2-include=/Applications/
Fetching: nokogiri-1.6.1.gem (100%)
Building native extensions with: '--use-system-libraries=true --with-xml2-include=/Applications/'
This could take a while...
Successfully installed nokogiri-1.6.1
Parsing documentation for nokogiri-1.6.1
Installing ri documentation for nokogiri-1.6.1
Done installing documentation for nokogiri after 3 seconds
1 gem installed

Using SPF13 Vim – Install


VIM is a powerful text/code editor, and there are so many plugins and configurations for it.
SPF vim give a solution of the plugins package and configurations refined for programers.


Follow the guide on SPF VIM SITE

OR just run the following command in your terminal:

curl -L -o - | sh

The startup screen

Not sure if it is a bug of SPF13, the annoying message ‘Type Command or ….. to continue’ shows up every time when start the vim after install spfvim. But we can get rid of this by adding the following line to file ‘~/.vimrc.local’:

let g:bufferline_echo=0

中文字符, Multi-byte characters

To get rid of the disorder of displaying multi-byte characters, need add the following lines to the file ‘~/.vimrc.local’:

set fileencodings=ucs-bom,utf-8,cp936,gb18030,big5,euc-jp,euc-kr,latin1
set fileencoding=utf-8
set encoding=utf-8

Custom Color Schema

The built in color can be changed as your with, i like this one:

colorscheme molokai

To be continue …

Time Zone in Rails

  • Get All Time Zones

    ActiveSupport::TimeZone.all.each{|tz| puts "#{tz.formatted_offset}, #{}"};nil
    -11:00, American Samoa
    -11:00, International Date Line West
    -11:00, Midway Island
    -10:00, Hawaii
    -09:00, Alaska
    -08:00, Pacific Time (US & Canada)
    ... ignore the remaining ...

    To list all the built in time zones with Rails

  • Get Specific Time Zone
    Use'Eastern Time (US & Canada)')

    To get the instance of a time zone with the name listed within the above output

  • Custom Time Zone
    When u know the offset, you can do this via

    ActiveSupport::TimeZone[5.hours + 30.minutes]
    => (GMT+05:30) Chennai

    But if the time zone u specified is not supported, it will return nil.

  • Parsing Time with Time Zone
    When u got the time zone using above methods, `time_zone` for example, using

    pry(main)> time_zone.parse('2014-12-30 17:40')
    => Tue, 30 Dec 2014 17:40:00 IST +05:30

    To parse a string like time.

  • Convert Time Zone


    is the time we want to handle,


    is the target time zone we want to conver


    For example:

    pry(main)> time =
    => Tue, 30 Dec 2014 09:48:06 UTC +00:00
    pry(main)> time.hour
    => 9
    pry(main)> target_time_zone = ActiveSupport::TimeZone[8.hours]
    => (GMT+08:00) Beijing
    pry(main)> converted_time = time.in_time_zone(target_time_zone)
    => Tue, 30 Dec 2014 17:48:06 CST +08:00
    pry(main)> converted_time.hour
    => 17

    For the UTC time zone, the following code:


    is a quick method for converting time into TimeZone ‘UTC’

  • Daylight saving time


    to check if a time is with daylight saving

Link Error of undefined symbol delete[] and new[] in iOS Development with WXAPI


Undefined symbols for architecture x86_64:
  "operator delete[](void*)", referenced from:
      +[WeChatApiUtil EncodeBase64:] in libWeChatSDK.a(WeChatApiUtil.o)
      +[WeChatApiUtil NsDataEncodeBase64:] in libWeChatSDK.a(WeChatApiUtil.o)
      +[WeChatApiUtil DecodeWithBase64:] in libWeChatSDK.a(WeChatApiUtil.o)
      +[WeChatApiUtil DecodeBase64:] in libWeChatSDK.a(WeChatApiUtil.o)
  "operator new[](unsigned long)", referenced from:
      +[WeChatApiUtil EncodeBase64:] in libWeChatSDK.a(WeChatApiUtil.o)
      +[WeChatApiUtil NsDataEncodeBase64:] in libWeChatSDK.a(WeChatApiUtil.o)
      +[WeChatApiUtil DecodeWithBase64:] in libWeChatSDK.a(WeChatApiUtil.o)
      +[WeChatApiUtil DecodeBase64:] in libWeChatSDK.a(WeChatApiUtil.o)
  "___gxx_personality_v0", referenced from:
      Dwarf Exception Unwind Info (__eh_frame) in AppDelegate.o
      Dwarf Exception Unwind Info (__eh_frame) in main.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)


Config ssh access with apache

First, generate the ssh keys and the certificate.

We use a self-signed wildcard certificate here.
Run the following command:

cd /etc/apache2/
mkdir ssl
cd ssl
sudo openssl req -x509 -nodes -days 365 -newkey rsa:2048 -keyout /etc/apache2/ssl/apache.key -out /etc/apache2/ssl/apache.crt

The last command will prompt some filed for you to input.
The most important one is Common Name, we fix this with a wildcard url, for example: *
Then the first part is done.

Second, configure the apache

In the /etc/apache2/sites-available, there are your sites configuration files.
Take as example, the file should be modified to something like this:

 DocumentRoot /somewhere/the/site/at
 ErrorLog /somewhere/the/site/at/logs/error.log
 CustomLog /somewhere/the/site/at/logs/access.log combined
 SSLEngine On
 SSLCertificateFile /etc/apache2/ssl/apache.crt
 SSLCertificateKeyFile /etc/apache2/ssl/apache.key
  SSLRequireSSL On
  SSLVerifyClient optional
  SSLVerifyDepth 1
  SSLOptions +StdEnvVars +StrictRequire

Third, restart your apache

service apache2 restart

If you got something wrong, like SSLEngine not valid, you should enable the model first:

a2enmode ssl

Setup Git Repo on VPS

We can setup our own Git repo on VPS, it’s very easy. After the setup, we can access our repo as:

//clone our repo to local, we use git as username and domain as the server domain(like
git clone git@domain:a_repo.git

The simple steps are as follows:

  1. add user ‘git’ on your host
  2. setup ssh access for your local computer to your host as ‘git’
  3. create and init your repo on your server
  4. access your repo in local computer


add user ‘git’ on your host

ssh login into your host as root, and do the following:

useradd -d /home/git -m git
passwd git

setup ssh access for your local computer to your host as user ‘git’

in your local computer, do the following:

if you have no rsa keys, you need to generate one first:

cd ~/.ssh
ssh-keygen -t rsa 

this will generate id_rsa and in your ~/.ssh directory

if your key name is not id_rsa you need to add your key with:

ssh-add your_custome_name_of_key

with these keys, do the following:

cat | ssh git@domain 'cat >> .ssh/authorized_keys'

then you are able to run ssh git@domain without your password if everything goes well.
if not, check your host with permissions of /home/git, it should belongs to user git.

create your own repo

this is done on your host

ssh git@domain
mkdir your_first_repo.git
cd your_first_repo.git
git --bare init

then your git repo is setup fullly

access your repo on your local computer

you can clone your repo to local using:

git clone git@domain:your_first_repo.git

then all works done. enjoy it.

Or, if you have a repo already exists in your local computer and want to using the repo on your host, just setup the remote and up stream of your local repo, it will works well, as following:

//assume you are already in your local repo directory
git remote add origin git@domain:your_first_repo.git
git push --set-upstream origin master




0 */2 * * * date >> /var/log/date.log



前面5位数,分别代表的是 分钟 小时 日 月 星期几, 然后后面就是条件满足时候运行的命令。
逗号 (‘,’) 分开的值,例如:“1,3,4,7,8”
连词符 (‘-‘) 制定值的范围,例如:“1-6”,意思等同于“1,2,3,4,5,6”
星号 (‘‘) 代表任何可能的值。例如,在“小时域” 里的星号等于是“每一个小时”
斜杠 (‘/’) 代表整除,例如”


Using VCR with WebMock in Rails Rspec Tests

If the application need interaction with another web service, it’s convenience to using VCR with WebMock to test the application, rather than doing the request to another web service every time.


Modify Gemfile

group :test do
  gem 'webmock'
  gem 'vcr'

and don’t forget to run

bundle install

Config VCR

The following code can be placed in the spec_helper.rb

VCR.configure do |c|
  c.allow_http_connections_when_no_cassette = true
  c.cassette_library_dir = 'spec/cassettes' #this specified the directory for placing the record files
  c.hook_into :webmock
  c.default_cassette_options = {
    :record => :once,
    :erb => true,
    :match_requests_on => [:method, :uri, :host, :path, :headers]

Using VCR

Then you can using VCR when write the rspec test like:

describe 'Some api call tests', :vcr => true do
#write normal api call tests here


Sometimes we need to re-record the cassettes, because maybe the request params changed in our app or the response is updated from third-party server.

It’s very easy to do that, just modify your VCR.config block, set record: all instead of :once.

:record => :all

and run your rspec tests related to that cassettes, then the cassettes files will be updated.

And you can specify the matchers per test:

describe 'Something', :vcr => {match_requests_on:[:method, :uri]} do
  # Some tests

The following method can tell whether vcr is recording, it’s very useful in some scenarios:


[Repost] Here Document in Ruby

This is repost from , good post!


Here Document(or HereDoc) is a way to declare String literal in Ruby programming language:

some_text = <<END_OF_STRING
 You can write any text here for your document that's why such
 statement is called - HereDoc

That’s it! Now some_text variable points to the string object containing the text going between END_OF_STRING
As you may know HereDoc isn’t a unique Ruby feature, rather it’s a common construct(with some distinctions) for scripting languages “brewed” in Unix environment.

The terminator

By Ruby convention a variable starting with capital letter is a constant. But that’s not a case for the END_OF_STRING from previous example, because terminator is just a string which parser treats as the end of HereDoc.
Well if a terminator is a string then can i use arbitrary(say put spaces within) string as the terminator like end of string? The answer is – yes you can!
<<heredoc is interpreted same as <<"heredoc" (please note double quotes around latter heredoc).
But explicit notation(with quotes) is a bit more powerful.

String interpolation

By explicitly enclosing terminator with quotes you may have:

a_text = <<"Ruby, please end my HereDoc once you find this terminator string"
Hello world!
Ruby, please end my HereDoc once you find this terminator string


fuzzy_names = <<">>"
foo, baz, bar

Wow, if i can use double quoted string, then probably i can use single quoted string as well:

puts <<'end of string'
end of string

as single quoted strings aren’t interpolated unlike double quoted:

puts <<"end of string"
end of string

Indent modifier

By default HereDoc terminator is expected to be placed on the very beginning of the separate line
By using – on HereDoc declaration, you may indent end terminator arbitrary:

greeting = <<-"here document ends"
                 Hello world
               here document ends

Keep in mind that leading spaces are kept.

Advanced usages

a, b = <<'EOA', <<-EOB
is equal to
a, b = "string_a\n", "string_b\n"

At this point i’m thinking about HereDoc as “placeholder” that gets substituted with the string itself. Why is that important? Because you may then treat HereDoc declaration as the actual string and send messages(call methods):

<<'heredoc'.reverse == "\n!dlrow olleH"
Hello world!

is a true statement!

SOAP Protocol

SOAP – Simple object access protocol, based on the HTTP, using in the information transferring between endpoints on the Internet.
SOAP – 简单对象存取协议,基于HTTP,是一个用来在Internet上传输信息的标准

SOAP package from sender (发送方的例子)

The package from sender in like below:

<?xml version="1.0"?>




The namespaces and the Envelope in the example are forced to be present. the Header is optional.
In the Body, the sender can have what ever it want to be there, but must follow the XML rules.

The response from receiver (接收方的反馈)

<?xml version="1.0"?>

   <m:GetPriceResponse xmlns:m="">


In this manner, the endpoints exchange informations through internet.

Using in Ruby – SOAP4R (Ruby中的gem – SOAP4R)

Reference (参考)

STI of ActiveRecord in Rails

STI, Single Table Inheritance, supported by ActiveRecord in rails to let us build the models’ hierarchy on a single data table.

Model description

For example, we have a User model, and have an Administrator model, which inherit from User. we can build just one table named ‘user’, and make sure there is a column named ‘type’ and of string type in the User table. like below:

mysql>describe 'user';
| Field                    | Type         | Null | Key | Default  | Extra          |
| id                       | int(11)      | NO   | PRI | NULL     | auto_increment |
| type                     | varchar(255) | YES  |     | NULL    |                |
| name                     | varchar(255) | YES  |     | NULL     |                |


then, we can writing following code to have a look of STI:

class User < ActiveRecord::Base
    validates_presence_of :name
class Administrator < Post

just this, and we can verify it in console:

admin = Administrator.create( :name => "admin")
admin.type # "Administrator" # 1


the STI is enabled by default, and so the 'type' in table is likely reserved for STI and we can not using it for other purpose;
and another problem is that if the shared columns are not so much in the model hierarchy, it's a waste using STI, we prefer to setup another table for the child model.
Luckily, we can disable this feature in a table that not using this feature. by doing this:

class User < ActiveRecord::Base
    self.abstract_class = true
    validates_presence_of :name
class Administrator < Post

by doing this, the 'type' columns in User can be used at our will and there must another table for Administrator alone.


The difference from %w to %W in Ruby

Difference between %w and %W

In short, %w act as ', while %W act as "
In long words, %w not convert the #{} clause, but %W do, like the codes below:


irb(main):001:0> foo="hello"
=> "hello"
irb(main):002:0> %W(foo bar baz #{foo})
=> ["foo", "bar", "baz", "hello"]
irb(main):003:0> %w(foo bar baz #{foo})
=> ["foo", "bar", "baz", "\#{foo}"]


Typhoeus : a gem for http requests in rails.


Single request

request =
  method: :post,
  body: "this is a request body",
  params: { field1: "a field" },
  headers: { Accept: "text/html" }

# handle the response as follows
request.on_complete do |response|
  if response.success?
    # hell yeah
  elsif response.timed_out?
    # aw hell no
    log("got a time out")
  elsif response.code == 0
    # Could not get an http response, something's wrong.
    # Received a non-successful http response.
    log("HTTP request failed: " + response.code.to_s)

# this will actually execute the request

Parallel requests
Typhoeus doing well in the parallel requests, just doing this:

hydra = Typhoeus::Hydra.hydra

first_request ="")
first_request.on_complete do |response|
  third_request =
  hydra.queue third_request
second_request ="")

hydra.queue first_request
hydra.queue second_request
# this is a blocking call that returns once all requests are complete

For more information, looking:
Typhoeus on Github

How to customize screen resolution in windows7 with ATI graphics card

Recently, I brought a Dell U2713HM display, with resolution of 2560 * 1440. And my current computer have a HD6800 ATI card.

Then when I connect display with DVI cable, it turns out that the highest resolution I can set is 1920 * 1200 in the windows settings. That’s sucks.

So after tried a lot of solutions, there is one works!

first, unlock the pixel clock of grahpics card, using:

second, specify your custom resolution using CRU:

Great thanks to the authors of those softwares!!