TwitterのBootstrapを使ってみた
Twitter APIの認証画面がSafariで英語になる件
rubyのIOとエンコーディングについて
IOのドキュメントより
Kernel.#openのドキュメントより
第二引数のモードには、文字列では以下のパターンを受け付けている。
- "{mode}"
- "{mode}:{ext_enc}"
- "{mode}:{ext_enc}:{int_enc}"
modeはr/w/a/r+/w+/a+というオープンモードの指定。ext_encは外部エンコーディングの指定で、int_encは内部エンコーディングの指定。
File.open
Shift_JISで記述したCSVファイルをエンコーディングを指定してFile.openで読み込んだ場合。
$ cat encoding.rb File.open('sjis.csv', 'r:Shift_JIS:UTF-8') do |input| input.each_line do |line| puts line.encoding puts line end end $ ruby -v ruby 1.9.2p290 (2011-07-09 revision 32553) [x86_64-darwin11.0.1] $ ruby encoding.rb UTF-8 "あ","い","う","え","お"
CSV.foreach
CSV.foreachの:encodingオプションも同じだと思い試したが、例外が発生してしまう。
$ cat csv_encoding.rb require 'csv' CSV.foreach('sjis.csv', :encoding => 'Shift_JIS:UTF-8') do |row| puts row end $ ruby csv_encoding.rb /Users/koshigoe/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/csv.rb:2027:in `=~': invalid byte sequence in UTF-8 (ArgumentError) from /Users/koshigoe/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/csv.rb:2027:in `init_separators' from /Users/koshigoe/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/csv.rb:1570:in `initialize' from /Users/koshigoe/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/csv.rb:1335:in `new' from /Users/koshigoe/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/csv.rb:1335:in `open' from /Users/koshigoe/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/csv.rb:1201:in `foreach' from csv_encoding.rb:3:in `<main>'
CSVライブラリのソースを追いかけて、読み込みの実装を確認。改めて、File.openの確認のために以下を試す。
io = File.open('sjis.csv', 'r:Shift_JIS:UTF-8') data = io.read puts data.encoding io.rewind data = io.read(1024) puts data.encoding io.close
バイト数を指定せずにreadを実行すると内部エンコーディングに変換されるが、バイト数を指定するとASCII-8BITとなる。
で?
どうしたらいいんだ?File#readの仕様を把握してないので、次はそこを探ろう。
追記
引数 length が指定された場合はバイナリ読み込みメソッド、そうでない場合はテキスト読み込みメソッドとして 動作します。
なるほど。
追記
CSVの読み込み処理。
class CSV ... def read_io(bytes) @io.read(bytes).force_encoding(raw_encoding) end end
追記
CSVモジュールのread_ioメソッドを書き換えて、エンコーディング指定だけじゃなく変換までやるようにしてみた。どうするのが筋が良いのかは考えてない。
--- /Users/koshigoe/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/csv.rb 2011-10-19 00:23:20.000000000 +0900 +++ /Users/koshigoe/.rbenv/versions/1.9.2-p290/lib/ruby/1.9.1/csv.rb.orig 2011-10-19 00:23:18.000000000 +0900 @@ -2315,7 +2315,7 @@ end def read_io(bytes) - @io.read(bytes).encode(raw_encoding, @io.external_encoding) + @io.read(bytes).force_encoding(raw_encoding) end end
外部エンコーディングだけ指定した場合、内部エンコーディングも指定した場合で期待通りの結果を得られた。
require 'csv' CSV.foreach('sjis.csv', :encoding => 'Shift_JIS') do |row| row.each{|col| puts col.encode('UTF-8') } end CSV.foreach('sjis.csv', :encoding => 'Shift_JIS:UTF-8') do |row| puts row end
次はRedmineで情報を探るべきだろうか。見逃される様なものじゃないと思うし、バグではないと思うんだけどよくわからんね。
node.jsでFacebookアプリの開発を始める
FacebookのGraph APIやOpen Graphをもっと触っておこうというのが趣旨です。
なんでnode.jsを選んだか
根拠はありません。イベント駆動モデルということで、1インスタンスでのスループットがRailsより高いのかなと思ったからです。
加えて、触ったことがない技術をいくつか触れるからという理由もあります。
環境はHeroku
収益を上げられるわけでもなく、利用も見込めない(herokuドメインのSSL証明書を使うので自分以外は使いたくないはず)ので、Herokuの無料で使える範囲に収めたら良いと思っています。
- Dyno x 1
- Worker x 0
- Cron /Day
- MongoLab (240MB)
MongoLabだけ無料で使える容量が飛び抜けて大きいのが気になっています。なぜでしょうね?
MongoDB
これは、Herokuでそれなりの容量をもらえる無料ストレージがMongoDBだったという理由以外にありません。
敢えて言うなら、こういう場合でもない限り触る機会もなさそうだからということもあります。
node.js用にはmongooseを選択。他に選択肢があるのかは知りません。
ひとまず、認証用にeveryauthを選択しました。connect-authやmongoose-authという選択肢もあるようです。
- mongoose-auth
- everyauthをMongoDBと一緒に使う場合に便利だとか
- everyauthどころかnode.jsでいっぱいいっぱいなのに、さらにややこしくしないでくれ、ということで採用見送り
- connect-auth
- connectってなんだ、expressでこい、という超上から目線でマニュアルを求めた結果採用見送り
近況
- node.js インストール
- npm インストール
- package.json 把握(HerokuでGemfile的な扱い)
- mongoose経由でMongoDBを使ってみた
- mongooseを使ったモデル定義を外部ファイルに切り出してみた
- mongooseのfind系で躓いた
- node.jsのイベント駆動モデルに慣れず、コールバック(非同期処理)で考える癖がついてない
- findOneが結果を戻り値を返さないことにも手間取った
- コールバック(クロージャ)で外側のローカル変数を共有して代入する方法でごまかしてる
- そもそもCommonJSを把握してないので、Promiseとかなんとなくで使っているからフワフワする
- everyauthでFacebook認証を実現してみた
とにかく、「動けば良いや」の精神でドキュメントは読みつつ、あまり深入りせずに実装をトライ&エラーですすめています。
FacebookのOpen Graph
触ってみた。
- https://developers.facebook.com/docs/beta/opengraph/
- https://developers.facebook.com/docs/beta/opengraph/tutorial/
使用感。
- アプリケーション(名前空間)でのアクションとオブジェクトの準備が面倒くさい
- 開発・ステージ・本番といった環境別にアプリケーションを作る場合に面倒くささが倍々ゲーム?
- アクション、オブジェクト、アグリゲーションの設定項目が多いのが面倒だが、前向きに考えれば可能性が広がりんぐ
- アクションはアプリケーションローカルしかないんだろうか?
- オブジェクトにはグローバルなものがある(OGPで定義済みのog:typeはグローバルと思われる / book は名前空間不要だった)
- アクションにせよオブジェクトにせよ、共通語彙に収束してくれるとやりやすくなりそう
- publish_actionsパーミッションが要求された(アプリケーションにパーミッション与える前)
使うだけなら面倒なだけで難しさはありません。これを使ってキラーアプリ(?)作れと言われたら黙り込みますけどもね。
「アクション定義はアプリケーションごとに行う」ということに引っかかりを覚えたまま、消化不良でおしまい。
社内勉強会でUnicornについて発表したけどあまりの準備不足に全俺が泣いたので少しずつまとめていく〜中断
気が抜けてきたので、ここまで書いてきたことをHikiにまとめて中断とした。再開予定は未定。
社内勉強会でUnicornについて発表したけどあまりの準備不足に全俺が泣いたので少しずつまとめていく〜その6
Unicornの設定ファイル
Unicornは、Rubyスクリプトを設定ファイルとして読み込み評価(eval)する。
$ unicorn --config-file=unicorn.conf.rb config.ru
設定ファイルは指定された場合だけ評価される。--config-fileオプション(もしくは-c)が省略されれば、デフォルトの設定で動作する。
instance_eval(File.read(config_file), config_file) if config_file
設定ファイルの読み込みと評価は上記の通りで、Unicorn::Configuratorクラスのインスタンスをコンテキストとしてevalする形になっている。つまり、設定ファイルで利用可能なディレクティブは、基本的にUnicorn::Configuratorクラスのインスタンスメソッドと同義。
チューニングに関するドキュメントも書かれている。
設定ファイルのサンプルも用意されている。
- http://unicorn.bogomips.org/examples/unicorn.conf.rb
- http://unicorn.bogomips.org/examples/unicorn.conf.minimal.rb
以降、ディレクティブについて書き連ねていく。
before_exec/before_fork/after_fork
フックが用意されているので、必要に応じてコールバック処理を定義すると良い。
- before_exec
- 新しいマスタプロセスを作る(reexec)際のexec()が実行される直前にあるフックポイント。
- before_fork
- ワーカープロセスをforkする直前にあるフックポイント。
- after_fork
- ワーカープロセスをfork後、いくつかの必要な処理を挟んだところにあるフックポイント。
after_forkでワーカープロセス個別にリスナーを登録することで、ワーカープロセスにダイレクトにリクエストを投げることができるので、デバッグなどで役立つことがあるはず。
preload_app
ワーカープロセスをforkする前に、マスタプロセスの中でアプリケーションをプリロードできる様にする。デフォルトで無効になっている。
この機能を有効にすることで、Copy-on-Writeフレンドリであればメモリ消費を抑えられる。ただし、マスタプロセスとワーカープロセスとの間でリソースを共有してしまう問題があるため、フックを利用してソケットを開き直すなどすること。ログファイルについては、アトミックな書き込みが出来るようにしているため、開き直す必要はない。
この機能が無効である場合、HUPシグナルによって設定ファイルをリロードした際にアプリケーションもリロードし、ワーカープロセスをグレースフルに再起動する。アプリケーションがロードされる際、常にGem.refreshが実行される。
user
ワーカープロセスのユーザとグループを指定することが出来る。指定しない場合は、マスタプロセスと同じものとなる。
ほか
- client_body_buffer_size
- listen
- logger
- pid
- rewindable_input
- stderr_path
- stdout_path
- timeout
- worker_processes
- working_directory