2015年第6周技术小结
快速生成 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 作了很好的 讲述。文中写到的下面两个地方让我感觉收获颇多。
-
使用一个 Chrome 的插件 Postman 测试 API;
-
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 。