2011年8月3日水曜日

Amazon SimpleDBってなんじゃ?(RUBY SDK鈍行編2 railsでsimpledbを使う)

前回とタイトルが微妙につながってませんが、ruby on railsのインストールが終わったので、続いてawsのsdkをつかったrailsアプリケーションを作ってみます。

aws-sdkでは、完全ではないですがrailsのサポートもしており、SimpleDBをrailsのORMとして利用することができます。方法は以下のとおりです。

まず、必要なライブラリを全てインストールします。
# yum -y install ruby-sqlite3
# yum -y install sqlite
# yum -y install sqlite-devel
# yum -y install ncurses-devel
# yum -y install readline-devel
readlineのコンパイルとインストールを行います。
$ cd /usr/local/src/ruby-1.9.2-p290/ext/readline
$ ruby extconf.rb
$ make
# make install

新規にrailsアプリを作成します。(前回と同じものです)
# cd /var/www/html
# rails new myfirstcloud -J -T
# chown memorycraft:memorycraft -R myfirstcloud
$ cd /var/www/html/myfristcloud

bundlerでインストールするgemを定義します。今回sqlite3は使用しませんが、エラー回避のため便宜上入れて起きます。
$ vi Gemfile
...
gem 'aws-sdk'
#gem 'sqlite3'
gem 'sqlite3-ruby', '1.2.5', :require => 'sqlite3'
...

awsのアクセス認証用に証明書情報を定義します。rubyコードでの記述も可能ですが、ここではYAMLで定義します。記法はconfig/database.ymlとほぼ同じです。
$ vi config/aws.yml
development:
  access_key_id: アクセスキー
  secret_access_key: シークレットキー

test:
  <<: *development

production:
  <<: *development


SimpleDBはRDBMSではなくキーバリューストアなので、db:migrateは必要がなく、属性の定義はモデルで行います。aws_sdkのSimpleDBには仮想属性というものがあり、裏側で通常Railsでサポートしているデータ型とSimpleDBの属性が以下のようなメソッドで紐付けられています。
  • string_attr
    stringの属性
  • integer_attr
    integer(整数型)の属性
  • sortable_integer_attr
    値の範囲が決まっているソート可能なintegerの属性

    範囲を:rangeで指定します。
    validates_numericality_ofで最大値と最小値の制約を適用することが一般的で、
    もし範囲外だった場合、実行時エラーを引き起こします。

    通常のintegerとちがうところとして、SimpleDBは数値型をサポートしておらず全ての値は文字列に変換されます。
    そのため、数値でのソートに問題が生じます。たとえば2と10を昇順に並べると文字列比較のため10,2の順になってしまいます。
    このsortable_integerは、この問題に対応するため0詰めして保存されます。
  • float_attr
    float(浮動小数点型)の属性
  • sortable_float_attr
    値の範囲が決まっているソート可能なfloatの属性
    sortable_integerと同じくfloat値を0詰めで保持します。

    【正のfloat】
    たとえばsortable_float_attr :score, :range => (0..10)と指定した場合、
    辞書的にソートされても問題ないように5.5は"05.5"と文字列保存されます。

    【負のfloat】
    たとえば
    sortable_float_attr :position, :range => (-10..10)
      
    のように、範囲が負の値を含んでいいた場合、すべての値を正になるようにマイナス分だけずらして保存されます。
    つまり"000"から"020"として保存されることにより、ソートを可能にしています。

    注意としては、こういった方式で表示したり入力したりした値と、実際に保存される値がことなるので、
    一度運用を開始した後に値の範囲を変更したい場合、保存済みの全ての値を更新してあげる必要があるので要注意です。
  • boolean_attr
    boolean型の属性
    なにも指定しないでnewされたとき、デフォルトはfalseです。
  • datetime_attr
    日時型の属性
    created_atとupdated_atに対して指定された場合、自動管理されます。
  • timestamps
    timestamps
    datetime_attr属性のcreated_atとupdated_atを生成するための便利メソッドです。

ここでは以下のようにモデルを定義します。
$ vi app/models/my_first_domain.rb 
class MyFirstDomain < AWS::Record::Base
  string_attr :title
  integer_attr :num
  sortable_integer_attr :sort_num, :range => 0..99
  boolean_attr :bool_val
  timestamps

  validates_presence_of  :title, :num
end

ドメインがまだ存在していない場合は、rubyコンソールから作成することも可能です。
$ rails console
> MyFirstDomain.create_domain

モデルとドメインの作成が終わったら、それ以外の部分をscaffoldで作成します。
rails generate scaffold_controller MyFirstDomain title:string num:integer sort_num:sortable_integer bool_val:boolean

最後にroutesに追加します。
$ vi config/routes.rb
Myapp::Application.routes.draw do
    # 追加
    resources :my_first_domains
end

それでは確認してみましょう。

httpd.confの設定は前回のとおりであることを確認したら、
ブラウザで
http://IPアドレス/my_first_domains
を見てみましょう。
このとおり、my_first_domainのscaffoldのインデックス画面が確認できます。


それでは、アイテムを新規作成してみます。
ためしにSort Numを範囲外の1000で 登録しようとすると、下記のようにエラーが発生します。



これを防ぐため、モデルにvalidates_numericality_ofを追加します。
$ vi app/model/my_first_domain.rb
validates_numericality_of :sort_num, :greater_than_or_equal_to => 0, :less_than_or_equal_to => 99

再度登録しようとすると、今度はちゃんとバリデーションメッセージが表示されるようになりました。


範囲内の数値で登録すると、正常に登録が成功しました。


このとおり、railsからもさくっとSimpleDBを使うことができました。

つかれた。。今日はここまで。