ヘンシュウチョさんの、
「RailsだとWeb APIとか自動生成できるってホント?俺に教えてよ!つーか勉強会やろうぜ」
という発言を切欠に小勉強会をやってきました。
ヘンシュウチョさんはオープンソースXML DB eXistの話。XPathやXQueryなどXML関連は仕様の分裂や議論が絶えないので深追いや混乱が楽しいですね。eXistの日本語ドキュメントは殆どなさそうなので是非公開してほしいです。
yoshukiさんはvimやscreen関係の開発環境の話でした。俺なんかはすぐ開発環境をおそろかにして生産性を下げてしまうので非常に参考になりました。
俺は「土日でサービス作れるようになる」を目指しているので、RESTfulアプリケーションの簡単作成方法を話ました。
スライドだけだとさっぱりなので手順とソースも上げとこうと思います。
ソース:
手順:
プロジェクトを作成。(面倒なのでsqliteを使います)
$ rails rest-todo -d sqlite3
$ cd rest-todo
scaffold_resourceジェネレーターを使って、Controller, Migrationファイル, route.rbファイルへの設定追加をします。
$ ruby script/generate scaffold_resource Task name:string completed:boolean created_at:timestamp updated_at:timestamp
$ tree app
app
|-- controllers
| |-- application.rb
| `-- tasks_controller.rb
|-- helpers
| |-- application_helper.rb
| `-- tasks_helper.rb
|-- models
| `-- task.rb
`-- views
|-- layouts
| `-- tasks.rhtml
`-- tasks
|-- edit.rhtml
|-- index.rhtml
|-- new.rhtml
`-- show.rhtml
migrateしてからサーバーを起動します。
$ rake db:migrate
$ ruby script/server
生成された一覧画面。
Web APIでのCRUDをirbから確認。
$ irb -r 'net/http'
> http = Net::HTTP.start('dev', 3000)>
puts http.get('/tasks.xml').body
>
puts http.get('/tasks/1.xml').body
>
http.post('/tasks.xml', 'task[name]=task3')
>
puts http.get('/tasks.xml').body
>
http.put('/tasks/3.xml', 'task[name]=task3...!!??')
>
puts http.get('/tasks/3.xml').body
>
http.delete '/tasks/3.xml'
>
puts http.get('/tasks.xml').body
認証機能を追加。authenticatedジェネレーターでuserモデルを使ってaccountコントローラーを生成します。
$ ruby script/plugin install http://svn.techno-weenie.net/projects/plugins/acts_as_authenticated
$ ruby script/generate authenticated user account
$ rake db:migrate
出来たDBを確認。
$ sqlite3 db/development.sqlite3
SQLite version 3.3.8
Enter ".help" for instructions
sqlite>
.tables
schema_info tasks users
sqlite>
.schema tasks
CREATE TABLE tasks ("id" INTEGER PRIMARY KEY NOT NULL, "name" varchar(255) DEFAULT NULL, "completed" boolean DEFAULT NULL, "created_at" datetime DEFAULT NULL, "updated_at" datetime DEFAULT NULL);
sqlite> .schema users
CREATE TABLE users ("id" INTEGER PRIMARY KEY NOT NULL, "login" varchar(255) DEFAULT NULL, "email" varchar(255) DEFAULT NULL, "crypted_password" varchar(40) DEFAULT NULL, "salt" varchar(40) DEFAULT NULL, "created_at" datetime DEFAULT NULL, "updated_at" datetime DEFAULT NULL, "remember_token" varchar(255) DEFAULT NULL, "remember_token_expires_at" datetime DEFAULT NULL);
login_requiredメソッドがおかしくて(Basic認証の方だけ)100%認証が通らないのでオーバーライドします。
$ vim app/controllers/application.rb
include AuthenticatedSystem
def login_required
username, passwd = get_auth_data
if self.current_user == :false && username && passwd
self.current_user = User.authenticate(username, passwd) || :false
end
logged_in? && authorized? ? true : access_denied
end
タスクのCRUD全部に認証をかけます。
$ vim app/controllers/tasks_controller.rb
class TasksController < ApplicationController
before_filter :login_required
(略)
end
Jester.jsを使ってJavaScriptからWeb APIと認証の動作を確認します。
$ wget 'http://svn.thoughtbot.com/jester/tags/rel-1.3/jester.js' -O public/javascripts/jester.js
$ vim app/views/layouts/tasks.rhtml
<%= javascript_include_tag :defaults %>
<
%= javascript_include_tag 'jester' %
>
$ mv app/views/layouts/tasks.rhtml app/views/layouts/application.rhtml
FireBugsから確認します。認証が必要なリソースにアクセスしようとするとBasic認証のWindowが表示されます。
Jester.jsでCRUDの確認。(実際には_methodパラメータによるメソッドエミュレーションを使っているのでPUTやDELETEがPOSTになっています。)
通常のページとWeb APIを同じロジックで認証できるのはシンプルですっきりした感じがします。派生する話題も色々ありそうで今後も手っ取り早い作り方をチェックしていきたいと思います。