公開が遅くなりましたが、、RubyMotion Advent Calendar 2013の14日目の記事です。
RubyMotionの初心者の僕が、ごく一般的なHTTPのAPI WrapperのRubyGemをなんとかしてRubyMotionのGemに書き換えたという話を書きたいと思います。
(なのでツッコミどころ満載だと思いますのでご指摘ございましたらよろしくお願いいたします。><)
今回書き換えた対象の Gem は翻訳クラウドソーシングサービス Gengo のAPIをの Wrapper を提供しているこちらのクライアントを使用しました。
#RubyMotion gemの雛形作成
RubyMotionのcreateコマンドからgem作成用のtemplateを指定して作成することができます。
motion create template=gem gengo-motion
lib/projectディレクトリ配下にソースを移動
RubyMotionのgemはデフォルトでlib/project配下のrbファイルを読み込むようなので、ソースをとりあえずまるっと移動します。
lib_dir_path = File.dirname(File.expand_path(__FILE__))
Motion::Project::App.setup do |app|
app.files.unshift(Dir.glob(File.join(lib_dir_path, "project/**/*.rb")))
end
必要なライブラリの書き換え
有名な話ですが、RubyMotionはrequreが使えないので、Rubyの多くのライブラリが使えません。これは大変です。でも一つ一つRubyMotionで使えるライブラリに置き換えていきたいと思います。
‘openssl’の書き換え
OpenSSLライブラリが使えないのでhmacの暗号化を行うために、CocoaPodsで公開されているIGDigestというライブラリを代用しました。
cocoapodsのライブラリを使用するには、gemspecファイルに以下を記述し、
spec.add_dependency 'motion-cocoapods', '~> 1.4.0'
spec.add_dependency 'cocoapods'
Rakefile内で以下のように宣言します。
Motion::Project::App.setup do |app|
# Use `rake config' to see complete project settings.
app.name = 'gengo-motion'
app.pods do
pod 'IGDigest'
end
app.frameworks << 'Security'
end
こんな感じで書き換えができます。
# Creates an HMAC::SHA1 signature, signing the timestamp with the private key.
def signature_of(ts)
# OpenSSL::HMAC.hexdigest 'sha1', @opts[:private_key], ts
ts.SHA1HMACWithKey(@opts[:private_key])
end
‘net/http’の書き換え
HTTPのWrapperはbubble-wrapなどの便利ライブラリがRubyMotion用に公開されていますが、headerなどをゴニョゴニョやるにはNSURLRequestを直接呼び出す方が都合が良さそうなので、naoya_itoさんのHBFav2のソースをパクって参考にさせていただいて書き換えました。
# http = Net::HTTP.start(@api_host, 80)
# resp = http.request(req)
request = NSURLRequest.alloc.initWithURL(url.nsurl, cachePolicy:@cache_policy, timeoutInterval:@timeout)
‘cgi’の書き換え
url escape処理はsugarcubeのNSString拡張を用いて書き換えました。
sugarcubeはいろんな便利ライブラリが詰まっていてRubyMotionでの開発で重宝しそうです。
sugarcubeのstring拡張を使用するにはgemspecファイルに以下を記述し
spec.add_dependency 'sugarcube'
Rakefileに以下を記述しました。
require 'sugarcube-attributedstring'
こんか感じで書き換え可能です。
# Use CGI escape to escape a string
def urlencode(string)
# CGI::escape(string)
string.escape_url
end
specの記述方法変更
RubyのspecにはあるけどRubyMotionのspecにはないメソッドがいくつかあったのでそれを書き換えました。
should_notとraise_errorは使えなかったので以下のように、
it "should be successful" do
lambda do
@gengo_client.getAccountBalance
# end.should_not raise_error
end.should.not == :error
end
be_an_instance_ofは使えなかったので、class.shouldに書き換えて検証してます。
it "should have a credits field as a string" do
credits = @useful_response_body['credits']
# credits.should be_an_instance_of(String)
credits.class.should == String
end
gemの公開
最後にgemの公開方法ですが、通常のRuby Gemと同じです。
gem build gengo-motion.gemspec
gem push gengo-motion-1.0.gem
作成したRubyMotionのgemのソースはこちらになります。
https://github.com/toshipon/gengo-motion
※ まだ開発途中で、一部のAPIが動かなかったり、specを完全に移行できていません。もし興味がありましたら是非forkお待ちしております!
参考にさせていただいたサイト