Ruby己死?NodeJS能否取代Ruby?

ourjs發表於2013-12-27

  我最近一直在使用nodejs,我跟我的小夥伴們一直在討論nodejs是否會最終取代Ruby。我認為評價一門語言的是否流行最重要的指標就是使用這門語言和框架開始新的專案的數量。

  我認為一張基於gems的釋出專案數量的圖表可以很好的解決我的問題。rubygems首頁上的就有最新的流行資料顯示,但是我對最近的一些資料非常地感興趣。我認為如果開發者向gems(不同版本)貢獻的程式碼緩慢下降,那麼這就表明了這門語言的就不怎麼流行了。

  拿資料說話

  在簡單的搜尋之後,我無法找到適合的資料去做成一張圖表。不過我抓取了一些網站並發現一些有意思的資料。我使用的是nodejs cheerio庫。gem的可執行檔案給了我們一張清單,它告訴我們都有誰在跑gem。幸運的是每一個gem的主頁都是一個很漂亮的地址(url),比如:Rails的主頁是:http://rubygems.org/gems/rails

  下面是我抓取用的原始碼:

var request = require('request'),
    cheerio = require('cheerio'),
    bytes = require('bytes'),
    sys = require('sys'),
    fs = require('fs'),
    exec = require('child_process').exec;

console.log('program begin: ' + new Date());
fs.openSync('out.csv', 'w');

exec("gem list --remote", { maxBuffer: 20000*1024 }, processGems);

function processGems(error, stdout, stderr){
    var gems = stdout.split("\n");
    console.info('total gems parsed: ' + gems.length);
    gems.forEach(function(gem){
        gem = gem.substring(0, gem.indexOf(' '));
        console.info('crawling gem: ' + gem);
        request({
            uri: 'https://rubygems.org/gems/' + gem,
        }, getContent);
    });
}

function parseSize(size){
    size = size.replace(' ', '');
    size = size.replace(/\)|\(/g, '');
    size = size.toLowerCase();
    try{
        size = bytes(size);
    }
    catch(e){
        console.error('unable to parse :' + size);
    }
    return size;
}

function escape(s){
    if (s.indexOf('"') != -1) {
        s = s.replace(/"/g, '""');
    }
    if (s.match(/"|,/)) {
        s = '"' + s + '"';
    }
    return s;
}

function getContent(error, response, body){
    if (error && response.statusCode != 200) {
        console.error(error);
        console.error(response);
        return;
    }
    console.info(response.request.href + ' complete, status: ' + response.statusCode);

    var $ = cheerio.load(body),
        gem = $('div.title h2 a').text(),
        latest = $('div.versions ol li').last(),
        version = $(latest).children('a').text(),
        date = $(latest).children('small').text(),
        size = $(latest).children('span.size').text(),
        line;
    line = escape(gem) + ',' +
        escape(version) + ',' +
        escape(date) + ',' +
        parseSize(size) + '\n';
    fs.appendFile('out.csv', line);
}

  整理資料

  結果檔案有2.7Mb,可以在這裡下載,這不是可以做成圖表的資料來源。我希望我的圖表y軸顯示當天釋出程式的數量,x軸顯示釋出日期。下面的一段nodejs可以整理之前的csv(資料)檔案成我想要的格式。

var __ = require('lodash'),
    moment = require('moment'),
    csv = require('csv'),
    fs = require('fs');
    
fs.openSync('releasedate.csv', 'w');

csv()
    .from.path(__dirname+'/gems.csv', { delimiter: ',', escape: '"' })
    .to.array( function(data){
        var csv = '';
        var grouped = __.groupBy(data, function(gem) {
            return gem[2];
        });
        
        var array = []
        for(var gem in grouped) {
            array.push({
                date: escape(gem),
                unixtime: moment(gem, 'MMM D, YYYY').valueOf(),
                released: grouped[gem].length
            });
        }
        arraySorted = __.sortBy(array, 'unixtime');
        arraySorted.forEach(function(gem){
            csv += gem.date + ',' + gem.released + '\n'; 
        });
        fs.appendFile('releasedate.csv', csv);
    } );

function escape(s){
    if (s.indexOf('"') != -1) {
        s = s.replace(/"/g, '""');
    }
    if (s.match(/"|,/)) {
        s = '"' + s + '"';
    }
    return s;
}

  用R繪製圖表

  非常完美。現在開始繪圖了。我剛開始想用Excel,但是我發現我只能在一張圖上面建立255個點。這對於65K的資料檔案來說是遠遠不夠的,所以我最終使用了R。下面的兩行程式碼解釋了我為什麼喜歡用R的原因:

data<-read.csv('releasedate.csv')
plot(zoo(data$Released,as.Date(data$Date,"%m/%d/%y")),xlab="Release Date",ylab="Releases",main="RubyGems Release Date Trend")

  最終結果是我期望看到的一條曲線:

  起我初驚呆了。這結果跟我之前預想的不太一樣,這張圖表顯示越來越多的開發者正在使用gems,我從這張圖表上面得到了三個結論:

  1.Rubby的meetup組織有一大群虔誠的追隨者,並且有很強的領導力。

  2.網上有非常多的關於Ruby的學習資源。

  3.使用Rails建立網站非常非常容易。

  原文 jmoses.co