JRuby on Railsシステム構築入門 (DB Magazine SELECTION) 橋本 吉治 |
サンプルソース
記事中で変更点の全てを説明することが困難になってきたためrailsのapp以下だけですがサンプルソースを用意しました。サンプルソースそのため、記事中では変更点のキーポイントだけを解説いたします。詳細はソースをdiffして下さい。
例外
ActiveRecordの例外をDataMapperへ置き換えます。ActiveRecord::RecordNotFound -> DataMapper::ObjectNotFoundError
ActiveRecord::RecordNotSaved -> DataMapper::SaveFailureError
検索条件(books_controller.rb)
app/controllers/books_controller.rbの検索処理を修正します。DataMapperでは全検索はモデル.allで行います。今回はborrowedがfalseのものを検索対象とします。# 書籍
@books = Book.find :all, :conditions => {:borrowed => 0}
# GAE
@books = Book.all(:borrowed => false)
ソート順(users_controller.rb)
app/controllers/users_controller.rbでは検索結果のソートを行います。# 書籍
@users = User.find(:all, :order => :name)
# GAE
@users = User.all(:order => [:name.desc])
制約(user.rb)
モデルクラスへ制約を加えてみます。対象はユーザモデル(app/models/user.rb)です。今回は
- ユーザ名に必須・一意制約
- 入力されるパスワードには6文字以上15文字以下
- 入力確認フィールド
# 書籍参考:DataMapper - Validations
validates_presence_of :name
validates_uniqueness_of :name
validates_length_of :text_password, :within => 6..15,
:too_short => "Password must be more than 6 characters.",
:too_long => "Password must be less than 15 characters."
attr_accessor :password_confirmation
# GAE版
property :name, String, :required => true, :unique=>true
validates_confirmation_of :text_password, :confirm =>:password_confirmation
validates_length_of :text_password, :max => 15,:message => "Password must be less than 15 characters."
validates_length_of :text_password, :min => 6,:message => "Password must be more than 6 characters."
attr_accessor :password_confirmation
多対多関連
GAEではbookとbookshelfの多対多の関連にpossessionの様なテーブルは必要ありません。詳しくはこちらにまとめました「chirokings: GAE+JRuby+Datamapperで多対多」def bookshelves参考:DataMapper - Associations
if self.bookshelf_ids == nil
[]
else
Bookshelf.all(:id=>self.bookshelf_ids)
end
end
def add_bookshelf(bookshelf)
self.bookshelf_ids = self.bookshelf_ids.to_a << bookshelf.id
end
def remove_bookshelf(bookshelf)
self.bookshelf_ids = self.bookshelf_ids.to_a
self.bookshelf_ids.delete(bookshelf.id)
end
private
property :bookshelf_ids, List
トランザクション
GAEでは異なるエンティティグループに属するエンティティは一つのトランザクションで実行する事が出来ません。今回のケースではbookとbookshelfのエンティティを1つのトランザクションで保存するには同一のエンティティグループに属させなければいけません。現状では同一のエンティティグループに属していないためトランザクションを行うと下記のエラーが発生します。ArgumentError (java.lang.IllegalArgumentException: can't operate on multiple entity groups in a single transaction.):Datamapperではこのあたりのことは現在進行中というとで解決策は今のところありません。おそらくこのデータモデルでは解決することは困難と考えられます。それはRDBでのデータモデルのままではGAEへの単純移行は困難になる可能性を秘めています。そのため、サンプルソースではトランザクションを行わないようにしています。
Support for some datastore features like transactions and entity groups are in progress.参考:トランザクション - Google App Engine - Google Code
参考:appengine-jruby - Google App Engine API Wrappers and Tools for JRuby - Google Project Hosting