Step By Step of Creating a Ruby Gem

2016 年 11 月 9 日 Develop, ruby on rails No comments , , ,

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

2016 年 9 月 15 日 Develop, iOS No comments , , , , ,

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!

Understand the ios app provisioning

2016 年 9 月 3 日 Develop, iOS No comments , , ,


This graph is abstracted from this great article, described the relations of those entities very clear.


Making Sense Of iOS Provisioning, great article!
iOS Code Signing: Under The Hood

[Repost] The definition of nil, empty, blank and present in ruby on rails

2016 年 8 月 31 日 Develop, ruby on rails No comments , , , , , , ,

rails defs for nil empty present blank

Stop mac from automatically pairing bluetooth audio devices

2016 年 8 月 29 日 Develop, 系统维护 No comments , , ,

In terminal, run

sudo defaults write /Library/Preferences/ DontPageAudioDevices 1

Faster Dock in Mac OSX

2016 年 7 月 4 日 Develop, 系统维护 No comments , ,

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

2016 年 5 月 29 日 C++, Develop, 算法 No comments , ,


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)

2016 年 5 月 28 日 C++, Develop, 算法 No comments , ,


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

2016 年 5 月 11 日 C++, Develop, 算法 No comments , ,


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

2016 年 5 月 9 日 Develop, 系统维护 No comments , , ,

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

2016 年 5 月 8 日 Develop, 算法 No comments , , ,


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

2016 年 5 月 7 日 Develop, 算法 No comments , ,

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

2016 年 5 月 6 日 Develop, 算法 2 comments , ,

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

2016 年 5 月 5 日 C#, C++, Develop No comments , , , , ,

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.


2016 年 5 月 4 日 Develop, Site No comments , ,


Attacker embedded your pages into another page in a <frame> tag, and there is a transparent layer on top of your button or link. And it will receive the user click instead of your button. Then navigate user to some other places.


Using <X-Frame-Options> ;
Using Content-Security-Policy


Distribution Items Equally in View with Auto-Layout in iOS

2016 年 5 月 3 日 Develop, iOS No comments , ,

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

2016 年 5 月 2 日 Develop, 系统维护 No comments , , , , ,

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

Modify $PATH in Docker

2016 年 3 月 25 日 Develop, 系统维护 No comments , ,

Tried many methods but only this works:
Use docker file

FROM whichDockerImageYouWantToModify
ENV PATH $PATH:/some/new/path/you/want/add

Mysql Error: Table ‘performance_schema.session_variables’ doesn’t exist [Solved]

2016 年 2 月 10 日 Develop, mysql, 系统维护 No comments , , ,

Got a mysql error:

Table 'performance_schema.session_variables' doesn't exist

Fixing is easy, just execute command in console:

mysql_upgrade -u root -p --force

SSH Timeout and Non-password Login

2015 年 6 月 29 日 Develop, 系统维护 No comments

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

2015 年 2 月 13 日 Develop, ruby on rails No comments , , ,

  • 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

2015 年 2 月 6 日 Develop, 系统维护 No comments , , , , , , ,

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

2015 年 2 月 5 日 Develop, ruby on rails No comments , , ,

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

2015 年 1 月 6 日 Develop 2 comments ,


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

2014 年 12 月 30 日 Develop, ruby on rails No comments , , ,

  • 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

2014 年 11 月 30 日 Develop, iOS 1 comment , , ,


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)


Hide ‘Others’ on the login screen of Mac OS X

2014 年 10 月 12 日 系统维护 No comments

Run following command in Terminal:

sudo defaults write /Library/Preferences/ HiddenUsersList -array-add user_1 user_2 user_3 user_4

Learnt from

Config ssh access with apache

2014 年 7 月 10 日 Develop, 系统维护 1 comment , ,

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


2014 年 5 月 16 日 曲谱 No comments , ,









Setup Git Repo on VPS

2014 年 5 月 5 日 Develop, Site No comments , ,

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

acts_as_paranoid Gem in Rails

2014 年 4 月 24 日 Develop, ruby on rails No comments , ,

This gem is used for soft delete models, with this gem, you can delete your data, but recovery later.


2014 年 4 月 23 日 曲谱 No comments , ,







Rails Gem CanCan

2014 年 4 月 23 日 Develop, ruby on rails No comments , ,



2014 年 4 月 21 日 Life No comments , ,


徽位 音程



2014 年 3 月 15 日 Music, 曲谱 6 comments , ,





2014 年 3 月 3 日 Life, Music, 曲谱 2 comments , ,






笑傲江湖古琴曲谱 笑傲江湖古琴曲谱






2014 年 2 月 25 日 Life, Music No comments , ,



古琴基本指法练习之七 – 左手按音和吟

2014 年 2 月 16 日 Life, Music No comments , , , ,



2014 年 2 月 15 日 Life, Music No comments , ,