RubyKaigi 2011 のメモ、2 日目です。rubykaigi.org に録画があることに気づいたので、リンクをつけてます。
安全なプログラムのつくりかた
安全なプログラムの作り方 | 日本Ruby会議2011(7月16日〜18日)
- 西山 和広
1995 頃、Perl / CGI で BBS 作成
- 入力の HTML エスケープ、フィルタリング
- onclick、javascript: の普及で危険に
対策
- 入力チェック
- 出力はエスケープ
- 環境の変化に注意
javascript URL
- http / https へのリンクのみ許可
GET は冪等 (副作用なし)
- js / form なしでアクセスさせられるため
- GET で削除するようにしてたらクローラに削除された例も
/tmp を避ける
- tmp 直下危険
- 固定のファイル名は特に危険
- symlink attack
- Windows では /tmp ないし
- tmpdir tempfile つかう
- rails なら Rails.root + "tmp" でも
パーミッションは最小限に。
- tmp 直下にソケット作って誰でもアクセスできる状態になっていた例
- umask でデフォルトを最小限のパーミッションに
- コードの所有者と、アップロードファイルなどの所有者を変えて、権限を設定する
- 脆弱性があった場合に、コードの改変を変えられる可能性がある
正規表現によるチェック
- 予期しないものをスルーしないように
- \w より [A-Za-z0-9] のほうが明確
- [[:alnum]] でも
任意のユーザー入力から正規表現を生成するのは危険
- パターンによっては DoS 可能
コンソールへ任意の出力を許すのは危険。
- WEBrick のエスケープシーケンスの脆弱性
- rvm でも (JVM#30414126)
- ログ、コンソールへの出力は String#dump で出力
コマンドライン処理でのエスケープ
- コードとしてのエスケープ
- シェルが処理するエスケープ
- 起動するプログラムが処理するエスケープ
- 複数引数の system つかう
- ファイル名に空白があっても良いか、ファイル名が - から始まってもよいか '"*\0 などが入っていても良いか
- シェルによる違い
- foo="aaa bbb"
- some foo
- だとシェルによって aaa と bbb だったり、aaa bbb だったり。
- ARGV で確認
jpmobileのベストプラクティス
jpmobileのベストプラクティス | 日本Ruby会議2011(7月16日〜18日)
小川 伸一郎
- https://github.com/jpmobile/jpmobile
らくらく連絡網
- RoR + jpmobile
- MySQL / TokyoTyrant / memcached
- Apache/ nginx
emoji / kanji 変換
- view を utf8 で書くとキャリアごとに変換して返す
- docomo なら utf-8 -> sjis
- リクエストもそれぞれの文字コードから utf8 にする
- rack ミドルウェアで実現
- mobile_carrier params_filter
- Rails.application.config.jpmobile.mobile_filter
- を initializer に書く
- session id
- a なら url 埋め込み
- form なら hidden に埋め込み
- cookie が使えないときのみ
view selecter
- 規約にそってファイルを探す。
- index_mobile_docomo.html.erb みたいな
- controller で include Jpmobile::ViewSelector
- disable_mobile_view! で探索を拒否することも
- layout / partial も対応
japanese mail
- body, subject は iso2022jp
- subject は base64 エンコード
- ヘッダは 76 文字 / 行である必要
- エンコード後に折り返すと復元に失敗する場合あり
- エンコード前に折り返し
emoticon
- docomo: sjis
- au: jis
- sb: utf8
- Unicode の私用領域に独自のコードでマッピング
Jpmobile::Mail::Base
- メールアドレスによって文字コード切り替え
Testing
- functional test
- template
- request.mobile?
- assert_template (>1.0.0.7pre7)
- charset
- rack を通過しないので utf-8
- integration test では変換される
- unit test
- mailer
- mail オブジェクトの段階では utf-8
- デリバリー後、@emails.first.to_s なら変換後
known issue
- 文字コード変換に非可逆のケース
- link_to に utf8 文字列を渡す場合は、そのままだと、docomo からのリクエストに utf8 文字が含まれることになってしまうためエラーや文字化け
- メールで charset がわからない場合、iso1022jp に決めうちなどの対策をとらないとエンコーディングエラー
質疑
- rfc違反メールにも対応
- unicode 絵文字
- 1.8 では扱えないので、1.8 対応の必要がなくなれば対応したい。
Writing Friendly Libraries
Writing Friendly Libraries | 日本Ruby会議2011(7月16日〜18日)
-
- Segment 7
- 90 unique gems
- Serious lib (works)
- Joke lib
Conventions
- ほかのライブラリの規約に従う
- LibraryName::Extention
- bin/executable
Version
- major.minor.revision
- major: 非互換変更
- minor: 新機能
- revision: バグフィックス
使いやすく
- 実際に使う人が使いやすく
- ruby がどうやってるか参考にする
Printable
- to_s: 人間が読む用
- inspect: デバッグ用
- pretty_print: 巨大な構造を表現
Comparable
- ==
- <=> と Comparable
- ==** と~ をマッチ用に
Hashable
- hash と eql?
- Array unique
- Array deferable
- each と Enumerable
Enumerator
- enum_for と Enumerable
Chanable
- enum.map.with_index ...
- return enum_for methodunless block_given?
Exceptions
- Common subclass (ArgmentError とか)を使う
- なぜ例外が起こったのか伝える
- 例外オブジェクトに例外に関係のあるデータをくっつける
- (ActiveRecord::RecordInvalid なら record メソッドで原因となったオブジェクトが得られる)
initialize_copy
- dup や clone から作られる
- deep copy
- 共有状態の管理
Marshal
- compact で fast に
- ガイドライン
- Arrray か ハッシュで
- marshal_dump は better
- VERSION を必ずつける
- 互換性
- 新機能追加しやすい
- 古いデータをこわさない
メンテしやすさ
- 引き継ぎのためにも
- do one thing
- 書きやすい
- 読みやすい
- 再利用しやすさを最大化
Release note
- important changes
- new features
- bug fixes
- Change log とは異なる、機能、変更ベースで
テストせよ
- testcase
- abstract test case
- 実装
bin/executable は最小限に
- 実際の処理は lib 下に集約
後方互換
- api と実装をわける
- api レイヤーで互換性を保持する
- less api class better : api に関わるクラスを少なくしよう
C Extentsion
- C は難しくリファクタリングしにくい
- できるだけ ruby で書く
Documentation
- API を書く
- 内部実装は隠す
- example をつけよう
Extensibility
- Hooks
- callback のしくみを入れる (ActiveRecord.before_save みたいな)
- subclass を作って override method (ActiveRecord#before_save みたいな)
- Plugins
- hooks の登録
- Gem.find_files を使って load する
Release
- README
- description
- bugtracker
- source repository
- url
- Release notes
- 機能の変化、非互換姓
- Automation
- test
- manifest
- gem create / upload
- tag release
- update doc
- use libraries
- 自動化しよう
- コピペするな
- Hoe というライブラリ
- https://github.com/seattlerb/hoe
- rake release VERSION=x.y.z で全部チェック
- プラグインもあるし設定も DRY
- git / isolate (bundler) / minitest / email などのプラグインあり
質疑
- news と chage log が違うのになぜ news をすすめる?
- changelog は多すぎる revert もあるし
- news はユーザ向け、changelog は (ライブラリ自体の) 開発者むけ
C はどういうときに使う?
- C library のラッパか、高速処理のため。前者をよくかく。
ユーザーからフィードバックを得るための tips があれば
- prerelease 版という手もあるけど使う人すくない
- bug tracker を使いやすくする
- 自分が、じゃなく、ユーザーが。
- bug tracker だけでなく ML を作るのもよい
- rubyforge より github のが好き
- github issues は使えるようになった
ライブラリが使うリソースはどこに置くべきか
- rubygems に data_dir というメソッドがあるのでそれを使う
- ふつう shared だけど記憶あいまい
Use rails_best_practices to refactor your rails codes
Use rails_best_practices to refactor your rails codes | 日本Ruby会議2011(7月16日〜18日)
@flyerhzm/ Richard Huang
- huangzhimin.com
- openfeint
RailsConf in Shang-hai で @ihower が Rails best practice という発表
- チェック、実践が大変
- それを簡単にする gem を作成、全部ではない
- code checker が 28 人いる
rails-bestpractices.comでベストプラクティスを共有している
- 70 practices
- gem document
- gem blog
使いかた
- gem install rails_best_practices
- cd rails_project
- rails_best_practices
- plain でも html でも出力
- html は解決法への url つき
- 該当箇所をエディタで開ける
なぜ使うのか
- 美しいコードを書くため
- チームでの開発のため
- コード規約
- コードレビューの一部を自動化でき、本質だけに言及できる
解析ツールについて
- java には checkstyle
- ruby には saikuro / flog / flay / reek / roodi などがある
- この gem は rails 開発チームに特価している
How works
- 行末の空白などの lixical チェック
- sexp (symbol expression) に変換して、モデル名や関連のチェック
- ベストプラクティスのチェック
- sexp は ruby_parser で作る (rails_best_practice blog 内 play with sexp)
設定
- rails_best_practices -g
- config/rails_vest_practices.yml がつくられるので、チェックしないプラクティスをコメントすればよい。
拡張
- github の wiki にチュートリアルつけてる
質疑
- プロジェクトの一部に対して、テストの内容を限定することはできるか
- パターンの除外はコマンドでできるけど、特定のディレクトリとかは未実装
- ruby のバージョンが変わったときにパーサが対応できるか
- たぶん。ripper 使うかも。
BDD style Unit Testing
BDD style Unit Testing | 日本Ruby会議2011(7月16日〜18日)
-
- http://ihower.tw
- OptimisDev
- Ruby Taiwan
テストの種類
- unit test: コードは正しいか
- customer test (acceptance test) : 正しいソフトウェアか
テストの役割
- verification
- check regression (downgrade を防ぐ)
- api design
- documentation
BDD の印象
- 仕様書のよう、読みやすい
フレームワーク
- RSpec
- Minitest::Spec
記法
- description Order do # クラス
- description "#amount" do ... # インスタンスメソッド
- description ".size" do ... # クラスメソッド
https://github.com/citrusbyte/context
- test/unit で context 使う
- matches でマッチャも使える
minitest/pride
- 出力をかわいくする
minitest/turn
- 出力を読みやすくする
BDD style caveat (注意点)
- too magic
- 高度な syntax で理解しづらい場合が
- its(:status) { should == "New" } みたいな記法
- let は流れを崩すので可読性がおちる
- DSL
- マッチャによっては冗長
- 深いネスト
- 深いネストはよくない
- どの before が適用されるかわかりにくい
- Mock が多すぎるとよくない
- 遅い
- test/unit に比べて遅い
- とくに RSpec
- ministest/spec は test/unit なみ
- でもプロダクションコードの速さのほうが問題になるよね
5 years know-how of RSpec driven Rails app. development.
5 years know-how of RSpec driven Rails app. development. | 日本Ruby会議2011(7月16日〜18日)
-
- 英和システムマネジメント
- Rails レシピブック
- 達人出版界
- はじめる! Cucumber
コンテキストをつくるのがむつかしい
- コンテキスト構築までのテクニック
モデルのテスト
- Skinny controllers, Fat models
- ほかは Cucumber で
データの用意がたいへん!
- ex. 塾の実習参加 app
- events has many cources, has many lessons, has many rooms and periods
- students has many registrations
- lessons has many registrations
- Student#subscribe(cource) でコース全部履修
- Student#register!(lesson_2_4) で一部別のコマに変えれる
- これだけでもいくつもデータを用意しないといけない
データの種類
- マスターデータ
- ほとんど追加更新されない
- 依存少ない
- UI を scaffold で納品できるような
- 主たるユーザ自身が変更しない
- リソースデータ
- 運用時、主に追加更新されるもの
- ユーザによって更新される
- イベントデータ
- リレーション
- has_many :through => に入りそうなもの
ストラテジー
- fixture
- 速い
- メンテ性低い、柔軟性低い
- マスターデータ向き
- fixture_replacement
- fabrication / factory_girl
- ひな形からオブジェクトを作る
- 使い方が難しい
- 遅い
- リソースデータ向き
- before / setup
- 割と速い
- 記述が分散する
- イベントデータ向き
- これらを全部組み合わせて使うといい
DRY
- fixture_rep や before とかでは同じようなことを何回も書くことになる。
- context を share する
- 適切な名前をつける
- let(:answer) { 42 }
- answer.should == 42
- 名前をつけてしまえば、どこ由来 (fixture, fixture_replacement, before) だろうが OK
- 状況に名前をつける
- shared_context: let や context をシェアする
- shared_context "生徒があるコースを履修している" do
- let ...
- before ...
- include_context で使う
- 「いつものあのセット」として使える。そこから状況ごとに変更できる。
- 適切な名前をつける
- http://bit.ly/esm-hiring-rubyists
- rubyworldconf にでます
Efficient JavaScript integration testing with Ruby and V8 engine.
Efficient JavaScript integration testing with Ruby and V8 engine. | 日本Ruby会議2011(7月16日〜18日)
-
- chris kowalik
JavaScript のテスト
- selenium では時間がかかりすぎる。
- ciサーバだと設定面倒
selenium / watir / phantom
- 超おそい
ピュア javascript
- Jasmine とか
- おそい!
ヘッドレスブラウザ
- HtmlUnit (Java)
- Zombie (Node.js)
- EnvJS
- Rubyist には苦痛
速いのがほしい!
- js サポート
- フレンドリな api
- ポータブル
ruby 用 v8 拡張 + browser 実装
scaffold
- Nokogiri で DOM パース
- HTTPクライアントとして RestClient / CURB
- js は Mustang
mustang : v8 in ruby
- https://github.com/nu7hatch/mustang
- rubyracer の書き直し
- v8 単体よりは遅いけど
- (高速化のための実装の話、理解できてない)
Mike
- https://github.com/nu7hatch/mike
- LibXML2 / LibCURL / LibV8 で作成 (みんな C++)
- htmlunit / webkit / node.js, zombie に影響されてる
- 1. 複数ウィンドウ対応
- 2. frame サポート
- 3. ユーザの操作 click_link など
- 4. js 実行
- 5. alert /confirm のモック
- 6. api きれい!
- イベントハンドリング
- XmlHttpRequest
- Web Socket
- Ruby 拡張
Net::HTTP
Advancing Net::HTTP | 日本Ruby会議2011(7月16日〜18日)
-
- yehudakatz.com
Net::HTTP.start do |http| http.get do |chunk| end # レスポンス解放 # keep alive できる http.get do |chunk| end # レスポンス解放 end # ソケット解放
(途中から全然理解できませんでした・・・。並列化とか Reactor とか言ってた気がする。)
Method Shelters : Classboxes でも Refinements でもない別のやり方
Method Shelters : Classboxes でも Refinements でもない別のやり方 | 日本Ruby会議2011(7月16日〜18日)
- @flexfrank
オープンクラスでメソッドかぶっちゃったりする問題
- あるライブラリがメソッド追加 -> 別のライブラリがメソッド追加で上書きされちゃう
- 別プロセスにして druby でなんとか解決するとか
- mathn が Integer#/ をrational にしちゃうのでつらい
これまでの解決案
- selector namespaces (smalltalk)
- refinements
- class ... のかわりに refine ... として定義し、using ... で使う
- lexical スコープの中のみ
- local rebinding はできない
- classbox
- matz 日記参照
- import したクラスに追加などができる。
- 同じ名前でその scope でだけ有効なサブクラスをつくる感じ。
- A と、Aを書き換えたクラスを import する B、の両方を import すると B からみた A は改変されてないものになる。
method shelter
- exposed chamber
- public api 用
- 呼べるし上書き
- hidden chamber
- private 用
- 呼べない上書きできない
CRubyのロックデザインの解説および改善案について
CRubyのロックデザインの解説および改善案について | 日本Ruby会議2011(7月16日〜18日)
- 小崎資広
- (MacBook の電池が切れてしまったため、メモなし。かつ、あまり理解できてなかった。マルチコア環境では、複数スレッドのうち、1 つのスレッドがほとんど処理されない場合があり、Ruby 1.9.3 ではこの問題を解決したという話だったと思う。)
(Lightning Talk 1 は聴けませんでした)