focuslight-validator validate sinatra application - validation night at line corporation
TRANSCRIPT
focuslight-validator
validatesinatra application
Satoshi SUZUKI, @studio3104
validation night at LINE Corp. Dec 4, 2014 1
who? Satoshi SUZUKI
» Twitter: @studio3104
» GitHub: studio3104
» Work: LINE Corporation
validation night at LINE Corp. Dec 4, 2014 2
Focuslight GrowthForecast の Ruby クローン
» GrowthForecast は様々な値を WebAPI 経由でグラフ化できる Web ツールです。
» シンプルな API でリアルタイムにグラフを作成、更新でき、Web インターフェイスからグラフの表示をカスタマイズしたり、複数のメトリクスを重ね合わせたグラフを作成できます。
GrowthForecast - Lightning fast Graphing / Visualization より引用
validation night at LINE Corp. Dec 4, 2014 7
focuslight-validator» Focuslight で使われている validator module
» 汎用的に使うことが出来るように書かれている
» RubyGems からカンタンインストール!
$ gem i focuslight-validator
validation night at LINE Corp. Dec 4, 2014 8
with Sinatrarequire 'json'require 'sinatra/base'require 'focuslight-validator'
class App < Sinatra::Base helpers do def validate(*args) Focuslight::Validator.validate(*args) end
def rule(*args) Focuslight::Validator.rule(*args) end end
post '/notice' do result = validate(params, message: { rule(:not_blank) }) halt 400, result.errors.to_json if result.has_error? # do anything... endend
validation night at LINE Corp. Dec 4, 2014 9
with Sinatrapost '/notice' do # params[:message] がブランクではないかのチェック result = validate(params, message: { rule(:not_blank) })
# もしもブランクだったら、JSON 化したエラーメッセージを 400 で返す halt 400, result.errors.to_json if result.has_error?
# do anything...end
validation night at LINE Corp. Dec 4, 2014 10
Result ClassFocuslight::Validator.validate() の返り値
» Focuslight::Validator::Result のインスタンス
p Focuslight::Validator::Result.instance_methods(false)#=> [:errors, :hash, :[], :[]=, :error, :has_error?]
» [], []= が生えてる
» そのまま Hash アクセス出来る
validation night at LINE Corp. Dec 4, 2014 11
built-in rules
定義済みの内蔵ルール
» not_blank, choice, int, uint, natural, float, double, real, int_range, bool, regexp
これらのルールでは条件を満たせない場合» lambda rule を使って解決(後で出てきます)
https://github.com/focuslight/focuslight-validator/blob/master/lib/focuslight/validator.rb#L121-L147
validation night at LINE Corp. Dec 4, 2014 16
built-in rules (not_blank)nil か空白文字でなければ valid
» strip された値が返るparams = { v1: 'Foooo!!!! ', v2: '' }rule = Focuslight::Validator.rule(:not_blank)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v2=>"v2: missing or blank"}p result.hash #=> {:v1=>"Foooo!!!!"}
validation night at LINE Corp. Dec 4, 2014 17
built-in rules (choice)リストに含まれている値と一致すれば valid
» そのままの値が返るparams = { v1: 'yellow', v2: 'gold' }rule = Focuslight::Validator.rule(:choice, %w[ yellow red ])result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v2=>"v2: invalid value"}p result.hash #=> {:v1=>"yellow"}
validation night at LINE Corp. Dec 4, 2014 18
built-in rules (int)整数であれば valid
» to_i された値が返るparams = { v1: '-3104', v2: '3.104' }rule = Focuslight::Validator.rule(:int)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v2=>"v2: invalid integer"}p result.hash #=> {:v1=>-3104}
validation night at LINE Corp. Dec 4, 2014 19
built-in rules (uint)0 か自然数であれば valid
» to_i された値が返るparams = { v1: '3104', v2: '-3104' }rule = Focuslight::Validator.rule(:uint)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v2=>"v2: invalid integer (>= 0)"}p result.hash #=> {:v1=>3104}
validation night at LINE Corp. Dec 4, 2014 20
built-in rules (natural)自然数であれば valid
» to_i された値が返るparams = { v1: '3104', v2: '0' }rule = Focuslight::Validator.rule(:natural)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v2=>"v2: invalid integer (>= 1)"}p result.hash #=> {:v1=>3104}
validation night at LINE Corp. Dec 4, 2014 21
built-in rules (float)整数か小数(指数表記も含む)であれば valid
» to_f された値が返るparams = { v1: '3.104', v2: '3104', v3: '3.104e-03', v4: 'three' }rule = Focuslight::Validator.rule(:float)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule }, v3: { rule: rule }, v4: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v4=>"v4: invalid floating point num"}p result.hash #=> {:v1=>3.104, :v2=>3104.0, :v3=>0.003104}
validation night at LINE Corp. Dec 4, 2014 22
built-in rules (double)整数か小数(指数表記も含む)であれば valid
» to_f された値が返るparams = { v1: '3.104', v2: '3104', v3: '3.104e-03', v4: 'three' }rule = Focuslight::Validator.rule(:double)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule }, v3: { rule: rule }, v4: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v4=>"v4: invalid floating point num"}p result.hash #=> {:v1=>3.104, :v2=>3104.0, :v3=>0.003104}
validation night at LINE Corp. Dec 4, 2014 23
built-in rules (real)整数か小数(指数表記も含む)であれば valid
» to_f された値が返るparams = { v1: '3.104', v2: '3104', v3: '3.104e-03', v4: 'three' }rule = Focuslight::Validator.rule(:real)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule }, v3: { rule: rule }, v4: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v4=>"v4: invalid floating point num"}p result.hash #=> {:v1=>3.104, :v2=>3104.0, :v3=>0.003104}
validation night at LINE Corp. Dec 4, 2014 24
built-in rules (int_range)指定範囲内の数値であれば valid
» to_i された値が返るparams = { v1: '3104', v2: '3.104', v3: '-1' }rule = Focuslight::Validator.rule(:int_range, 0..10000)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule }, v3: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v3=>"v3: invalid number in range 0..10000"}p result.hash #=> {:v1=>3104, :v2=>3}
validation night at LINE Corp. Dec 4, 2014 25
built-in rules (bool)true, false, 1, 0 のいずれかであれば valid
» true か false が返るparams = { v1: 'true', v2: '0', v3: 'FalseClass' }rule = Focuslight::Validator.rule(:bool)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule }, v3: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v3=>"v3: invalid bool value"}p result.hash #=> {:v1=>true, :v2=>false}
validation night at LINE Corp. Dec 4, 2014 26
built-in rules (regexp)任意の正規表現にマッチすれば valid
» そのままの値が返るparams = { v1: 'Foooo!!!! ', v2: '' }rule = Focuslight::Validator.rule(:regexp, /^F.*/)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule },)
p result.has_error? #=> truep result.errors #=> {:v2=>"v2: invalid input for pattern ^F.*"}p result.hash #=> {:v1=>"Foooo!!!! "}
validation night at LINE Corp. Dec 4, 2014 27
lambda rule» built-in rules にない条件を使いたい場合
» lambda 式を自分で書く
validation night at LINE Corp. Dec 4, 2014 29
example of lambda rulemessage の文字数制限の validationparams = { message: 'focuslight-validator is so awesome!!' }result = Focuslight::Validator.validate( params, message: { rule: Focuslight::Validator.rule( :lambda, ->(m) { m && (1..10000).include?(m.strip.length) }, 'invalid length', :strip ), },)
p result.has_error? #=> falsep result.errors #=> {}p result.hash #=> {:message=>"focuslight-validator is so awesome!!"}
validation night at LINE Corp. Dec 4, 2014 30
specifiable multiple rules複数のルールを指定することも出来るparams = { v1: '10' }rule1 = Focuslight::Validator.rule(:not_blank)rule2 = Focuslight::Validator.rule(:int)result = Focuslight::Validator.validate( params, v1: { rule: [ rule1, rule2 ] },)
p result.hash #=> {:v1=>10}
validation night at LINE Corp. Dec 4, 2014 32
specifiable multiple rules複数のルールを指定する場合は順番に注意 1
params = { v1: '10', v2: '20' }rule1 = Focuslight::Validator.rule(:not_blank)rule2 = Focuslight::Validator.rule(:int)result = Focuslight::Validator.validate( params, v1: { rule: [ rule1, rule2 ] }, v2: { rule: [ rule2, rule1 ] },)
# 後から指定したルールに基づく型変換がされるため、# v2 は `to_i` されていない# エラーがある場合のメッセージも後から指定したルール優先p result.hash #=> {:v1=>10, :v2=>"20"}
1 version 0.0.1 時点
validation night at LINE Corp. Dec 4, 2014 33
validation typessingle key, single value
» 単一の value を持つデータの validationsingle key, array value
» value に配列を持つデータの validationrule for combination of 2 or more params
» 複数の values に対する複合的な validation
validation night at LINE Corp. Dec 4, 2014 35
validation typessingle key, single value
params = { v1: nil, v2: nil, v3: nil }rule = Focuslight::Validator.rule(:int)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule, default: '100' }, v3: { rule: rule, excludable: true },)
p result.has_error? #=> truep result.errors #=> {:v1=>"v1: invalid integer"}p result.hash #=> {:v2=>100, :v3=>nil}
validation night at LINE Corp. Dec 4, 2014 36
validation typessingle key, single value
» default
» 対象が nil だった場合のデフォルト値
» excludable
» 対象が nil だった場合そのまま nil にする
validation night at LINE Corp. Dec 4, 2014 37
validation typessingle key, array value
params = { v1: %w[ 10 20 30 ], v2: %w[ 3104 ] }rule = Focuslight::Validator.rule(:int)result = Focuslight::Validator.validate( params, v1: { array: true, rule: rule }, v2: { array: true, rule: rule, size: 5..10 }, v3: { array: true, rule: rule, excludable: true },)
p result.has_error? #=> truep result.errors #=> {:v2=>"v2: doesn't have values specified: 5..10"}p result.hash #=> {:v1=>[10, 20, 30], :v3=>[]}
validation night at LINE Corp. Dec 4, 2014 38
validation typessingle key, array value
» array
» 配列を対象とした validation を行うかどうか
» size
» 許容する配列のサイズを Range で指定
» excludable
» 対象が nil だった場合空の配列を埋める
validation night at LINE Corp. Dec 4, 2014 39
validation typesrule for combination of 2 or more params
params = { v1: '10', v2: '20', v3: '30' }rule = Focuslight::Validator.rule(:int)result = Focuslight::Validator.validate( params, v1: { rule: rule }, v2: { rule: rule }, v3: { rule: rule }, [ :v1, :v2, :v3 ] => { rule: Focuslight::Validator::Rule.new( -> (x, y, z) { x.to_i + y.to_i + z.to_i < 15 }, 'too large' ) },)
p result.has_error? #=> truep result.errors #=> {:"v1,v2,v3"=>"v1,v2,v3: too large"}p result.hash #=> {:v1=>10, :v2=>20, :v3=>30}
validation night at LINE Corp. Dec 4, 2014 40
validation typesrule for combination of 2 or more params
» 複数の values に対する複合的な validation
» 指定した values の合計値をチェックしたいなど
» 返り値のオブジェクトには values が含まれない
» 含めたい場合は通例どおり value 個別に定義
validation night at LINE Corp. Dec 4, 2014 41
validation typesrule for combination of 2 or more params
» built-in rules は使えない
» values の個数分を引数として取る Focuslight::Validator::Rule のインスタンスを定義して渡してあげる必要がある
Focuslight::Validator::Rule.new( -> (x, y, z) { x.to_i + y.to_i + z.to_i < 15 }, 'too large')
validation night at LINE Corp. Dec 4, 2014 42