Friday, 30 November 2012

Herokuのスタックに独自のシェルコマンドを導入する

Herokuではgemでパックされていないシェルコマンドは使えないと思っていました。

が、最近buildpackでgit push でスタックを作成する時に


$ heroku create myapp --buildpack https://github.com/heroku/heroku-buildpack-ruby

としてカスタムのbuildpackを指定する事により、カスタムのシェルコマンドを導入する事ができます。あとはRubyの中で `command`です。buildpackについては下に記事があります。


シェルで使い慣れているあれやこれやのコマンドをHerokuにデプロイしたアプリケーションでもつかえるようになります。ただここまで来ると自分でクラウドアプリケーションサーバであるHerokuではなくVPSなど自分でサーバの環境から構築するのとどちらが良いのか微妙なラインになってきますね…。

Wednesday, 28 November 2012

Caching implementation on RoR

今作っているRuby on Railsでアプリケーションをキャシングをするのに、調べ物をあれこれと。

アプリケーションはHeroku上で動かすのですが、Herokuのドキュメント上にはアプリケーションが再起動する際にはコンパイル後に保存されたディスク上のデータは消えるので、ディスクキャッシュは使えないそうです。なのでHerokuのおすすめとしてはmemcachedを使う事。

ということで、今回はHerokuのプラグインであるMemcacheを使ってキャッシュしてみました。キャッシュの方法は下の3つ。

- ページキャッシュ --> アプリケーションのレイアウトを流用した404や500ページを使用したいのでカスタムでページを作ってページキャッシュ。データも大きくないし、消えてしまっても特に問題無いのでディスクキャッシュで。これは単純に

caches_page :action_name

と書くだけです。

- アクションキャッシュ --> sitemap.xmlをデータベースからデータを引っ張ってきて作成しているので、これをアクションキャッシュで保存。データベースが大きくなる予定なので、botが来る度にxmlを生成しているとパフォーアンスの低下に繋がる可能性が高いです。検索botたちが訪問する頻度はそんなに高くないだろうと思うので、3日で賞味期限が切れる様に設定。多分これで良いと思います…。これも同じくコントローラの最初で

caches_action :action_name, expires_in: 3.days

と記述するだけ。

- 外部API --> ショッピングモールが提供するAPIから商品の情報を引っ張ってきているのですが、このレスポンスがかなり時間がかかっている様です(20個ぐらいの商品情報を引っ張って来るのに2秒近く)。これは取りあえずAPIのデータのみをmemcachedに保存。まずは賞味期限8時間ぐらいで動かしてみます。コントローラ上でmemcacheを使用して幾つかのviewでもキャッシュしたデータを利用できる様にします。製品ごとに販売できる商品を製品のキャッシュデータをデータベースの中のidとupdated_atのタイムスタンプ、それに'buyable'の文字列を付与したインデックスで管理します。

@buyables = Rails.cache.fetch([@product, 'buyables'], expires_in: 8.hours) { @product.buyables }

Monday, 26 November 2012

Ruby block, Proc, lambdaについてやっと調べてみました。

ずっと分からないと感じていたRubyのclosureについて調べてみました。

まずProcオブジェクトは手続きを記述したコードブロックを保存したオブジェクトです。これだけだとただの無名関数ですが、Procはその中にその時の周りの変数の状態なども保存できる事から、closureになるのでしょう(PHPのある日本語マニュアルページでは”無名関数はクロージャとも呼ばれ”と書いてあるけど…)。

例えば

x = 0

foo = Proc.new {return x}
foo.call

とすると

=>0

が返ってきます。しかし、


foo = Proc.new {return x}
x = 0
foo.call

とすると

NameError: undefined local variable or method `x' for main:Object

とエラーが出ます。Proc.newした時にあったKernelにくっついたxメソッドの返り値を参照しているのでしょう。ここで => 0が返って来ないのがclosureと無名関数の違いなのではないでしょうか?

Rubyでは変数の明示的削除はできないらしいですが、例えば


x = 0

foo = Proc.new {return x}
x.delete
x = 0
foo.call


などとできると

NameError: undefined local variable or method `x' for main:Object

のエラーが返ってくると思います。


closureの使い途として考えられるのは例えばDBにクエリを送る際にメソッドチェーンにして遅延評価し、DBのIOを少なくする事でしょうか。

例えばPostモデルがあった時に

@post = Post.has_image.sort_by_date.first

そのままコードを読めば、has_imageメソッドでまずPostのオブジェクトの配列を作って取得し、その後でソートして、その一番最初のオブジェクトを取得するとなります。が、本当にこんな事をしていればサービスとして破綻してしまいますね(破綻しなくても無駄が多すぎて許せないという人もいるのでしょうか…)。

ここはActiveRecordやその他のORMではProcを使用してsort_by_dateの部分までクエリを作ってしまってfirstで初めてPostのオブジェクトを返すという事にしているのでは(まだActiveRecordのコードは読んだ事が無いのですが、これは次の課題です)?

誰かこの文を読んでclosure理解の役に立つと良いですね…。それともやっぱり分かりにくい文になったかな…。

Friday, 23 November 2012

TCP/IPを今更調べてみました



とある会社のCTOと話をした時にTCP/IPの事を訊かれた事を思い出し、今更ですがO'Reilly本を基礎にして調べてみました。

プロトコルのレイヤーとしては

4. Application Layer
  ウェブサーバ、メールサーバ、ファイルサーバなどなどのサービス、またその上に載っているアプリケーションのレイヤー。

3. Host-to-Host Transport Layer
  Transport Control Protocol (TCP)とUser Datagram Protocol (UDP)などが属する。データをしかるべきポート番号に送ったり、データの送受信を確認したりする。

2. Internet Layer
  Internet Protocol (IP)やInternet Control Message Protocol (ICMP)がここに属する。データグラムのサイズを調整したり、IPアドレススキームを解決したりする。RouterはInternet LayerとNetwork Access Layerのみ使用。その上のレイヤーはHostとHostの間で使用する。

1. Network Access Layer
  EthernetのアドレスとIPアドレスの対応を取るなど。


と分類するのが一番すっきりするという説があります。

ちなみにTCP/IP protocol suiteの名前は歴史的なもので、別にUDP/ARPとかでも良かったのではないかと思います。TCP/IPは確かにキャッチーだけど、歴史的な遺産をそのまま使うのは余り好きじゃないですね。TCP/IP Protocol Suiteと同等の用語であるInternet Protocol Suite (IPS)の方を使おうか…。でもそれだと他の人と話が合わなくなりそうだし…。

Thursday, 22 November 2012

Never run when you can walk.


最近こんなフレーズの一部を聞きました。
"A bad ride is better than a good run
Never run if you can walk . . .
. . . never walk when you can stand . . .
. . . never stand when you can sit . . .
. . . never sit when you can lie down.
Any fool can be uncomfortable in the field,"
日々仕事に追われて、すぐに使えるプラグインや関数を探すのに追われているのは私だけでしょうか?

プロダクションの現場で走らなければいけない時はいつでも来るので、走らなくてよい時間を使ってもっと根本の例えば言語のコードを読む事や、OOをもっと理解する、ネットワークの基礎を知るなどやっておく事がありそうです。

私も歩く事を勉強し直しです。

下の記事にもう少し詳しい説明があります。元はカナダの軍隊のオフィシャルでないコード らしいですね。


http://answers.google.com/answers/threadview?id=259247

Tuesday, 20 November 2012

Twitter Bootstrapで素早くUI開発

Twitter Bootstrapを今作っているウェブアプリケーションに導入しています。

Twitter Bootstrapはグリッドやテンプレート、マルチデバイスサポートのレイアウトやボタン、またGlyphiconsも無料で使える契約をTwitterがしてくれています。

CSSエンジンのLess、HTMLの構造などを調べればかなり速く、フレキシブルなUI の構築ができます。Railsでも使えるgemが出ていますし、多分他のウェブ開発フレームワークでも使えるようにしてくれている人がいると思います。

Friday, 16 November 2012

Vimでファイルを保存する時に現在のファイルのフォルダを取得

Vimでファイルを保存する時に現在のファイルのフォルダを取得するのに少し困っていると、下の記事を見つけました。


結論は

:w %:p:h/FILENAME

で現在編集中のファイルがあるフォルダに新しくファイルを保存できます。

vで選択したファイルの一部を別ファイルに保存する際などに便利です。

なお、%が現在のファイルを返し、:p (path) がそのフルパスを返します。そして:h (head of path)でそのフォルダを返します。

Thursday, 15 November 2012

TextmateからVimに切り替えます

今までコマンドやショートカットを憶えられないからという理由でGUIのテキストエディターであるTextmateを使ってきましたが、もっとコードを書く効率を上げたい動機が切迫してきたのでVimに切り替えます。

だんだんと、調べ物をしている時間や実験でコードを書いている時間の方がプロダクションのプログラムを書いているよりも圧倒的に多くなってきました。で、実際もっともっと調べものをする時間を増やしたいので、できるだけ書く時間を短くしたいと感じています。ので、一つの手段としてVimを導入する事にしました。
$ vimtutor
でチュートリアルが走るので、同じく初めての方はここから始めてみてください。 チュートリアルは全部で7章あります。チュートリアルの内容はあくまで覚えようとするのではなく実際にやってみて体で覚えていくようにとのことです。なんだか職人っぽいん学習方法ですね。

チュートリアルで出てきたコマンドは下の通り。

第1章

  • h --> 左へカーソル移動
  • j --> 下へカーソル移動
  • k --> 上へカーソル移動
  • l --> 右へカーソル移動
  • :q! --> vimの終了 (quit)
  • x --> カーソルの下の文字を削除
  • i --> テキストを挿入 (insert)
  • A --> 行の最後にテキストを挿入 (Append)
  • :wq --> ファイルをセーブして終了
第2章
  • dw --> 次のワードまで削除 (delete)
  • d$ --> 行の終わりまで削除
  • d + motionでいろいろな削除ができる。motionの例は下のとおり
  • 0 --> 行の先頭に移動
  • w --> 次のワードの先頭に移動 (word)
  • e --> 次のワードの最後に移動 (end of word?)
  • $ --> 行の最後に移動
  • d + number + motion --> numberで指定しただけ削除が行える(例えば d10wなど)
  • dd --> 一行削除
  • u --> 元に戻す (undo) 
第3章

  • p --> 張りつけ(paste)
  • r --> カーソルの下の文字を置換 (replace)
  • c --> 文字の置換 (change)。例えば c10 で現在のカーソル一から10文字を削除して文字列を挿入(insertモード)。
第4章
  • CTL-G --> 現在のファイルの情報と現在のカーソルの位置情報を表示
  • G --> ファイルの一番最後へ移動 (Go?)
  • gg --> ファイルの先頭へ移動
  • number + G --> number行目へ移動
  • / --> 検索。/文字列のように使用。nで次の候補を検索、Nで前の候補を検索。
  • ? --> /とは反対の方向に検索
  • CTL-O --> 前にいたカーソルの位置に移動
  • CTL-I --> 次のカーソル位置に移動
  • % --> 対応する括弧に移動 ({[()
  • :s/old/new --> "old"を"new"で置換 (substitute)(最初の候補だけ置換される)
  • :#,#s/old/new --> #で指定した行の間の文字列を置換
  • :s/old/new/g --> 行内の全ての候補を置換
  • :%s/old/new/g -->  ファイル全部の文字列置換
  • :%s/old/new/gc --> 上の動作をそれぞれの候補ごとに対話式で置換
第5章
  • :! cmd --> シェルコマンドを実行。例えば :!ls など
  • v motion --> 文字列を選択 (visual selection)。選択した文字列に対してもコマンドを実行できる (例えば:w FILENAME 選択した部分のみをファイルに保存)
  • :r FILENAME --> ファイルの内容を現在のドキュメントに挿入 (read?)
  • :r !cmd --> シェルコマンドの返り値を現在のドキュメントに挿入。例えば :r !ls など
第6章
  • o --> 現在のカーソル位置の下に新しい行を挿入してinsertモードに移る 。Oでカーソルの位置に行を挿入
  • R motion --> 現在のカーソル位置から motion で指定しただけ文字列を削除し、insertモードに移行<ESC>で編集を終了。(Replace)
  • y --> 文字列をコピー (yank)。vで文字列を選択してyでコピー。
  • :set ic --> 文字列検索時に大文字、小文字を区別しない (ignore case)
  • :set noic --> 文字列検索時に大文字、小文字を区別
  • :set hls --> 検索候補の文字列全てをハイライトする (highlight search)
  • :set nohld --> hlsを解除
第7章
  • :help --> ヘルプを表示
  • CTL-W s --> 上下に画面を割って新しいウィンドウを作成
  • CTL-W v --> 左右に画面を割って新しいウィンドウを作成
  • CTL-W CTL-W --> ウィンドウを移動
  • CTL-D --> 候補のコマンドを表示。例えば :e CTL-Dで"e"で始まるコマンドの候補を表示<TAB>で次の候補に移動
ドキュメント外
:e FILENAME --> ファイルを開いて編集 (edit)



そういえばHTMLを勉強し始めた2年半前にはMac標準のテキストエディタでは使いにくかったのでTextWranglerを使い始め、CodaがいいよっていうことでCodaにZenCodingを入れて使いました。Railsを使い始めた1年前ぐらいの段階でTextmateを紹介してもらい、今やっとVimに移行です。さて、使いこなせるかな…。

Tuesday, 13 November 2012

箕面ハイキングに行ってきました

箕面に軽いハイキングに行ってきました。紅葉のとても良い時期でした。おすすめです。


Monday, 12 November 2012

Scala/Clojure/Ruby勉強会 報告 (cont.) #ujmben2012

勉強会に参加して、Rubyの遅延処理が2.0からEnumerable#lazyに実装されるということ(Scalaなどと比べるとそんなにlazyではないという議論になりましたが…)。あとScalaとClojure、Rubyの違いなどを聞いてきました。Clojureのアトミックなスレッドオペレーション(言葉が正しいか???)は特にインパクトがありました…。

まだまだ分からない事が多かったので、個人的にはScalaは分散処理をする必要があるときはおもしろい選択肢。Clojureは言語の仕様がかなり数学的に考えられていて面白いです。単体のマシンで走らせるプログラムにはとても面白そうという印象です。RubyはRailsを使っていると開発が速いので放せないですね。memoize処理の書き方もとてもシンプルで個性的。

Saturday, 10 November 2012

Scala/Clojure/Ruby勉強会 #ujmben2012

Scala/Clojure/Ruby勉強会に参加してきました。

http://kokucheese.com/event/index/57145/

言語ではなくハートで話す感じのこんなイベント私はとても好きです。とても刺激になりました。勉強会の後でもいろいろ調べものしないと…ですね。来年もまた参加したいです。

Google Calendarのイベントを拾ってFacebookページに投稿するアプリケーション

Google Calendarで管理しているイベントを前日に拾ってFacebookページに投稿するアプリケーションを作りました。コードはMITライセンスでGitHub上で公開しています。


ちょっとセッティングが面倒ですが使ってみてくださいね。セッティングにはある程度のRubyの開発環境とHerokuが使える事が前提です…。まだまだ開発者が使う事を前提としたアプリケーションですね…。

フィードバックもお待ちしてます。

Thursday, 8 November 2012

RailsとRubyのエラーハンドリングの違い

ウェブアプリケーションを作っていると

if !object.method
  do_this
else
  do_that
end

という方法でユーザを誘導する習慣が付いていますが、Rubyで組み込みやデスクトップアプリケーションなどを開発する際には下のようにする人が多いのではないでしょうか?

begin
  do_this
  do_that
rescue
  error_handling_method($!)
end

こうしておいて

def do_this
  raise 'Specific error message' if !some_method
end

などとそれぞれのメソッドの中でRuntime errorを発生させれば最後のrescueの所でまとめてエラーを処理できるので便利でした。例えばSTDOUTに表示させるとか、ログにまとめるとか、メールでエラーを報告するなどなど。

ちなみにRSpecではこのサイトに書いてある通り

it "should raise" do
 expect{Object.non_existent_message}.to raise_error(NameError) end

とすればテストが書けます。

Railsでも同じようにエラーの処理はできると思いますが、通常begin, rescue, endは使わないですね。ディベロッパー向けのAPI以外では、ウェブアプリケーションはエラーメッセージは極力詳細は出さない事もセキュリティー上大切なのでこのような設計になるのでしょうね。例外が発生したら多くの場合シンプルにbreakして500を返しますもんね…。ウェブサービスでもREST APIを作る人はもっと複雑なエラーハンドリングを開発しているんでしょうね。お疲れさまです。

Tuesday, 6 November 2012

RubyのTimeクラスオブジェクトをRFC3339に変換

Google Calendar API(v2)を使っていて、時間のクエリをRFC3339フォーマットにしてくださいということが書いてありましたが、RubyのTimeクラスにはrfc3339メソッドがありません。

このサイトに書いてあるにはRSSではRFC3339は標準なので、RubyではRFC3339フォーマットに時間を変化するのは#xmlschemaで提供されているそうです。

irb > Time.now.xmlschema

で変換できました。

※後で教えてもらったのですが、DateTimeクラスだとrfc3339メソッドがあるみたいです。ちなみにDateTimeクラスを用いると例えば下のコマンドで次の日の00:00時をRFC3339フォーマットのString形式で返してくれます。

Date.today.next.to_time.to_datetime.to_s

Saturday, 3 November 2012

Jiro Dreams of Sushi (ドキュメンタリー映画)

Jiro Dreams of Sushiというドキュメンタリー映画を観ました。じろうさんは、人によっては極端な仕事の仕方だという事を言う人も多い様ですが、私としては多くの会社で仕事をしている人より妥当な生き方をしているように感じました。


Friday, 2 November 2012

Stackoverflow使い始めてみてます



プログラミングQ&Aサイトのstackoverflowを使い始めてみています。

ちなみに最初の発言は見事にモデレータによって削除されました。Twitterで直接訊いてみたところ、なんでも私のは答えではなくコメントとして入れるべき内容だったそうです。ただコメントはある程度reputationというユーザの信頼度の数値が溜まらないとできないそうです。まあ初心者はまだまだ修行してくださいという事でしょうね。Githubといい、stackoverflowといい、コミュニティーのルールを学のも結構大変ですね…。

モデレータは何も分からない人への質問にもしっかり答えてくれる姿勢がありがたいです。meta stackoverflowというstackoverflow自体に関するディスカッションの場も公開で運営されていて面白いです。