Shoken Startup Blog

KitchHike Founder/CTO

楽天テクノロジーカンファレンス2012に行きました

Rakuten Technology Conference 2012 - 楽天テクノロジーカンファレンス2012に参加してきました。
特徴はなんといってもオールイングリッシュ!まさにこの記事の通りでした。


~引用~
いつか海外のイベントに参加してみたい、あるいは自分の英語力でどこまで英語のセッションを理解できるか試してみたいというITエンジニアの方。飛行機に乗る必要もなく日帰りできる、海外イベント的体験を試してみてはいかがでしょう。

海外イベントに参加したとして、自分はどこまで理解できる? 全編英語の「楽天テクノロジーカンファレンス2012」で腕試し - Publickey


■全体の感想
司会から英語でアナウンスで、ばっちり目が覚めました。こちらの参加者も書かれているとおり、質疑応答も全部英語。


~引用~
最初のセッションが始まるまでまだ時間があったので、のんびりと椅子に座って待ってたら、進行スタッフらしき女性達が

「ねぇ、セッションの後に日本語で質問があったらどうする?」

「でもさぁ、英語のセッションを聞きに来てて、日本語で質問するってあり得る?」

と話しているのが聞こえて思わず心がくじけそうになった。確かにそれはそうだなと思いつつ、どうなるかと思ってたら参加した全セッションでの質問は全て英語だった。といっても日本人以外からの質問が多かったけど。
楽天テクノロジーカンファレンス2012へ行ってきた - Diary of pcm_kas


■ランチが無料だった!
こんなにおいしそうなランチが無料!
f:id:sfujisak:20121022093807j:plain

さらに、コーヒー飲み放題、ペットボトルと軽食がフリーという豪華さ。
楽天さん、ありがとうございました。


■セッションの内容
特に印象に残ったセッション2つ。

・On relentless automation in software development
Kosuke Kawaguchi(Architect / CloudBees, Inc.)
Jenkins作者の川口耕介さんの講演。
まるでネイティブのような流暢な英語と洗練されたプレゼンに圧倒されました。
スライドのSummaryページで、「Jenkinsはマルチコア化・クラウド化するコンピュータ環境とソフトウェア技術者のGlue(糊)となる」とあったのが印象的でした。

・Refinements - A new feature of Ruby
Shugo Maeda
前田さんによるRuby 2.0の新機能Refinementsの講演。
最後の質疑応答で議論されていたことで、かなり理解度が高まりました。前田さんによると、
「Refinementsはアプリケーションエンジニアにはあまり必要ではないかもしれないが、ライブラリ開発者には必要な機能」とのこと。
質問してくれた外国人の方、Thank you.
Refinements、文字で読むと理解できなかったと思います。講演(質疑応答)を聞けて良かったです。

MongoDBへ様々なデータ型を保存/取得してみる。Date編

MongoDBへ様々なデータ型を保存/取得してみる。オブジェクトマッピング編 - Shoken OpenSource Society
MongoDBへ様々なデータ型を保存/取得してみる。バイナリ(BINARY)編 - Shoken OpenSource Society
MongoDBへ様々なデータ型を保存/取得してみる。Boolean編 - Shoken OpenSource Society

MongoDBへ様々なデータ型を保存/取得してみるシリーズ第4回は、Dateで日付/時間を取り扱ってみます。RubyからMongoDBへ現在時刻をinsertし、日付/時刻を条件に検索してみます。

RubyからMongoDBへ現在時刻を挿入

RubyのTimeクラスを使います。
参考
MongoDBへ様々なデータ型を保存/取得してみる。オブジェクトマッピング編 - Shoken OpenSource Society

現在時刻をMongoDBへinsertするサンプル

require 'mongo'

db_name='test'
coll_name='time_insert'

## 接続処理
db = Mongo::Connection.new.db(db_name)
coll = db.collection(coll_name)

coll.insert({:time => Time.now})

db[coll_name].find().each{ |doc|
  p doc
}

db.connection.close

実行するたびに現在時刻をinsertします。

[root@dev ruby]# ruby mongo-insert.rb
{"_id"=>BSON::ObjectId('4ff3ea4caf1fe603d1000001'), "time"=>2012-07-04 07:01:32 UTC}
{"_id"=>BSON::ObjectId('4ff3ea4daf1fe603d5000001'), "time"=>2012-07-04 07:01:33 UTC}
{"_id"=>BSON::ObjectId('4ff3ea50af1fe603d9000001'), "time"=>2012-07-04 07:01:36 UTC}
{"_id"=>BSON::ObjectId('4ff3ea51af1fe603dd000001'), "time"=>2012-07-04 07:01:37 UTC}
{"_id"=>BSON::ObjectId('4ff3ea52af1fe603e1000001'), "time"=>2012-07-04 07:01:38 UTC}
{"_id"=>BSON::ObjectId('4ff3ef2eaf1fe60bf1000001'), "time"=>2012-07-04 07:22:22 UTC}

日付/時刻を指定した検索

RubyからTimeクラスのオブジェクトを作成します。

require 'mongo'
require 'time'

db_name='test'
coll_name='time_insert'

## 接続処理
db = Mongo::Connection.new.db(db_name)
coll = db.collection(coll_name)

time_condition = Time.parse('2012-07-04')
puts "where time > #{time_condition}"

db[coll_name].find({:time => {"$gt" => time_condition}}).each{ |doc|
  p doc
}
puts

time_condition = Time.parse('2012-07-04 07:01:35 UTC')
puts "where time > #{time_condition}"

db[coll_name].find({:time => {"$gt" => time_condition}}).each{ |doc|
  p doc
}

db.connection.close

実行結果

[root@dev ruby]# ruby mongo-find-bytime.rb
where time > 2012-07-04 00:00:00 +0900
{"_id"=>BSON::ObjectId('4ff3ea4caf1fe603d1000001'), "time"=>2012-07-04 07:01:32 UTC}
{"_id"=>BSON::ObjectId('4ff3ea4daf1fe603d5000001'), "time"=>2012-07-04 07:01:33 UTC}
{"_id"=>BSON::ObjectId('4ff3ea50af1fe603d9000001'), "time"=>2012-07-04 07:01:36 UTC}
{"_id"=>BSON::ObjectId('4ff3ea51af1fe603dd000001'), "time"=>2012-07-04 07:01:37 UTC}
{"_id"=>BSON::ObjectId('4ff3ea52af1fe603e1000001'), "time"=>2012-07-04 07:01:38 UTC}
{"_id"=>BSON::ObjectId('4ff3ef2eaf1fe60bf1000001'), "time"=>2012-07-04 07:22:22 UTC}

where time > 2012-07-04 07:01:35 UTC
{"_id"=>BSON::ObjectId('4ff3ea50af1fe603d9000001'), "time"=>2012-07-04 07:01:36 UTC}
{"_id"=>BSON::ObjectId('4ff3ea51af1fe603dd000001'), "time"=>2012-07-04 07:01:37 UTC}
{"_id"=>BSON::ObjectId('4ff3ea52af1fe603e1000001'), "time"=>2012-07-04 07:01:38 UTC}
{"_id"=>BSON::ObjectId('4ff3ef2eaf1fe60bf1000001'), "time"=>2012-07-04 07:22:22 UTC}


Mongo Shellからの検索はこちらが参考になりました。
MongoDBで、日付の期間を指定して検索する方法 - DQNEO起業日記

Facebook Graph API で OpenSSL::SSL::SSLError

RailsFacebook Graph APIを使う時に以下のようなエラーが出た場合の対応方法。

OpenSSL::SSL::SSLError

SSL_connect returned=1 errno=0 state=SSLv3 read server certificate B: certificate verify failed

環境

ruby 1.9.3p194

対応方法

使用しているhttp clientのca_fileを設定する。

net/httpの場合
require 'net/http'

#OAuthに必要な各パラメータ変数をアプリごとに定義
client_id = 'xxxx'
client_secret = 'xxxx'
redirect_url = 'xxxx'

#codeはgraph apiのレスポンスから取得する
code = 'xxxx' 

https = Net::HTTP.new('graph.facebook.com', 443)
https.use_ssl = true
https.ca_file = "#{Rails.root}/config/ca-bundle.crt"
response = https.get("/oauth/access_token" +
                          "?redirect_uri=" + redirect_url +
                          "&client_id=" + client_id +
                          "&client_secret=" + client_secret +
                          "&code=" + code)
ca-bundle.crtの入手方法
[root@dev ~]# wget http://curl.haxx.se/ca/ca-bundle.crt
[root@dev ~]# cp ca-bundle.ctr {Rails.root}/config/ #{Rails.root}は環境によって変更する


参考
Ruby 1.9 and the SSL error « Martin Ottenwaelter


ところで、"net/http"と"net/https"ってどう使い分ければ良いのだろう??

追記: "net/http"と"net/https"の違い

ソース見た。
結論:マージされてるから、"net/http"使え。

ソースはここ。

ruby-1.9.3-p194/lib/net/http.rb
ruby-1.9.3-p194/lib/net/https.rb
https.rbの中身

これで全部。

=begin

= net/https -- SSL/TLS enhancement for Net::HTTP.

  This file has been merged with net/http.  There is no longer any need to
  require 'net/https' to use HTTPS.

  See Net::HTTP for details on how to make HTTPS connections.

== Info
  'OpenSSL for Ruby 2' project
  Copyright (C) 2001 GOTOU Yuuzou <gotoyuzo@notwork.org>
  All rights reserved.

== Licence
  This program is licenced under the same licence as Ruby.
  (See the file 'LICENCE'.)

=end

require 'net/http'
require 'openssl'

ドキュメントのネスト

MongoDBはドキュメントをネストさせることができます。

Mongo Shellから

insert

> db.nest.insert({x:5,list:{a:1,b:2}})

確認

> db.nest.find().forEach(printjson)
{
        "_id" : ObjectId("4fb5e74522646db867ef11f6"),
        "x" : 1,
        "list" : {
                "a" : 1,
                "b" : 2
        }
}

rubyから

rubyからMongoDBへネストしたドキュメントをinserして表示するサンプル。

#!/usr/local/bin/ruby
# -*- encoding: utf-8 -*-

require 'mongo'

db_name="test"
coll_name = "nest"

db = Mongo::Connection.new.db(db_name)
coll = db.collection(coll_name)

coll.insert({:x => 2,:list => {:a => 2, :b => 4}})

coll.find().each{ |doc|
  puts doc.inspect
}
[root@xxx xxx]# ruby mongo_nest.rb
{"_id"=>BSON::ObjectId('4fb5e74522646db867ef11f6'), "x"=>5.0, "list"=>{"a"=>1.0, "b"=>2.0}}
{"_id"=>BSON::ObjectId('4fb5e8523e91d8207d000001'), "x"=>1, "list"=>{"a"=>3, "b"=>9}}

MongoDBへ画像ファイルをバイナリで保存/取得

MongDBへローカルファイルの画像をバイナリで保存/取得するサンプルコードです。

環境

OS CentOS 5.4
ruby 1.9.3
mongo 1.6.1
MongoDB 2.0.4

MongoDBへ画像ファイルをバイナリで保存

#!/usr/local/bin/ruby
# -*- encoding: utf-8 -*-

require 'mongo'

#第1引数=保存する画像ファイル名,第2引数=保存先database,第3引数=保存先コレクション
if (ARGV.size < 3)
  puts
  puts 'Usage: ARGV[0]=file_name ARGV[1]=db_name ARGV[2]=collection_name'
  puts
  exit
end

db_name = ARGV[1]
coll_name = ARGV[2]

db = Mongo::Connection.new.db(db_name)
coll = db.collection(coll_name)

file_name = File.basename(ARGV[0])
image = File.open(ARGV[0], "r+b")

puts "insert to #{db_name}.#{coll_name} from local file '#{file_name}'"
coll.insert({:image => BSON::Binary.new(image.read,
                                        BSON::Binary::SUBTYPE_BYTES),
             :file_name => file_name
            })

db.connection.close

使用例

[root@xxx ~]# ruby insert_image_to_mongodb.rb input.png test image_collection
insert to test.image_collection from local file 'input.png'

MongoDBから画像ファイルを取得

#!/usr/local/bin/ruby
# -*- encoding: utf-8 -*-

require 'mongo'

#第1引数=取得する画像ファイル名,第2引数=保存先database,第3引数=保存先コレクション
if (ARGV.size < 3)
  puts
  puts 'Usage: ARGV[0]=file_name ARGV[1]=db_name ARGV[2]=collection_name'
  puts
  exit
end

db_name = ARGV[1]
coll_name = ARGV[2]

db = Mongo::Connection.new.db(db_name)
coll = db.collection(coll_name)

file_name = File.basename(ARGV[0])
result = coll.find_one({"file_name" => file_name})

puts "save image to local file as '#{file_name}'"
File.open(file_name, "w+b").write(result['image'].to_s)

db.connection.close

使用例

[root@xxx ~]# ruby get_image_from_mongodb.rb out.png test image_collection
save image to local file as 'out.png'