Ruby の http ライブラリの通信を表示する http-dump を作った
Ruby 上で http を叩いた通信見たい時に、毎回同じ事をやってるので抽象化して http-dump というライブラリを作った。
$ gem install http-dump
require 'net/http' require 'uri' require 'http-dump' HTTPDump.dump { Net::HTTP.get(URI('http://example.com')) }
と http でやりとりしてるコードを block で囲むと、以下のように出力される。
> GET http://example.com/ with headers {'Accept'=>'*/*', 'Accept-Encoding'=>'gzip;q=1.0,deflate;q=0.6,identity;q=0.3', 'Host'=>'example.com', 'User-Agent'=>'Ruby'} < 200 OK < Accept-Ranges: bytes < Cache-Control: max-age=604800 < Content-Type: text/html < Date: Fri, 03 Jan 2014 13:42:51 GMT < Etag: "359670651" < Expires: Fri, 10 Jan 2014 13:42:51 GMT < Last-Modified: Fri, 09 Aug 2013 23:54:35 GMT < Server: ECS (sjc/4FB4) < X-Cache: HIT < X-Ec-Custom-Error: 1 < Content-Length: 1270 < <!doctype html> <html> <head> <title>Example Domain</title> ... more ...
enable! / disable! で全体的に有効・無効を切り替えられる。
require 'open-uri' require 'http-dump' HTTPDump.enable! open('http://example.com').read HTTPDump.disable!
Rails からなら
group :development do gem 'http-dump', require: ENV['HTTP_DUMP_ENABLE'] ? 'http-dump/enable' : 'http-dump' end
を Gemfile に追加。
HTTP_DUMP_ENABLE=1 bundle exec rails s
で Rails アプリ内部から叩いている http のやりとりを表示、とかに使える。
サポートしてる http のライブラリは net/http ベースの物からその他 WebMock で使える物すべて。http-dump の内部実装は全くたいしたことはやって無くて、WebMock の機能にのってるだけです。
どうぞご利用下さい。
Rubyistokei for iOS を RubyMotion で作った話
この投稿は RubyMotion Advent Calendar 2013 の23日目の記事です。
最近 iPhone に買い換えて、初めて iPhone をメイン端末にしてみたので iOS アプリを何か作ってみよう、と思い最初は無難に Xcode + Objective-C で書いていたんだけど、そういえば RubyMotion でも iOS アプリ作れるんだっけ、どんな感じなんだろうと思って Rubyist がみんな大好き*1 Rubyistokei の iOS 版を作ってみた。
Rubyistokei は
- 画像の表示
- ネットワークでのデータ取得
- github 上に表示元のメタデータが上がってるため、それを取得し利用する
- レイアウトの構築
- タイマーの利用
- 時計なんで
あたりの実装が必要で、最初の題材としては簡単すぎずも無く、難しすぎずも無くちょうど良い感じでした。
というわけで作ってみたんだけど、コードはほぼ app_delegate.rb に。ネットワークやりとりして Rubyist オブジェクトを返す実装のみ rubyist.rb へ。本当はもっときれいな抽象化と、適切なファイル分離を行うんだろうけど、RubyMotion 自体はもちろん、Cocoa フレームワークや UIKit も理解してないため、1ファイルで試行錯誤できた方が楽だったので、ほぼ1ファイルで実装。きれいな実装では無いので、参考にはあんまりならないと思います。
- https://github.com/hotchpotch/rubyistokei-ios-motion/blob/master/app/app_delegate.rb
- https://github.com/hotchpotch/rubyistokei-ios-motion/blob/master/app/rubyist.rb
また SugarCube 等の RubyMotion で Ruby らしく書けるライブラリは、理解が薄い時から高レベルのラッパーを使ってしまうと、挙動の理解ができなくなってしまうので、意図的に使わずに。使ったのは BubbleWrap の HTTP と String#to_color ぐらいかな。
AppStore に申請してリリース
作ったからには AppStore に申請してリリースする気満々だったんだけど、レビューで落とされたヨ…。理由は、シンプルすぎる時計アプリだから、もっとユーザ価値を考えて!とのことでした。まわりの iOS 開発者に聞いてみたところ、これぐらいのアプリでも落とされたりすることもあるんだね、とのことだったので、運が良ければ通るし、運が悪ければ落とされる感でした。
RubyMotion で開発してみて
開発してみて、意外とつまずくところが少なかったなぁ、という印象。RubyMotion だからハマった、というところはほぼ無くて、だいたい自分が理解してない iOS フレームワークの部分だった。
RubyMotion JP など日本語のチュートリアルドキュメントも充実してて、日本語化してくださった皆さんには感謝です。
特に Objective-C の表現をどう Ruby で現してるか、などランタイムのことが書いてある RubyMotion Runtime Guide(日本語訳) が興味深かったですね。
*1:個人の見解です
GlitchKit - iOS でカジュアルにグリッチできるライブラリ
本日、社内外の iOS/Android 向け Tips 共有会、#potatotips 第二回 で、「XXXKit -それははしかのような物-」という内容を発表した。
最近 iOS (Objective-C) を今更ながらに学び始めたんだけど、新しい事を学んで今まで知らなかった/興味深いパラダイムがあると、それにどっぷりつかりがちで、それを プログラマにおけるはしか 、と言ったりする。
その中でかじってすぐに興味深いと感じたのは Objective-C の"カテゴリ"で。これはヘッダを import するだけ(実際は import するしない関わらずリンクされた時)で、様々なオブジェクトのクラスの挙動を拡張できる。Ruby における mixin + refinements のような物だし、Perl でも use して特定のオブジェクトの挙動を変えることが出来るが、Objective-C を学ぶまで、このようなことができることを知らなかった。
またこの "カテゴリ" と組み合わせて、標準のオブジェクトや UIKit といったフレームワークを拡張することができる XXXKit という語尾に Kit をつけたライブラリがある。たとえば EnumeratorKit なんかは、NSArray や NSDictionary で、Ruby の Enumerator 的なコードを書くことができるようになる。もちろんこれらは意図しない動作を引き起こす可能性もあるため、多用すると危険なのだが、そこは便利さとトレードオフなので、どうしてもオレオレ XXXKit を作りたくなる衝動がでてくる。
そのため、"カテゴリ" と "XXXKit" は Objective-C におけるはしかのようなものだなぁ、と感じた。と言うわけでカテゴリ使って Glitch する XXXKit を作ってみた。
Podfile に追加する
pod 'GlitchKit'
UIImageView -glitch でグリッチ
#import "GlitchKit.h" // glitch! [uiImageView glitch];
簡単便利
UIImageView -glitchWithBlock: でグリッチ
好きなようにグリッチさせる
// apply custom glitch [uiImageView glitchWithBlock:^int(int byte, int index, uint length, Byte *bytes) { return (byte == 42 && arc4random() % 3 == 1) ? 0 : byte; }];
簡単便利
他にもUIImage クラスで以下が使えるようになる。
- (UIImage *)glitch;
- (UIImage )glitchWithBlock: (int (^)(int byte, int index, uint length, Byte bytes)) block;
- (NSData *)glitchData;
- (NSData )glitchDataWithBlock: (int (^)(int byte, int index, uint length, Byte bytes)) block;
どうぞカジュアルにごりようください。