6月 18

OAuthを使えるようになっておけば今後いろいろなマッシュアップに便利だろうと思い、試してみました。RoRで書いたのは、最近ご無沙汰過ぎてあまりに覚えてなかったのでリハビリを兼ねたわけです。

class TwitterAuth
require ‘oauth’

def self.consumer

OAuth::Consumer.new(
[Consumer key],
[Consumer secret],
:site => “http://api.twitter.com”
)

end

def self.request_token(_token, _secret)

OAuth::RequestToken.new(
consumer,
_token,
_secret
)

end

def self.access_token(_token, _secret)

OAuth::AccessToken.new(
consumer,
_token,
_secret
)

end

end

まずは上記のクラスを作成。OAuth関連の処理はこっちにやらせます。で、次がコントローラー。

require ‘rubytter’

class AuthController < ApplicationController

def index

request_token = TwitterAuth.consumer.get_request_token(:oauth_callback => “http://#{request.host_with_port}/auth/callback”)
session[:request_token] = request_token
redirect_to request_token.authorize_url

end

def callback

_token = session[:request_token]
request_token = TwitterAuth.request_token(_token.token, _token.secret)
access_token = request_token.get_access_token(
{},
:oauth_token => params[:oauth_token],
:oauth_verifier => params[:oauth_verifier]
)
session[:request_token]=nil
_account = {
:user_id => access_token.params[:user_id],
:token => access_token.token,
:secret => access_token.secret
}
session[:account] = _account
redirect_to :action => “timeline”

end

def timeline

_account = session[:account]
token = TwitterAuth.access_token(_account[:token] , _account[:secret])
_twitter = OAuthRubytter.new(token)
@user_timeline = _twitter.user_timeline(_account[:user_id],:count => 100)

end

end

def timelineが自分のタイムラインを取ってくるところで、「:count=>100」と指定しているのは「新着100件取ってきて」っていうことです。ここを指定しないでおくと規定値では20件取得してくれます。def callbackでセッションに入れたuser_id、token、secretをデータベース等に保存しておけば次回以降はこれらだけで認証とツイートの取得ができます(というか認証自体はtokenとsecretだけでOK)。

Twitterのアプリケーション登録申請で登録する際、コールバックURLを指定しないとWebアプリケーションとして登録されません。「開発中だからURLなんて決まってないよ」っていうケースでも、適当なURLを登録しておいてください。どうせ実際のコールバックURLはRubyのスクリプトで指定しなおしています。ハセテツはここに気が付かず、そこそこの時間を浪費しました。

で、タイムラインを表示するviewは

<ul>
<% for item in @user_timeline do -%>
<li><%= item.text %></li>
<% end -%>
</ul>

こんな感じです。

Tagged with:
5月 11

前回のエントリが結局フレームワークの話になってしまったため、新しいエントリを書きました。

同じような処理をさせた場合、どの言語が一番早いのか。非常に気になるところでありますが、試したことがありませんでした。今回試してみたところ、意外な結果が出たのです。

下の方に書いたそれぞれのプログラムを実行した結果の、プログラム内部で計測したミリ秒を比較してます。

PHP Ruby Python
2.80秒 0.36秒 0.93秒

3回計測した平均です。同じ処理をさせるプログラムを書いたつもりですが、本当にフェアなものになっているのか正直自信がありません。そもそもPHPはWebアプリを主な目的としているとのことなので、こういう処理は得意としていないのかもしれない。

また、それぞれのプログラムのループ内2行目、文字列連結の部分をコメントアウトして実行してみると、これまた意外な結果が出ました。

PHP Ruby Python
0.07秒 0.06秒 0.39秒

PHPは文字列連結が苦手なんだろうか。暗黙的な型変換にコストがかかるのだろうか、等々考えてしまいます。それとも秒を求める部分がネックなんですかね。その辺は今後追っていきます。

ただ、これまでPythonの方がRubyより早い、と思っていたために自分の無知さに猛烈に恥ずかしい思いをしています。

実際にMySQLと連携するバッチを書いたときにはRubyの方が遅かったり、Railsアプリがもっさりだったり、「速い」という印象がまったくありませんでした。が、それはある特定の面しかみていない上での思い込みだったのかもしれません。

これはRailsが遅いのか、もしくはMySQL/Rubyが遅いのか。当時の書き方がマズかったのか。今後、いろんなケースでこういった比較をしてみようかと。

今回の検証がすべてではないし、これが答えだとも思っていません。また、そういう意図を含んだエントリではありません。今回の検証だって、特定の面しか見ていません。が、あまりに意外な結果だったため、自戒の念を含めてブログに書きました。

「こう書くともっとフェアだよ」「こういうテストの方がいいんじゃない」等、アドバイスいただけるとうれしいです。

フレームワークまで含めた検証した方が現実的なのだろうか。。。


PHP

#!/usr/bin/php
<?
function microtime_float()
{

list($usec, $sec) = explode(” “, microtime());
return ((float)$usec + (float)$sec);

}
$_start = microtime_float();
$_sec = date(’s’);

for($i=1;$i<100000;$i++)
{

$_val = (mt_rand(0, 100) + $i) / $i;
$_str = $_val.date(’s’);

}

echo microtime_float() – $_start;
?>

Ruby

#! /usr/local/bin/ruby

i=1
_start = Time.now

99999.times do

_val = rand(100) / i
_str = _val.to_s + Time.now.sec.to_s
i += 1

end

p (Time.now – _start).to_f

Python

#!/usr/bin/python
# -*- coding: utf-8 -*-
import datetime
import random

_start = datetime.datetime.now()

for i in range(1, 100000):

_val = random.randint(0, 100) / i
_str = str(_val) + str(datetime.datetime.now().second)

print datetime.datetime.now() – _start


検証環境

CPU:Xeon 1.86GHz
メモリ:2GB
OS: CentOS5.4 32bit
PHP:5.2.11
Ruby:1.8.7
Python:2.5.2

Tagged with:
4月 27

ハセテツは複数の言語を状況に応じて使い分けてきましたが、最近のWeb系開発はPython(+Django)がメインになってきています。

ちょっと前までRuby(+Rails)だったのですが、いろいろと考えるところもあり、乗り換えました。その乗り換えた理由をまとめてみようと思います。

まとめてみたら「やっぱりRailsじゃね?」となるかもしれません。w

Ruby(+Rails)

  • Rails便利すぎる。
  • コントローラとモデルが別々のファイルになってくれるのはソースが追いやすい。
  • Railsを通さない画像やCSSはpublicフォルダに置けばよいのはわかりやすい。
  • urlディスパッチャーがいまいち使いにくい。(知らないだけかも)
  • APサーバはmongrel一択?
  • VirtualHost使おうとするとApache+Passenger(mod_rails)だが、これが重い。(チューニングで速くなるのかも)
  • というか、Railsがそもそも重い。
  • ちゅーか、Rubyが重い、遅い。
  • PassengerはWindowsじゃ動かない。
  • mongrelもPassengerより激速軽快かというと、そうでもない。
  • gem便利すぎ。
  • ワンライナで書く人が多くて、Perlとおなじ匂いがする。

ハセテツが使っていたRubyは1.8で、速くなったといわれる1.9には触れていないのでもしかすると古いのかもしれません。でも、Railsって1.9には対応してないですよね?(本日現在)

Python(+Django)

  • Django便利すぎる。
  • 日本語の書籍、情報が少なすぎる。(ハマるとキツい)
  • modelが一枚のファイルなので、大量のmodelがあると可読性が激しくダウン。
  • viewファイルをフォルダで分けたくても、アプリケーションフォルダ直下以外にviewファイル置くなら「sys.path.append」しないといけない。(違う?)
  • urlディスパッチャーのカスタマイズが超便利。
  • mod_pythonが使えるので、Windows環境だろうがLinux環境だろうが気にせずVirtualHostが使える。
  • 速い。
  • 日本語大変。Shift_JIS怖い。
  • easy_installでパッケージのインストールは楽だが、管理が悪夢。

メリットとデメリットが入り乱れました。見難くてすいません。

結局フルスタックのフレームワークということで、DjangoとRailsに関しては一長一短だと思います。個人的にはRailsの方が良くできてたかなぁと。

最終的に、「RubyonRailsは重い」というオチになってしまうのです。Rubyも、Railsも、です。ただ、これはRuby1.9が実は劇的に速くなっていて、1.9に対応したRailsがリリースされたらすべて解決されるのかもしれません。

それでも、いまのところPythonの軽快さ、シンプルさに満足しています。あと、GAEでPythonが動くのもいいですよね。

「Googleが導入した言語」というのがハセテツ的に琴線に触れたのかもしれません。

ミーハーですいません。w

Tagged with:
8月 13

もう全部UTF8にしたいです。

require ‘kconv’

StrUTF8   = 文字列.toutf8
StrShiftJIS = 文字列.tosjis
StrEUC   = 文字列.toeuc

見たとおり、上からUTF8に変換、Shift_JISに変換、EUCに変換、です。

Tagged with:
6月 17

RubyでHTTP経由でのXMLの受信と解析でGETする方法は書きましたが、POSTまでは書いていませんでした。今回はRubyでPOSTする方法です。GETで猛烈に長いクエリをつければPOSTできなくても同じことが実現できますが、まぁそこは気にせず。

require ‘net/http’
Net::HTTP.version_1_2
http = Net::HTTP.new(ホスト名, 80)
response = http.post( ‘/hoge.php’, ‘a=hoge&b=hogehoge’ )
p response.body

これだけ。ホスト名にはhttpは付けません。ポート番号は省略しても大丈夫です。Content-Type等は必要に応じて。newするときの第三引数です。「application/x-www-form-urlencoded」でいいのかな?ハセテツはつけてませんが、きちんとPOSTできてます。あー、相手がUTF8じゃない場合とかは文字コードの指定が必要かも。

responseの中身を見ればHTTPステータスコードとかも入っていると思います。その辺は割愛。

次はファイルのアップロードのやり方なんかも調べてみましょう。使うかどうかは微妙な気もしますが。

Tagged with:
5月 27

まぁ簡単にいうとRSSリーダーみたいなことをしたいときに使います。相手がRSSじゃなくてもOKです。Web上のコンテンツを読み込みたいときに使います。ただ、今回のサンプルだとgetしかできないので、制限はあります。

require ‘open-uri’

open(“http://www.tt-house.com/atom.xml”){|f|
  data = f.read
  xmldoc = REXML::Document.new data
  xmldoc.elements.each(“feed/entry/title”){|element|
    p element.text
  }
}

文字コードのことは気にしてません。

これでハセテツラボRSSのタイトル一覧が取得できます。他のサービスとのマッシュアップ等にも使えますが、やっぱりデータのpostもできないと使い勝手は悪いですよね。

postをするサンプルは次回にしましょう。

Tagged with:
3月 13

RubyonRailsアプリケーションでサーバサイドでファイル圧縮、パスワードの設定をしてダウンロードさせる必要があったので調べてみました。

ZipRubyがあったりRubyZipがあったり、どっちがどうなんだか、相変わらずRubyは混乱します。今回は評判のよさそうなZipRubyを使いました。gemでインストールできて、バージョンは0.2.9でした。バージョン低いのがちと気になります。

gem install zipruby

これだけでインストールは終わりです。

require ‘rubygems’
require ‘zipruby’

Zip::Archive.open(‘hoge.zip’,Zip::CREATE) do |arc|
  arc.add_file(‘test.pdf’)
end

Zip::Archive.encrypt(‘hoge.zip’, ‘password’)

コレだけです。簡単すぎる。

複数ファイルをひとまとめにしたい場合は

arc.add_file(‘test.pdf’)

 

を繰り返せばOK。ただ、フォルダごとごっそり圧縮、という方法は不明。フォルダ名を引数に指定したら怒られてしまいました。当然の結果。

最後の行がパスワードの設定です。ZIPファイル作るときにパスワードを設定するのではなく、既存のZIPファイルに対してパスワードを設定する、というイメージですね。Lhaplusではちゃんと解凍できました。

Tagged with:
3月 12

MySQL/Ruby と Ruby/MySQL の二つがあるようです。どっちがどっちか混乱しましたが、MySQL/Rubyがgemでとってこれて、Cで書かれたAPIのようです。Ruby/MySQL はRubyで書かれているようで、比較的低速らしいです。今回はMySQL/Rubyを利用しました。

gem install mysql

で一式インストールできます。PHPのPEARやRubyのgemは、一度つかったらやめられません。これは堕落なのでしょうか。

で、今回はWindows上にMySQL5.0をインストールしてつないでみたのですが、バリバリ文字化けました。DBはUTF8で作ってあって、ソースも以下のようにUTF8であることを明記していました。

require ‘rubygems’
require “mysql”
require ‘iconv’

$KCODE = ‘UTF-8′

db = Mysql::connect(“ホスト名”, “ユーザ名”, “パスワード”, “DB名称”)
rs = db.query ‘クエリ’
rs.each do |item|
  p item[0]
end

なんでなんで?と調べていたら、my.ini(あー、iniってあたりがWindowsだなー、Linuxだとmy.cnfだったかな?)の[mysqld]に

default-character-set=utf8
skip-character-set-client-handshake

の追記が必要らしい。これはクライアントからの接続時に「文字コードはUTF8でっせ」とデフォルトで設定してあげるためのものらしいです。「set names utf8」と同じ意味ですね。これで文字化けずにWindows上でRubyとMySQLを利用することが出来るようになりました。

これまではC#とSQL Serverで統計とか集計のプログラム書いてたけど、Rubyの方がラクチンなんですよね。Railsばっかり注目されてますけど、Rubyは便利ですよ。

 

Tagged with:
12月 30

Datetimeオブジェクト.strftime(“%Y/%m/%d %H:%M”)

上記で、「2008/12/30 3:42」といった感じでyyyy/mm/dd HH:MM形式で出力される。まぁどの言語も大して変わりませんな。

Tagged with:
12月 25

p sprintf(%0#{5}d,1)

「00001」と出力されます。
printfとは違い、文字列オブジェクトが返ってきます。

 

Tagged with:
Get Adobe Flash playerPlugin by wpburn.com wordpress themes
preload preload preload