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 rubygems.org, 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
accent_to_ascii
├── CODE_OF_CONDUCT.md
├── Gemfile
├── LICENSE.txt
├── README.md
├── 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

accent_to_ascii.gemspec

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

lib/accent_to_ascii/version.rb

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

module AccentToAscii
  VERSION = "0.1.0"
end

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.

spec/accent_to_ascii_spec.rb

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

lib/accent_to_ascii.rb

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'

Gem::Specification.new do |spec|
  spec.name          = "accent_to_ascii"
  spec.version       = AccentToAscii::VERSION
  spec.authors       = ["uniEagle"]
  spec.email         = ["unieagle@gmail.com"]

  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      = "https://github.com/unieagle/accent_to_ascii"
  spec.license       = "MIT"

  spec.files         = `git ls-files -z`.split("\x0").reject do |f|
    f.match(%r{^(test|spec|features)/})
  end
  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"
end

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
  end

  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"
  end

  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" }
  end

  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"
    end
  end
end

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
  ACCENTS_MAPPING = {
    '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) }
    end
  end

  private

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

end

class String
  def accent_to_ascii(string = String.new(self))
    AccentToAscii.accent_to_ascii(string)
  end

  def accent_to_ascii!
    accent_to_ascii(self)
  end
end

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

Then the tests are green now:

$ rake
AccentToAscii
  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"
  accent_to_ascii!
    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 RubyGems.org, 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 RubyGems.org.

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

References

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

Official Guide of Publish Gems onto RubyGems.org

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:
https://www.dropbox.com/s/xdfycqlw4e1r6bt/someapp.ipa?dl=0

Replace www.dropbox.com to dl.dropboxusercontent.com to modify it as:

https://dl.dropboxusercontent.com/s/xdfycqlw4e1r6bt/someapp.ipa?dl=0
  1. Create manifest file as:
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
    <key>items</key>
    <array>
        <dict>
            <key>assets</key>
            <array>
                <dict>
                    <key>kind</key>
                    <string>software-package</string>
                    <key>url</key>
                    <string>https://dl.dropboxusercontent.com/s/xdfycqlw4e1r6bt/someapp.ipa?dl=0</string>
                </dict>
                <dict>
                    <key>kind</key>
                    <string>display-image</string>
                    <key>url</key>
                    <string>https://dl.dropboxusercontent.com/s/0ef4etggy0aw8sa/image.png</string>
                </dict>
                <dict>
                    <key>kind</key>
                    <string>full-size-image</string>
                    <key>url</key>
                    <string>https://dl.dropboxusercontent.com/s/0ef4etggy0aw8sa/image.png</string>
                </dict>
            </array>
            <key>metadata</key>
            <dict>
                <key>bundle-identifier</key>
                <string>YOUR APP BUNDLE IDENTIFIER</string>
                <key>bundle-version</key>
                <string>1.0</string>
                <key>kind</key>
                <string>software</string>
                <key>title</key>
                <string>YOUR APP NAME</string>
            </dict>
        </dict>
    </array>
</dict>
</plist>

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:

https://www.dropbox.com/s/imqvkwe2y395aua/manifest.plist?dl=0

To

https://dl.dropboxusercontent.com/s/imqvkwe2y395aua/manifest.plist

Please notice the postfix ?dl=0 also removed.

  1. Create a install html page using this manifest link:
<h1>Install</h1>
<a href="itms-services://?action=download-manifest&url=https://dl.dropboxusercontent.com/s/imqvkwe2y395aua/manifest.plist">
  Install YOUR APP NAME
</a>

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 , , ,

App-To-Profile-Mapping1

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

References

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/com.apple.Bluetooth.plist DontPageAudioDevices 1

Faster Dock in Mac OSX

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

This makes the animation faster

defaults write com.apple.dock autohide-time-modifier -float 0.15;killall Dock
//restore:
defaults delete com.apple.dock autohide-time-modifier;killall Dock

This makes the delay of show/hide Dock faster:

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

Reference:
http://apple.stackexchange.com/questions/33600/how-can-i-make-auto-hide-show-for-the-dock-faster

Leetcode: Palindrome Number

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

Problem

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

Analyze

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.

Code

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

class Solution {
public:
    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 {
public:
    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 , ,

Problem

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

Analyze

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 -.

Code

class Solution {
public:
    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;
                continue;
            }
            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 , ,

Question

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.

Analyze

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.

Code

C++ code

class Solution {
public:
    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;
            }
            dict[nums[i]]=i;
        }
        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.

Usage

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:

RemapKey.zip from unieagle.net

Leetcode: Integer to Roman

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

Question:

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

Analyze:

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.

Code

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;
            }
        } 
        else
        {
            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.

Question

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

Analyze

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

Code

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
            break
        end
        x /= 10
    end
    y * sign
end

C++ Code

class Solution {
public:
    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.

Question

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
A P L S I I G
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".

Analyze

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.

Code

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
            in_group_position
        else
            num_rows - 1 - (in_group_position - num_rows)
        end
        result[target_row] ||= ""
        result[target_row] << s[i]
    end

    result
end

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.

ClickJacking

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

Example

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.

Solution

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

Reference

https://en.wikipedia.org/wiki/Clickjacking

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.

Timeout

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/id_rsa.pub | ssh user@123.45.56.78 "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

References

https://docs.oseems.com/general/application/ssh/disable-timeout
https://www.digitalocean.com/community/tutorials/how-to-set-up-ssh-keys–2

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:
    https://hackhands.com/format-datetime-ruby/

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
/dev/disk0
   #:                       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
/dev/disk1
   #:                       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.

Note
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.

Reference
http://www.macx.cn/thread-2078747-1-1.html

[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/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/libxml2
Fetching: nokogiri-1.6.1.gem (100%)
Building native extensions with: '--use-system-libraries=true --with-xml2-include=/Applications/Xcode.app/Contents/Developer/Platforms/MacOSX.platform/Developer/SDKs/MacOSX10.10.sdk/usr/include/libxml2'
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 ,

Intro

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.

Install

Follow the guide on SPF VIM SITE

OR just run the following command in your terminal:

curl http://j.mp/spf13-vim3 -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
    Use

    ActiveSupport::TimeZone.all.each{|tz| puts "#{tz.formatted_offset}, #{tz.name}"};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

    ActiveSupport::TimeZone.new('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
    Let

    time

    is the time we want to handle,

    target_time_zone

    is the target time zone we want to conver
    Using

    time.in_time_zone(target_time_zone) 

    For example:

    pry(main)> time = Time.zone.now
    => 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:

    time.utc

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

  • Daylight saving time
    Using

    time.dst?
    

    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 , , ,

和微信Api对接的时候遇到这个问题:

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)

解决方法就是添加libc++.dylib

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/com.apple.loginwindow HiddenUsersList -array-add user_1 user_2 user_3 user_4

Learnt from http://jamauai.com/2013/02/28/how-to-remove-other-account-at-login-screen/

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: *.unieagle.net
Then the first part is done.

Second, configure the apache

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


 ServerAdmin someemail@somedomain.com
 ServerName www.somedomain.com
 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 , ,

入门曲子,学学。

这个版本曲谱简洁,五线谱,就一张:

秋风词

秋风词

另一个曲谱,简谱,看起来挺长的:

秋风词

秋风词2

秋风词3
秋风词

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 unieagle.net).
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

Details:

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 id_rsa.pub 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 id_rsa.pub | 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 , ,

https://github.com/goncalossilva/acts_as_paranoid

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 , ,

CanCan https://github.com/ryanb/cancan
用来处理用户权限,可以制定规则来指示用户current_user的访问权限。
(先挖坑,以后填)

古琴音阶分布

2014 年 4 月 21 日 Life No comments , ,

要做到看到简谱或者五线谱能弹出来,必须知道每个按音的分布,今天从按音图出发总结了一些规律,很简单的几条

徽位 音程
散音
全音
十三徽
半音
十二徽
半音
十徽八分
半音
十徽
全音
九徽
半音
八徽五分
半音
七徽九分
半音
七徽六分
半音
七徽三分
半音
七徽
半音
六徽七分
半音
六徽四分
半音
六徽二分
半音
六徽
半音
五徽六分
全音
五徽
半音
四徽八分
半音
四徽六分
半音
四徽四分
半音
四徽二分
半音
四徽
半音
三徽八分
半音
三徽四分
半音
三徽二分
半音
三徽
半音
二徽六分
全音
二徽
半音
一徽八分
半音
一徽六分
半音
一徽四分
半音
一徽二分
半音
一徽

远端从散音到七徽,是一个八度音阶,正好12个半音。
然后从七徽到四徽,是第二个八度音阶,也是12个半音。
最后从四徽到一徽,是第三个八度音阶,也是12个半音。

《酒狂》古琴曲谱

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

《酒狂》曲子挺好听,但是真快··
第三行开始把历看成劈了,怎么弹都不顺手···

酒狂


酒狂2
酒狂

《笑傲江湖》古琴曲谱

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

笑傲江湖古琴曲谱,吕颂贤版

笑傲江湖1

第二行和第三行中第二小节的名指九徽挑六上七九,左手改成中指比较顺手

第四行最后一个音,大七六挑七和大七九挑六可以一起用左手大指按住,这样音就不会断,而且也省去了过弦的麻烦

笑傲江湖2

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

这是用GarageBand弄出来的mp3,钢琴的,可以听一听节奏。省去了第二页开始那两段泛音的,和第一段很像。

笑傲江湖(上面不能播放的话可以下载下来听)

录了一次

笑傲江湖录音(上面不能播放的话可以下载下来听)

古琴基本指法练习之八

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

左右手一起的简单练习。

古琴基本练习之八

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

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

左手大指和无名指按音练习,还有吟。
古琴基本练习之七

古琴基本指法练习之六

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

第一个比较有旋律的练习
古琴基本练习之六-1
古琴基本练习之六-2