ハセテツがPython、というかDjangoを選んだ理由

2011-04-29
このエントリーをはてなブックマークに追加

思いっきり個人的な見解です。無知であるが故の部分も大きいと思います。

「そんなことねーぞ、こういうのもあるぞ」

っていうのがあると、教えて欲しかったりしてます。

正直、国内でのRuby人気は気になるのです。Rubyというか、RubyonRailsですよね。

2年位前は「Rubyすげえ!Railsすげえ!」だったんです。その前はPHPばっかり書いてました。

でも、RoR使うようになってフルスタックのフレームワークの便利さに魅了され、RoR一本でいくつもりでした。

まぁPHPの前はC#(ASP.NET)ばっかり書いてた頃もあったのですが。ちなみにその前はaspでした。

そんななか、Googleが導入し、GAEでも使えるPythonにも興味がありました。もともといろんな言語を使えるようになりたいとも思っていたので、新規プロジェクトの際にちと手を出してみたんですね。Python+Djangoに。

当時、Apacheにpassengerを組み合わせてRoRを走らせていたハセテツには一定時間ごとにインスタンスが終了されてしまうのが「なんだかなー」でした。アクセス数の多いサイトであれば気にならないのでしょうが、少ないサイトのだったのでリクエスト時に多少のタイムラグがあることが気になってしまっていました。

Python+Django、mod_wsgiはそれを解決してくれました。まぁmongrelでもよかったのかもしれませんが、当時は開発が止まっていた時期だったと。今はthinとかもあるから問題ないのかもしれませんね。

CakePHPやsymfonyは選択肢に入りませんでした。ステップ数が多くてリクエストごとのレスポンスが遅すぎました。APCとか使えばそれなりらしいのですが、そもそもPHPは手軽に書けるのが魅力だと思っていたので、フレームワークのお作法に従うのは違うなーと。

実際、Pythonがよかったのではなく、Djangoがよかったのかもしれません。それくらいDjangoはよくできていました。RoRのfind_by_sqlに匹敵するものがないのは残念ですが。

Djangoだとurlディスパッチャーは自分で設定というか、urlとコントローラを紐付けてやらないといけません。Railsのようにcontrollerが自動的にurlと紐付かれたりはしません。が、それが自由自在で便利でした。

フレームワークを経由しないでApacheから直接レスポンスを返す静的コンテンツを置くディレクトリの指定も簡単です。フレームワークから「ここに置け」って指定されることもありません。

Railsはループ処理のときは一件ごとにsqlを発行しましたが、結合して一気に取ってきてくれます。ちゃんとO/Rマッパーが外部結合してくれます。

Djangoも、syncdbした後にmodelの設計を変えると面倒くさいという不満はあります。まぁそれは事前にきちんと設計しておけばいいだけの話なのですが。

モジュールの多さという点では、PythonもRubyもPHPも必要なものはそろっているという印象です。「RubyにはあるけどPythonにはない」っていうのはなかったかと。

あ、PHP版のMeCabバインディングはなかったか。

あ、あとRoRってひとつのプロジェクトで複数のWebアプリって作れませんよね。

実際こうやって書き出してみると、たいした理由じゃないですね。ちっさな「うーん、なんだかなー」の積み重ねだったりしてますね。

でも、そういう小さな積み重ねって技術者にとっては大事だったりすると思います。不満だった点も、当時はそうだっただけで今はとっくに改善されているのかもしれません。

結局、Python書けるようになってもGAEのアプリは一本も書いてません。それでも、Python+Djangoを選択してよかったと思っています。

うまい感じにオチをつけられないのですが、いろいろ試した結果、もうしばらくはPython+Djangoでいってみようと思います。

メインの言語を持った上で、いろいろな言語、環境のプロジェクトがこなせるように勉強だけは欠かさずにしないといけませんね。

技術者は死ぬまで追いかけ続けるんだろうな。下りのエスカレーターを上っていくように。

立ち止まったらどんどん落ちていくんでしょうね。

RubyonRailsでOAuth経由でTwitterのタイムラインを取得する

2010-06-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>

こんな感じです。

RubyとPythonについて考えてみました

2010-04-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

RubyonRailsでページングする方法

2009-09-28
このエントリーをはてなブックマークに追加

will_paginateを利用します。とってもらくちんです。

require ‘will_paginate’

def hoge
  @items = Item.pagenate(
                  :conditions => [“hoge= ?”, hoge],
                  :page => params[:page],
                  :per_page => 30)
end

コントローラ側は以上。30レコードでページングします。find_by_sqlみたいな使い方も可能です。

  @items = Item.paginate_by_sql(
                  [“select * from hoge where hoge = ?”, hoge],
                  :page => params[:page],
                  :per_page => 30)

たいして変わりません。View側も通常のActiveRecordとの違いは

<%= will_paginate @items, :prev_label => ‘< 前’, :next_label => ‘次 >’ %>

こういうタグを記述しておけば勝手にページングアンカーが表示されるようになるくらいです。

:prev_labelは指定しなくてもOKです。デフォルトの文字列が表示されます。

 

RubyonRailsでform_tagのselect_tagを使う

2009-08-25
このエントリーをはてなブックマークに追加

#コントローラ側
@target_year_options = [2007, 2008, 2009]

#ビュー側
<%= select_tag(“target_year”, options_for_select(@target_year_options, Time.now.year)) %>

引数は「名前、option(要素配列、selectedの値)」ですね。selectedの値は省略可能です。

ビュー側に

<%= select_tag(“target_month”, options_for_select([’01’,’02’,’03’,’04’,’05’,’06’,’07’,’08’,’09’,’10’,’11’,’12’], Time.now.month )) %>

って感じで直接配列を書き込むことも可能。

<%= select_tag(“target_month”, options_for_select([[‘一月’,1],[‘二月’,2],[‘三月’,3],[‘四月’,4]], Time.now.month )) %>

これで表示は漢字、valueが数字、っていうやり方もできます。

こういうことも書き溜めておかないと、必要なときになってググるはめになるんですよね。

RubyonRailsでLike演算子を使ったあいまい検索をする方法

2009-07-07
このエントリーをはてなブックマークに追加

:conditionsにクエリ文字列ごりごり書くなら別に気にしなくてもいいのですが、まぁたいていはインジェクション対策も兼ねてプレースホルダーを使うか、シンボルを使うかのどちらかでは無いでしょうか。

ハセテツは前者です。PHPでもPEARを使っていたので、プレースホルダーを使っていました。

で、Rails(ActiveRecord)でプレースホルダーを利用している状況でLike演算子を使ったあいまい検索はどうしたらよいものか、と意外にシンプルな部分で躓いたりします。キーワード検索機能を実装しない限り、Like演算子って使わないですよね。

:conditions => [“hoge like ?”, “%#{hogeParam}%”]

上記の書き方であいまい検索ができました。手抜きではあるのですが、これでhogeParamが空白文字列であっても検索はできます。nilだったらどうしようもないですけどね。

RubyonRailsでクッキーの処理をモジュールで共通化する方法

2009-06-18
このエントリーをはてなブックマークに追加

猛烈にはまったので、これは書き残しておかないと後々後悔すると思った次第であります。もしかするとハセテツがやり方を知らないだけで意外と簡単なのかもしれません。もし「いやいや、あんたが知らないだけでこうやるとラクチンだよ」という情報お持ちの方がいたら教えていただけると非常にありがたいです。

Railsでクッキーを扱う際、コントローラに書けば特に問題はありません。ただ、メソッドをモデルやモジュール側に書いて置くと、コールしたときに怒られます。これはApplicationControllerを継承していないからのようです。といって、他のコントローラの中にメソッドを書いておいてそれをコールしても怒られます。クッキーは「自分のトコで処理しろや」ということなのでしょうか。

かといって、クッキーのチェックなどなどをすべてのコントローラに書くのはDRYに反しているのでは、と悩んでおったのです。

module HogeModule
 
  def self.included(base)
  base.class_eval{

    def set_cookies

      cookies[:key] = {:value => “hogehoge”, :path => “/”, :expires => Time.now + 45 }
      end

    }
  end

end

上記のようなモジュールを用意します。これは、このモジュールがコントローラからインクルードされるとset_cookiesというメソッドがインクルードした方のコントローラ側に展開され、selfとして扱えるということです。つまり、コントローラ自身のメソッドになる、という感じです(多分)。

あとはコントローラからset_cookiesをコールするだけです。エラーはでず、クッキーも書き込まれます。

base.class_evalの中に:before_filterを書いておけば、インクルードされるたびにフィルターも実行されます。ハセテツはbefore_filterでクッキーのチェックを行い、メソッドで書き込みを行うように書きました。

RubyonRailsでクエリを直接実行したいときの方法

2009-06-16
このエントリーをはてなブックマークに追加

ActiveRecord::Base.connection.execute(実行したいクエリ)

インデックス張りなおしたいときや更新クエリをごそっと投げたいときなんかは意外と重宝します。

これにコールバック関数とか組み合わせることができると便利なんですよね。あ、BackgrounDRb使えばいいのか。

RubyonRailsでメールを送信するサンプルをもうちょっと詳しく

2009-05-29
このエントリーをはてなブックマークに追加

RubyOnRailsで日本語メールを送信するでActionMailerの使い方を簡単に説明しましたが、これだけだと自分の備忘録にすらなっていないので追記。

config.action_mailer.delivery_method = :smtp
config.action_mailer.smtp_settings = {
  :address => ‘SMTPサーバ’,
  :port => 25,
  :authentication => :login,
  :user_name => ‘アカウント’,
  :password => ‘パスワード’
}

上記をconfig/environment.rbに追記。

送信するときには「RubyOnRailsで日本語メールを送信する」の例であれば、コントローラ等から

Hoge.deliver_sendmail

とすればOK。「Hoge」はクラスですね。「deliver_」はお約束です。アンダースコアの後ろがメソッド名になります。~というメソッドに紐付くメールを送信しなさい、っていうイメージですかね。

RubyonRailsのform_tag備忘録

2009-05-22
このエントリーをはてなブックマークに追加

頻繁に使うくせに、いつまでたっても覚えられない。ついついコピペして使いまわしちゃうから「あれ、どうやって書くんだっけ」の繰り返しになってしまう。

これは、確認も含めて整理しておこう。

<% form_tag ({:controller => ‘コントローラ’, :action => ‘アクション’}, {:method => ‘post’, :multipart => true}) do %>
  <dl>
    <dt>入力してください。「テキストボックス」</dt>
    <dd><%= text_field_tag :hoge, nil, :style => ‘width:320px;’ %></dd>
    <dt>選択してください「ラジオボタン」</dt>
    <dd>
      <label><%= radio_button_tag :status, ‘0’, ‘checked’ %>非表示</label>&nbsp;|&nbsp;
      <label><%= radio_button_tag :status, ‘1’ %>表示</label>
    </dd>
    <dt>コメントしてください。「テキストエリア」</dt>
    <dd><%= text_area_tag :comment, nil, :style => ‘width:320px;height:120px;’ %></dd>
    <dt>ファイルをアップロードしてください「ファイル」</dt>
    <dd><%= file_field_tag :file_name %></dd>
  </dl>
<% end %>

methodはデフォルトでPOSTなので、特に指定する必要はありません。ファイルをアップロードしない場合は

<% form_tag :controller =>’コントローラ’, :action => ‘アクション’ do %>

でもOKです。text_field_tagの「:hoge」は要素名、「nil」は値。アクション側で受け取るときは

params[‘hoge’]

で受け取れます。

Railsであればform_forが猛烈に便利なのですが、すべてのフォームがモデルとイコールなわけではないので、やっぱりform_tagの出番も増えます。

設計が間違ってるのかなぁ。