Ruby 與 Nodejs 介接:Schmooze(或其他語言介接)


#1

大概就是工作上的需求,有個橢圓曲線演算法,別人只有實作在 JavaScript,該曲線很偏門,連 OpenSSL 都沒實作,轉 Ruby 曠日費時,又不能不幹,所以最好的方式還是用它原本的東西對唄?

其實轉另外一個語言只需要知道 stdin / stdout / stderr 即可,不知道的人可以去研究一下,之後你就會了解為何高手都在 linux 下用 pipe 就可以解決所有的事情 … 其實就是一直過水的意思就是

所以我可以把另外一個語言封裝成最小的程式,然後把對方 call 成 subprocess,東西丟給它就用 stdin,輸出就是 stdout,出事多接 stderr,而選擇要不要用 non-blocking 的 pipeline 方式處理,這大概就是這個 gem 的製法

以下為實際 demo

$ gem i schmooze
$ mkdir node_wrapper

建立兩個檔案

[[%demo%/node_wrapper/package.json]]

{
  "name": "node_wrapper",
  "dependencies": {
    "base58": "^2.0.1"
  }
}

[[%demo%/main_processor.rb]]

require 'schmooze'

module MainProcessor
  class NodeWapper < Schmooze::Base
    dependencies base58: 'base58'
    method :node_base58 , %Q%
      function(ruby_input){
        return base58.int_to_base58(ruby_input);
      }
    %
  end
  def self.initialize
    @@node_wrapper = NodeWapper.new("#{__dir__}/node_wrapper")
  end
  def self.node_base58(input)
    return @@node_wrapper.node_base58(input)
  end
end
MainProcessor.initialize
puts MainProcessor.node_base58(1234567890)

之後記得要安裝 npm package,然後順便執行測試

$ cd %demo%/node_wrapper
$ npm install
$ cd ..
$ ruby main_processor.rb
#=> 2T6u2h

打完收工,其中應該解釋一行即可

# Ruby 的這行全等於
dependencies base58: 'base58'

// JavaScript 的這行
var base58 = require('base58');

不信?code 在這邊哈哈

所以在 anonymous function 內自然可以用 base58 這個物件就是,然而總體流程簡化一下,大概是下面這樣

_
  
Ruby => Open3 => Nodejs => Open3 => Ruby

Ruby <=(js: JSON.stringify() , ruby : JSON.parse(json))=<stdout<=< [[open3]] >=>stdin>=(ruby : obj.to_json , js : JSON.parse(json))=> Nodejs
 
_

所以你應該可以寫完任何的東西才是,事實上很多 gem 也都這樣做的,學到這招應該就可以到處偷東西來用才是,以上 : )

PS : ruby 下已經有 base58 了,這邊只是拿來做最小 demo 用的而已哩