快速生成 Excel 报表

psql -h localhost -p 1111 -d adb -U auser -F \| --no-align -f a_report.sql.private | ./excel.rb.private

或者

psql -h localhost -p 1111 -d adb -U auser -F \| --no-align -f a_report.sql.private > reports.csv
cat reports.csv | ./excel.rb.private

excel.rb.private 内容,


#!/usr/bin/env ruby

require 'axlsx'

p = Axlsx::Package.new
book = p.workbook

book.add_worksheet(name: 'reports') do |sheet|
  ARGF.lines do |line|
    if line =~ /rows\)/
      puts line
    else
      sheet.add_row line.split('|')
    end
  end
end

p.serialize 'reports.xlsx'

写 gem

传统的方法写 gem 可以参考此篇文章: http://guides.rubygems.org/make-your-own-gem/

现在使用 bundle 去写 gem 更方便,

  bundle gem your-new-gem-name
your-new-gem-name
├── Gemfile
├── LICENSE.txt
├── README.md
├── Rakefile
├── lib
│   └── your
│       └── new
│           └── gem
│               ├── name
│               │   └── version.rb
│               └── name.rb
└── your-new-gem-name.gemspec

一个完整的 gem 的骨架就有了。

ruby 新技能


  def map_send *args
    map{|obj| obj.send *args }
  end

  class Array
    def map_send *args
      map{|obj| obj.send *args }
    end
  end
  
  ['a12', 'b12', 'c45'].map_send :gsub, /\d+/, '' # ['a', 'b', 'c']
  

Rails API Guide

这篇文章 The Rails API Mini Guide 对怎么使用 Rails 构建 API 作了很好的 讲述。文中写到的下面两个地方让我感觉收获颇多。

  1. 使用一个 Chrome 的插件 Postman 测试 API;

  2. Routing 和 Versioning 代码,

namespace :api do  
  namespace :v1 do
    resources :stories
  end
end  
module API  
  module V1
    class StoriesController < ApplicationController
    end
  end
end  

JavaScript 编程实践

将事件绑定到一组 DOM 元素中

如果用 jQuery 来做是这样的,

$('.dom-node-list').on('click', function(){
  ...
})

You Don’t Need jQuery! 这篇文章蛊惑,我决定不使用 jQuery, 最初我使用下面的代码来实现 DOM 元素的事件绑定,

var dom_eles = document.querySelectorAll('.dom-node-list');
for(var i = 0; i < dom_eles.length; i++){
  dom_eles[i].addEventListener('click', function(){
   ...
  })
}

考虑到对以前对浏览器对兼容性,加入一个 registerEventHandler 方法,

var registerEventHandler = function(target, type, callback) {
  if(target.addEventListener){
	target.addEventListener(type, callback);
  } else {
	target.attachEvent('on' + type, callback);
  }
};

var dom_eles = document.querySelectorAll('.dom-node-list');
for(var i = 0; i < dom_eles.length; i++){
  registerEventHandler(dom_eles[i], 'click', function(){
    ...
  })
}

和 jQuery 对比下,感觉 jQuery 的 api 非常优雅,但是我们做些设计,也能实现和 jQuery 类似的 api,至少在形式上与 jQuery 趋近,

 var dom = {
 
   registerEventHandler: function(target, type, callback) {
     if(target.addEventListener){
       target.addEventListener(type, callback);
     } else {
	   target.attachEvent('on' + type, callback);
	 }
   },
	  
   $: function(ele){
     var ext_obj = {};
	 ext_obj.on = function(type, callback){
	   if(ele[0]){
	     for(var i=0; i < ele.length; i++){
		   this.registerEventHandler(ele[i], type, callback);
		 }
	   } else {
         this.registerEventHandler(ele, type, callback);
	   }
	 }

     return ext_obj
   }
 }

然后我们可以这样使用 dom.$,

  var dom_eles = document.querySelectorAll('.dom-node-list');
  dom.$(dome_eles).on('click', function(){
    ...
  })

创建能够访问执行环境中的变量的匿名函数

首先看看下面的代码会有什么问题,


  var ajaxRequest = function(query, callback){
	var url = encodeURI(set_position_url + '?' + query)
	var xhr = new XMLHttpRequest();
	
	xhr.open('GET', url);
	xhr.setRequestHeader('Content-Type', 'application/json');
	xhr.onload = callback;
	xhr.send();
  };
  
  ajaxRequest('a=1&b=2', function(){
    if(xhr.status === 200){
	  alert('success');
	}
  });

上面的代码执行时,浏览器会抱怨 xhr 在 callback 中未定义。

解决方法1:


  var ajaxRequest = function(query, callback){
	var url = encodeURI(set_position_url + '?' + query)
	var xhr = new XMLHttpRequest();
	
	xhr.open('GET', url);
	xhr.setRequestHeader('Content-Type', 'application/json');
	xhr.onload = callback(xhr); // 这里传入了 xhr 作为参数
	xhr.send();
  };


  ajaxRequest('a=1&b=2', function(xhr){
    return function(){
	  if(xhr.status === 200){
	    alert('success');
	  }
	}
  });

解决方法2:


  var ajaxRequest = function(query, callback){
	var url = encodeURI(set_position_url + '?' + query)
	var xhr = new XMLHttpRequest();
	// 在这里将 xhr 作为参数传给了 callback
	var createCallback = function(xhr){
	  return callback(xhr);
	}
	
	xhr.open('GET', url);
	xhr.setRequestHeader('Content-Type', 'application/json');
	xhr.onload = createCallback(xhr); # 这里传入了 xhr 作为参数
	xhr.send();
  };

  ajaxRequest('a=1&b=2', function(xhr){
    if(xhr.status === 200){
      alert('success');
    }
  });

显然方法2 比方法1 要优雅些。在这里我们可以看到 callback 方法能够很方便地访问到 ajaxRequest 方法里的局部变量 xhr 。