ruby on rails 活用のコツ - ko.meadowy.netnay/?c=plugin;plugin=attach_download;p=ruby+on...ruby...
TRANSCRIPT
Ruby on Rails と 私
2006年夏
Web家計簿「小槌」で
ドリコム Award on Rails 大賞&審査員特別賞
http://www.kozuchi.net/絶賛? 運用中!!
Ruby on Rails をはじめた理由
● Web家計簿が作りたかった
● 会社を辞めたので時間があった
● 慣れ親しんだJavaで作りたかったが、ダンナ
がサーバを用意してくれなかった orz
泣く泣くイヤイヤ Ruby on Rails を始めた
Ruby on Rails サイコー
あっという間に大好きに!
(^0^)/
なぜなら
● 早く作れる
● 行き届いている
● 複雑なものも十分作れる 何でもできそう
自宅にインフラ担当も確保できる
仕事が Ruby on Rails 一色に
● Java 7年
● Award
● Ruby on Rails 1年 ←いまここ– 家計簿
– ECサイト
– コミュニティ系サイト
– 業務アプリケーション
本日のテーマ
Ruby の基礎知識 - Javaと比べながら
RoR のどんなところを良く使っているか
RoR の苦手な分野
RoR を活かすための開発スタイル
RubyとJava 言語・記法の違い(1)
● すべてがオブジェクト
● 動的型付け
● コンパイル不要
● 文末の ; が省略可能
● # でコメント
● メソッド呼び出しの()を省略できる
● メソッド名に一部の記号が使える
RubyとJava 言語・記法の違い(2)
● 慣習として、変数名やメソッドは小文字で_
でつなぐ
● パッケージはなく Module で代用
● end でブロックを閉じる
● return を省略できる(最後の評価値を返
す)
irb で試してみる
Hash Ruby – の根幹
{:name => "Yasuko"}
{:url => {:controller=> 'Order', :action => 'update'} }
has_many :members, :class_name => 'GroupMember', :foreign_key => 'g_member_id'
構造体代わり、XML代わり、柔軟な引数の実現
ついでに Array
a = []
a << 1 # [1]
a << 'yes' # [1, yes]
a[0] # 1
a.last # 'yes'
Rubyのこんなところが好き
● ダックタイピング(動的型付け)
● Module による mix-in を使った多重継承– Javaでは、1系統の目的で継承を使ってしまった
ら、委譲しか選択肢がなくコードが冗長に
– アスペクト指向的なプログラミングもしやすい
– とにかく同じコードを書かなくて済む
● ブロック渡し– プチフレームワークを簡単に作れる
– Javaではクラスが必要だがRubyならメソッドだけ
ダックタイピング
def sum(items)
s = 0
items.each{|i| s += i.amount.to_i}
s
end● items には each が必要
● items のメンバーには amount が必要
● amount で返されるオブジェクトには to_i が必要
上記が満たされることを信じられるなら型チェックは
要らない
ダックタイピングのいいところ
● コード量が少ない– 型名を書かなくていい
– 型チェックを通すための儀式的コードが要らない
ex. インターフェース
● 設計変更の際のコード量が少ない– クラス設計を見直さなくても目的を達成できる
● 引数の型の違うだけのメソッドが増えない
ダックタイピングに必要なマインド
● 呼ぶ側は、呼ばれる側に確かにそのメソッド
があることを信じる
● 引数にどんなクラスが要求されているかは想
像する
信じられる、想像できる体制と規約が重要
具体的な対応策(1)
信じたら裏切られた
(NoMethodError)
● 必要なら明示的な型チェックを入れる
● 単体テスト
具体的な対応策(2)
想像したら外れた
def foo(item)
「え、配列が欲しかったの?」
良い名前をつけるずっと良い名前でるようにメンテナンスする
コメント
Ruby の黒魔術
● クラスのメソッドを動的に追加、変更、削除
できる(→メタプログラミング)
● __send__で何でも呼べる
● eval でソース断片を実行できる
● method_missing で拾えば存在しないメソッ
ドもあるように見せかけられる
自由度が高い
やろうと思えば何でもできる
生産性が高い
だから Rails は Ruby で生まれた
● 柔軟
● 強力
● 少ないコードで多くの仕事ができるようにで
きる
● オブジェクト指向
フレームワークを作るのに適している
Ruby が Java よりイケてない点
文字列がバイト列 (;_;)
文字単位の処理が苦手Unicode 対応が熱望される
Ruby 1.9 or 2.02007年クリスマス?
Ruby on Rails の話
お世話になっている度合いの感触
ActiveRecord
ActiveSupport
Ajax
Ruby
Controller
view
migration
test
あ、プラグイン忘れた (^^;)(べつやくメソッド)
ActiveRecord まず嬉しいこと
● O/Rマッピング
● スキーマ設定ファイル不要
● 約束事を守れば少ないコードで快適– プライマリキーはidって名前で整数で自動発番
– type って列名は使わないで
– テーブル名は複数形、モデルクラスは単数形
– foreign key は相手テーブル名にあわせた名前
– created_at, updated_at
ARにおける関連
● belongs_to
● has_one
● has_many
● has_and_belongs_to_many
● has_many :through を使った多対多
必要のない関連は張らなくて良い
belongs_to と has_many
has_many
belongs_to
関連名は自由につけられる
class Community < ActiveRecord::Base
has_many :community_members
end
class Community < ActiveRecord::Base
has_many :members,
:class_name => 'CommunityMember',
:foreign_key => 'community_member_id'
end
こんな感じで使えます
# 指定されたコミュニティオブジェクトを取得
community = Community.find(params[:id])
<table>
<% for m in community.members %>
<tr><td><%= m.name %></td></tr>
<% end %>
</table>
View
Controller
多対多 has_many を使った例
User は、CommunityMember 越しに Community を複数持つ
多対多 has_many を使った例
class User < ActiveRecord::Base
has_many :communities,
:through => :community_members
end
class CommunityMembers
belongs_to :community
belongs_to :user
end
使い勝手の良い AR features
● 単一テーブル継承
● ポリモーフィック関連
● コールバックメソッド
● 検証
単一テーブル継承
● 1つのテーブルのレコードを複数の、継承関
係のあるクラス群にマッピングする
ポリモーフィック関連
●複数のテーブルが1種類のクラスであるかのよ
うに紐づけられる。
コールバック
● オブジェクトの仕事をオブジェクトに隠蔽で
きる
● 明示的にトランザクションをはらなくても同
一トランザクションで処理される
● 経験が浅いとコールバックメソッドで書くべ
き処理を Controller に書いてしまいがち
コールバックの例
● before_validation
● after_validation
● before_save
● after_save
● before_destroy
● after_destroy
詳しくは ActiveRecord::Callbacks
検証
● 組み込みの検証メソッドが充実
● 自前で書くのも難しくない
● コールバック・検証は、モデル同士が継承関
係にあっても期待通りに動く– Ruby ではクラスメソッドも継承チックに動くし
RoRもその方向で作られている
● save と save! の違い
Migration
● データベーススキーマの変更を管理、共有
● これさえあればDBなんて変え放題
● Migration を使う際のコツ– SVN でコミットする際、Migration 番号が衝突し
ないように人間が注意する必要がある。
– Migration 内で AR クラスや自作ユーティリティ
クラスを使うのは避けたほうが無難。
– データそのものの投入は別の方法で。
– 困ったときは execute でSQL。
– schema.rb は参考資料と割り切る。
RoR における Ajax
● Prototype.js をラップするヘルパー– Ajax.Updater
– Ajax.Request
– Observer
● Scriptaculous をラップするヘルパー– ドラッグ&ドロップ
● Dojo Toolkit
Ajax.Updater 動作イメージ
html
<dev id="items">
</div>
Ajaxリクエストを送り、
指定領域を結果で書き換える JavaScript
Ajaxリクエストを処理してページの一部を返す
Ajax.Updater
サーバサイド
Ajax.Updater on Rails
● form_remote_tag
● link_to_remote
● remote_function
<%= link_to_remote '削除',
:update => 'items',
:url => {:action => 'delete', :id =>
@item.id } %>
Ajax.Request と RJS
html
Ajaxリクエストを送り、
Responseを実行する JavaScript
Ajaxリクエストを処理してJavaScript を返す
Ajax.Request
サーバサイド
RJS
RJSでできてUpdater でできないこと
● 複数のエリアを同時に書き換える
● どこのエリアを書き換えるかを、サーバサイ
ドに処理が渡ってから決定する
Flex と RoR
Flex RoR
XML
XML
Hash であつかえるObjct 渡し
model.to_xmlObjct 生成 / 更新
Controller - Filter の活用
● Controller 内の多くのメソッドに共通する
前後処理を書くことで簡潔に
● 多くのメソッドが共通するように
Controller を設計しないとゴチャゴチャに
ActiveSupport
● Ruby の標準クラスを拡張
● Ruby のマニュアルだけでは分からない
● よく使うのはこんなところ– Time.days_in_month(7, 2007) # 今月の日数
– Date.today # 今日
– "GroupMember".underscore # group_member
– "group_member".classify # GroupMember
Ruby - よく使うコンテナメソッド
● Array– first
– last
– include?
– join
– delete_if
● Enumerable– any?
– collect, map
– detect, find
– find_all, select
– include?
※初心者が自分で書いてしまいがちな、重要度の高い処理を書き出してみました。
Ruby - Moduleでコードを集約する
module ImageAttachable
def self.included(base)
base.extend(ClassMethods)
base.has_many :attached_images
...
end
module ClassMethods
...
end
end
RoR(AR)の苦手なことの例
● primary key, foreign key 以外での関連
– 例えば、code と 有効期間で持ってくる
– ARの関連ではなく自力で
● has_many メンバーの削除をリアルタイムで行わな
いようにする
● 親子関係にあるモデル同士に互いにオブジェクトレ
ベルでリンクする
● has_many 関係の子オブジェクトが作られるときに
親オブジェクトの状態によって初期化を操作する
苦手なことの例(2)
● 日付(Date)がらみがいまいち– Ruby のDate は数値じゃないと例外。RoRは文字
列が基本なのでやや扱いにくい。
– ハッシュ←→Date や 文字列←→Date が標準機
能として不足に感じる
– Time だけの Ruby クラスがなく、DBのTime型と
の互換の際に注意が必要
苦手なことの例(3)
● 日本語文字列の操作– 現状、正規表現がもっとも良い解法
– 噂では、Unicode対応後も正規表現がよいとか
(速度面から、正規表現で対応できるならそのほ
うがよいとのお告げが・・)
RoRを活かすための開発スタイル
● アジャイル?
● プロジェクトの最初に気をつけるべき技術上
のポイント
● RoR らしいコードを書くヒント
アジャイル?
● ウォーターフォールでも開発は可能
● 高い生産性を期待するならアジャイル
● なぜなら– ウォーターフォールで作ると、おそらく結果的に
たくさんのコードを書くことになる
● なら、Ruby on Rails でなくてもいんじゃね?
– 仕様段階で見えなかった漏れや、実装してみて気
づいた問題、アイディアをフィードバックして路
線変更する待ち時間が邪魔をする
余談 - アジャイルへの遠い道のり● 「計画を立てない」罠
– NO!!
● 染み付いた受託開発マインド– おかしいと思っても言われた仕様どおりに作る
– 機能を縦割りで順番に作っていく
– 後で本格的に作るものも形だけ先に作ってしまう
● コミュニケーション不足– 仕様決定者が遠くにいて連絡が取りにくい
– ソースレビューをしない
– 重大な実装でも担当者が一人で決めてしまう
余談 - ハイブリッド方式
● リスクの高い部分は精鋭部隊でアジャイル開
発
● リスクの低い部分はウォーターフォール的に
オフショアマンパワー活用
開発人数について
● 5~6人までがやりやすい(気がする)
● 人数が増えるとこんなことが起きる– リファクタリングが追いつかない
– レビューされないソースが多くなる
– テストが通らないのが常態化
– 担当が固定的になり、コミュニケーションしづら
い雰囲気に
● 人数を増やすなら、上記の改善策を
● 2人ずつチームで開発している案件も
プロジェクトの最初に気をつけるべき技術上のポイント(1)
● Controller 設計は、URL 設計から始める– URL 設計からみて近いアクションを同じコント
ローラに入れる
● routes.rb がきれいに書ける
● filter がきれいに書ける
● 出来上がったURL がRESTっぽくてカッコイイ
● コーディング規約を合意する
● 初期段階からテストを書く
● コンソールを活用する
プロジェクトの最初に気をつけるべき技術上のポイント(2)
● Act As やポリモーフィック関連など、Rails
を使ってできることは自前でやらない
● 利用できるプラグインは利用する
● 自前でやるべきときは自前でやる
● セキュリティについて理解し、最初から h
やプレースフォルダなどを使う習慣づけ
● 例外を拾ってきれいに見せるのはなるべく最
初はやらない。投げ捨て基本がお奨め
良いRoRコードを書くヒント
● Ruby
– Array, Hash の機能を使う(自前で書かない)
● AR
– インスタンス寄りに考える
– コールバックメソッドと検証を充実させる
● View
– こまめにヘルパーを作る
– 基本的に、キリの良い html タグ単位で部品化を
● 全般
– 設定(引数)最小限で動くように設計する
– View, Controller の事情を Model に持ち込まない
ご清聴ありがとうございました