focuslight-validator validate sinatra application - validation night at line corporation

44
focuslight-validator validate sinatra application  Satoshi SUZUKI, @studio3104 validation night at LINE Corp. Dec 4, 2014 1

Upload: satoshi-suzuki

Post on 13-Jul-2015

1.699 views

Category:

Technology


1 download

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

suddenly,

validation night at LINE Corp. Dec 4, 2014 3

Do you knowGrowthForecast ?

validation night at LINE Corp. Dec 4, 2014 4

Ok. Well,validation night at LINE Corp. Dec 4, 2014 5

Do you knowFocuslight ?

validation night at LINE Corp. Dec 4, 2014 6

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

Amazing!!

validation night at LINE Corp. Dec 4, 2014 12

Too easy!!

validation night at LINE Corp. Dec 4, 2014 13

Too simple!!

validation night at LINE Corp. Dec 4, 2014 14

built-inrules

validation night at LINE Corp. Dec 4, 2014 15

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

lambdarule

validation night at LINE Corp. Dec 4, 2014 28

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

specifiablemultiplerules

validation night at LINE Corp. Dec 4, 2014 31

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

validationtypes

validation night at LINE Corp. Dec 4, 2014 34

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

it is roughly like this

validation night at LINE Corp. Dec 4, 2014 43

fin.

validation night at LINE Corp. Dec 4, 2014 44