Home > Tags > Ruby

Ruby

RubyでDuckTyping

今日、知人に「DuckTypingのメリットが今一ピンとこない」と言われて実際にコード書いて説明をしたのだけれども、せっかくなのでエントリにまとめる。

DuckTypingとは、動的言語の柔軟性を表現する概念で以下の格言に由来する。

“If it walks like a duck and quacks like a duck, it must be a duck”
(もしもそれがアヒルのように歩き、アヒルのように鳴くのなら、それはアヒルである)

つまり、アヒルのように振る舞うものは、実際にそれが何であろうとアヒルと見なすということになる。

もうちょっと言語よりな言い方をするのであれば、あるオブジェクトどのクラスに属するか考慮せず、どのようなインターフェースを持つかに注目するのがDuckTyping。

DuckTypingにおいて重要なことは「明示的な型チェックを避ける」と言うことで、どう言うことかと言うと

上記のようなコードを書いてしまうと、Duckクラスもしくはそれらを継承したクラスしか扱えなくなり、動的言語のメリットが失われてしまう。

その知人に紹介した簡単なDuckTypingの例が以下。

ここではwriteメソッドさえあれば、渡されたオブジェクトが何かは問わない。これをもうちょっと実際に使うようなコードに書き直すと以下のようになる。

やっていることは、ほとんどwrite_messageと同じだけど、こちらの方がまだピンとくると思う。Loggerはログを書き出すだけの簡単なクラスだが、DuckTypingを用いることによって、その書き出し先を柔軟に変更することができる。

実際はどんなオブジェクトが渡されるかわからないのでrespond_to?でメソッドの有無のチェックぐらいはした方がいい。

エラー処理をもうちょっと別の方法を取ってみる。

こちらの方法を取ると、仮に呼び出したメソッド内で例外が発生した場合もうまく処理することができる。個人的には大体こちらの手段を取ることが多い。

結構長くなったけど、大体こんな感じ。DuckTypingは慣れない人からするとよくわからないところも多いと思うけど、うまく使えれば結構便利な機能。使いすぎは禁物だけどうまく使っていくといいだろう。

Rails2.0.2から2.2.2に上げたらFileColumnがNameErrorだした。

自分の担当している案件のRailsのバージョンを2.0.2から2.2.2に上げたら以下のようなエラーが発生。

uninitialized constant FileColumn::ClassMethods::Inflector (NameError)

これの対応は/vender/plugin/file_column/lib/file_column.rbの以下の部分を

my_options = FileColumn::init_options(options,
                                                 Inflector.underscore(self.name).to_s,
                                                 attr.to_s)

以下のように書き換えればとりあえず対応できる。

my_options = FileColumn::init_options(options,
                                                 self.name.to_s.underscore,
                                                 attr.to_s)

ちゃんちゃん。

RSpecの結果をHTMLで出力する方法

RSpecにはオプション-hがあるので、そこでフォーマットを指定してやればいい。以下、Railsの例。

RAILS_ROOT$ spec spec -f h:spec/spec_report.html

これで、specディレクトリにspec_report.htmlが出力される。

Re:Ruby初心者の2冊目はなに?

Ruby初心者の2冊目はなに?
Rubyの「最初の二冊目」は何? に答えてみる。 – どんなジレンマ

id:hrkt0115311さんに名前を出してもらったことだし、簡単に紹介しておこうと思う。crossreviewに書いてない本も多いしね。と言うかしょっぱなからそうなんだけど。

Rubyレシピブック第二版

Rubyレシピブック第二版

id:hrkt0115311さんもすすめてたけど、たのしいRubyを読んだのならこれもオススメ。大体初心者が思うあれがしたい、これがしたいはここを参照すれば載ってると思う。ただ、なにができるかは書いてあるけど、それらで何かを作る方法は書いてないので作りたいものが曖昧だとこれ1冊だとどうしたらいいかわからなくなるかも。

Rubyで作る奇妙なプログラミング言語

Rubyで作る奇妙なプログラミング言語

そこでオススメするのがこの「Rubyで作る奇妙なプログラミング言語」。この本1冊あればRubyで言語を実装できるようになる。もちろんタイトルにある通り「奇妙なプログラミング言語」をだけど。もしBrainfuckと言った奇妙な言語を触ったこともない、聞いたこともないと言うのならそれらを知る意味でもこの本をオススメしておく。Brainfuck楽しいよ、Brainfuck。

初めてのRuby

初めてのRuby

これまたid:hrkt0115311-22さんと被ってるけど、オススメなのだから仕方がない。まぁ初心者の二冊目としては難しい部類かもしれないが、ある程度Rubyに慣れてきたら読んでみるといいと思う。

ちなみにRubyにも当然マニュアルが存在するが、初心者が読むには正直内容が難しい。この本を読めばマニュアルが読めるようになると著者のyuguiさんも言っていた記憶があるので、マニュアルの前にこちらを読むことをオススメする。

追記: るりま(Rubyリファレンスマニュアル)の知名度が低いそうなのでリンクを載せておく。まぁメンテされてるのはこっちのはずだから本来はこっちを載せるべきだったのかもしれない。thx Sixeight。
るりまWiki

恋するプログラム

恋するプログラム

yharaさんの「Rubyで作る奇妙なプログラミング言語」と同様にこちらも何かを作ることを題材としている。内容も人工無脳を作るというものなのでプログラマなら少なからず心魅かれると思う。まぁちょっと内容が古いかもしれないけど。

だがしかし。これ多分もう売ってないと思う。残念至極。ちょっと前にこの本の出版に関わった人から「復活させたいんだけどねー」と聞いた記憶があるが今のところ特に予定はなさそうだ。

Enjoy Programming!!

まぁ大体こんなものか。一応Railsの本ははずしたけど、Webアプリ作りたいなら苦労を知らないとフレームワークの仕組みがわからないとか変に考えずとりあえずやってみればいいと思う。仕組みは後からでもいくらでも学べるし。

とは言うものの、プログラミング自体が初心者のようだからWebプログラミングみたいに言語以外の知識が必要となるものを最初にやろうとすると混乱しがちなのでとりあえずはRubyを中心に学べばいいと思う。Webアプリを作る以外にもプログラミングを楽しむ方法はいくらでもあるし。

Enjoy Programming!!

JRubyとProcessing1.1でaction-coding!

せっかくProcessingも正式版になったことだし、少しaction-codingで遊んでみる。

まずはJRubyをインストール。面倒なのでバイナリで。環境はMac OSX 10.5.5。

http://dist.codehaus.org/jruby/からjruby-bin-1.1.5.tar.gz(バージョンは適宜読み替え)をダウンロード。現時点では1.1.5をインストールしておけば大丈夫だろう。解凍したら適当な位置に移動。

$ tar zxvf jruby-bin-1.1.5.tar.gz
$ sudo mv jruby-bin1.1.5 /usr/local/bin

次にパスを通す。

export JRUBY_HOME=/usr/local/bin/jruby-1.1.5
export PATH=/opt/local/ghc/bin:/opt/local/bin:/opt/local/sbin:/usr/local/bin:$JRUBY_HOME/bin:$PATH

PATHは環境によって違うと思うので適当に読み替え。sourceで読み込ませてjrubyコマンドが使えればOK。

$ source ~/.zshrc
$ jruby -v
jruby 1.1.5 (ruby 1.8.6 patchlevel 114) (2008-11-03 rev 7996) [i386-java]

次にaction-codingをインストールする。基本的にはチュートリアルに従っておけばいい。一点だけProcessing1.0からファイルの位置が変っているので以下の作業がいる。Processingのパスは普通にインストールしていれば同じだと思うけど、違う場合は適宜読み替えで。

$ pushd /Applications/Processing.app/Contents/Resources/Java/lib
$ cp ../core.jar .
$ popd

最後に、config.yamlの修正。

p5home: /Applications/Processing.app/Contents/Resources/Java

これでサンプルのアプリケーションが実行できるはず。

 jruby aco.rb examples/basics/arrays/array_objects.rb

後はチュートリアルに従って、サンプルを修正してリアルタイムに変更が反映されるのを楽しみつついろいろ弄ればいいんじゃないかな。(setup内の編集だけは、ウィンドウにフォーカスをあててCmd+rもしくは、Ctrl+rでリロードが必要)

結構、変更がリアルタイムに反映されていくのは楽しい。スケッチっていう観点からしたらわざわざビルドするより、こっちの方が気楽でいいよね。

Macでgem install mysqlをする方法

Rails2.2からmysqlのアダプタが付属していないので各個人でインストールする必要があります。gemで入れようとするとエラーがでると思うので以下のように対応してください。

$ sudo gem install mysql
$ cd /opt/local/lib/ruby/gems/1.8/gems/mysql-2.7/
$ sudo ruby extconf.rb --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config
$ sudo make
$ sudo make install

パスに関しては、人によって違うかもしれませんが適宜読み替えてください。

追記

$ sudo gem install mysql -- --with-mysql-config=/opt/local/lib/mysql5/bin/mysql_config

これでも大丈夫らしい。

Rails2.2のi18n(国際化)を簡単に試してみた

11月21日にRails2.2が正式リリースされた。 RCなどでチェックしてた人は既に知っているかもしれないけど、2.2からデフォルトでi18n(国際化)対応がされている。

ちなみにi18nというのはinternationalizationの頭と後ろのiとn、文字数が18文字というところから来てるらしい。

とりあえず、まずはアプリの作成。

$ rails i18n_demo

作成されたファイル群の中にconfig/locales/en.ymlというファイルが出来ていると思うけど、これが翻訳ファイルになる。今回は英語と日本語を用意しようと思うので、en.ymlをコピーしてja.ymlを作成する。

$ cp config/locales/en.yml config/locales/ja.yml

翻訳ファイルを修正しようにも、そもそもアプリケーションが出来ていないので、scaffoldで簡単に作ってしまおう。

$ ruby script/generate scaffold entry title:string body:text
$ rake db:migrate

とりあえずは適当にサイトタイトル的なものでも作ってみよう。翻訳ファイルに関しては元々あった内容は削除してしまっていい。

# config/locales/ja.yml
ja:
  site_title: サイトタイトル

一応英語も。

# config/locales/en.yml
en:
  site_title: SiteTitle

Viewの修正。

# app/views/entries/index.html.erb

<%= I18n.t :site_title %>

この状態でサーバーを起動し、http://localhost:3000/entriesにアクセスしてみる。「SiteTitle」という文字が表示されているはずだ。この状態だとまだ言語がデフォルトの英語の設定になっている。多分、ブラウザの言語設定とかは見てなさげ?。ちょっとソースを見てないのでまだ未確認。もしかしたら、リクエストのヘッダーを見て言語を決める部分は自分で実装しなきゃいけないのかもしれない。

なんにせよ、日本語で表示したい場合は以下のようにする。

# config/environment.rb
# 最下行に追加
I18n.default_locale = "ja"

これで再度アクセスすれば「サイトタイトル」と表示されているはずだ。

次にGETパラメータで言語が切り替わるようにしてみよう。

# app/controllers/application.rb

before_filter :set_locale
def set_locale
  I18n.locale = params[:locale]
end

これでhttp://localhost:3000/entries?locale=enで「SiteTitle」と表示されているはずだ。

次にモデルの日本語化をしてみよう。まずはエラーメッセージを出すためにバリデーションを追加する。

# app/model/entry.rb
class Entry < ActiveRecord::Base
  validates_presence_of :title, :body
end

http://localhost:3000/entry/newでフォームに何も入力せず送信すればエラーがでるので英語で表示されていることを確認する。

普通のバリデーションのエラーとは違うエラーがでているけど、これは翻訳ファイルをちゃんと書いてないからでているエラー。英語の方はちょっと面倒なので無視するが、とりあえず日本語化をすすめる。

#config/locales/ja.yml
ja:
  site_title: サイトタイトル
    activerecord:
      errors:
        template:
          header: "{{model}}でエラーが発生しました。"
          body:   以下のエラー内容を確認してください。
        messages:
          blank:  が空白です。
      models:
        entry: エントリー
      attributes:
        entry:
          title: タイトル
          body: 本文

以上の修正をして、もう一度エラーを出してみるとエラーが日本語に変わっているはずだ。翻訳ファイルのどの部分がどの部分に対応してるかは雰囲気でわかると思う。

今回は必要な部分だけ翻訳したけど、もうちょっとちゃんとした翻訳ファイルが必要ならRailsをローカライズするも参考にするといいと思う。

諸々めんどくせー!って人は松田さんのRails 2.2の I18nによる日本語化を最も簡単に行う方法へどうぞ。gemで一発です。

まだ2.2はリリースされたばかりで、i18nまわりの日本語の情報はあまり多くはないと思うけど、そこまで複雑な仕組みでもないし、翻訳ファイルに関して言えば基本的な部分(ActiveRecordとか)は使い回しができるので手間もそこまで大きくはないと思う。ブラウザの言語設定での判断もそのうちプラグインがでてくるんじゃないかと思っている。

「国際化とか必要ないよー」の人も、バリデーションのエラーを日本語化するのにgettextを入れる必要がなくなったりとこれでかなりラクになるんじゃなかろうか。

RubyGemsのupdateの方法が変わっていた

せっかくMerb1.0がでたことだしインストールしてみようかと思ったら、gemを1.3以上いれやがれ!と怒られてしまった。それならアップデートするかーと思い、update –systemをやってsuccessと出たはいいけど、gem -vで1.2と表示される。MacPortsの方でアップデートして、1.3入れても-vは1.2でなんぞーとか思っていたらupdateの方法が変わってたみたい。

以下、update手順。

  1. RubyForgeからrubygems-upate-1.3.1.gemをダウンロード
  2. $ sudo gem install rubygems-update-1.3.1.gem
  3. update_rubygemsというコマンドができてるので実行。
    $ sudo update_rubygems
  4. 完了

これで無事、RubyGemsの1.3.1がインストールされた。

$ gem -v
1.3.1
$ sudo gem install merb
・・・
・・・
37 gems installed

これでOK。37gems installedってのも凄いな。

RailsでMySQLとPostgreSQLを同時に扱う方法(+問題点)

プラグインとか無しで、複数のDB(MySQLとPostgreSQL)を扱う方法。Rails2.1でしか試してないけど、多分1.2とかでも大丈夫。多分。MySQLとPostgreSQLの接続ライブラリはgemからインストールしておくこと。

まずは、database.ymlに扱うデータベースの定義を書く。

development:
  adapter: mysql
  encoding: utf8
  database: db_development
  username: root
  password:

test:
(面倒だから略)

production:
(面倒だから略)

psql_development:
  adapter: postgres
  encoding: utf8
  database: ma2_mcd
  username: root
  password:

psql_test:
(面倒だから略)

psql_production:
(面倒だから略)

次にPostgreSQLに接続させたいモデルを編集する。例えば、ProfileモデルはPostgreSQLの方に接続させたい場合は以下のようになる。

class Profile < ActiveRecord::Base
  establish_connection("psql_#{RAILS_ENV}".to_sym)
end

establish_connectionにシンボルでdatabase.ymlの定義を渡せば、そのモデルはその定義のデータベースに接続する。本番、テスト、開発でそれぞれ定義が違うだろうから、RAILS_ENVで今起動している環境の定義を呼び出すようにしてやる。

追記

上記の設定で一応アプリは動作するけど、いくつか問題点があるのでそれをメモしておく。

マイグレーションの使い分けはどうする

例えば、db/migrateにcreate_hoge_for_psql.rb(数値は略)とcreate_foo_for_mysql.rbと合った場合、それをどう実行するかが問題になってくる。

普通にrake db:migrateやrake db:migrate RAILS_ENV=psql_developmentとやったら、hogeとfooが両方とも作られてしまう。こちらとして望んでるのは、hogeがPostgreSQLのみ、fooがMySQLのみにできて欲しい。

うーむ、弱った。

数字を使わずに素数判定

86のSkypeチャットで話題になったのでちょこちょこっと書いた。普通にループして比較するだけお。もっといい方法あるんだろうけど、とりあえずはよしとする。

class Integer
  def prime?
    return false if self.zero? || self == [[]].size
    ([[],[]].size...self).each do |i|
      return false if (self%i).zero?
    end
    true
  end
end

suztomoのやつ。
http://d.hatena.ne.jp/suztomo/20080918/1221746629

Home > Tags > Ruby

Feeds
Meta
Others

Return to page top