trafaret 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 6a6f9ebc15fa44c667060779f703eb99d2462d83
4
- data.tar.gz: 82a0675c08400058c321efa24851b6a0e9d2a66f
3
+ metadata.gz: bc7865262c4ddd22e53d71b22cb53aa70b53f403
4
+ data.tar.gz: f5fe1c37f11b712d536e3fdb6de0c0189f0fa31e
5
5
  SHA512:
6
- metadata.gz: cd413ceeafc1db8704c047a81e8bb72d56404183cd5c62c446bdafc8652be4a7b6469b4b3821e4346155b8dfae2f35207c91d3eba9558d19ffcb28bc8824a8e1
7
- data.tar.gz: 7e978fa7abe98d587cd85985fc18fc862e2c298457eba0b65f8d59afd47f57f8c58e2b3968abada01be6f5e321edc4adf3360443112203bf7a22b6627b2433d1
6
+ metadata.gz: d3021461ace4f7c6df04852525cdd60a8fb161f1915d641b6493cc3da3253e4fba8d21e6e3271e9e5cdbfcce4cb353f99c71b7c269366950100116e292063b1d
7
+ data.tar.gz: d9cca1a58733a9d30c4b8917e0e0f6b01666f3f8b82611957a727b365949992b59510c17e149725c64a6d84eb86a7fcadd315129ceda85bb3aa77a9bd0ecf75e
data/lib/trafaret.rb CHANGED
@@ -1,76 +1,37 @@
1
- require "trafaret/version"
1
+ require 'active_support/core_ext'
2
+ require 'trafaret/version'
3
+ require 'trafaret/errors'
4
+ require 'trafaret/validator'
5
+ require 'trafaret/validators'
6
+ require 'trafaret/base'
2
7
 
3
8
  module Trafaret
4
- class Attribute
5
- def initialize(name, options = {}, &blk)
6
- @name = name
7
- @options = options
8
- @blk = blk
9
+ def self.get_validator(validator)
10
+ if validator.is_a? Symbol
11
+ class_name = validator.to_s.classify
12
+ validator = Trafaret.const_get(class_name) rescue nil
13
+ validator ||= Kernel.const_get(class_name)
14
+ else
15
+ validator
9
16
  end
10
-
11
- def name
12
- @name.to_s
13
- end
14
-
15
- def get(obj)
16
- if @blk
17
- return @blk.call obj
18
- end
19
- data = begin
20
- obj.send(@name)
21
- rescue NameError
22
- nil
23
- end
24
- data ||= begin
25
- obj[@name] || obj[@name.to_s]
26
- rescue NoMethodError, TypeError
27
- nil
28
- end
29
- end
30
-
31
- alias :dump :get
32
17
  end
33
18
 
34
- class Array < Attribute
35
- def dump(obj)
36
- cls = @options[:class]
37
- if data = get(obj)
38
- data.map do |elem|
39
- cls.dump elem
40
- end
41
- else
42
- []
43
- end
44
- end
19
+ def self.get_instantiated_validator(validator, options = {})
20
+ val = self.get_validator(validator)
21
+ val = val.new(options) if val.is_a? Class
22
+ val
45
23
  end
46
24
 
47
- class Hash < Attribute
48
- def initialize(name = nil, options = {}, &blk)
49
- @name = name
50
- @options = options
51
- @attrs = options[:attributes] || []
52
- instance_eval(&blk)
53
- end
54
-
55
- def attribute(name, options = {}, &blk)
56
- @attrs << Attribute.new(name, options, &blk)
57
- end
58
-
59
- def array(name, options = {}, &blk)
60
- @attrs << Array.new(name, options, &blk)
61
- end
62
-
63
- def hash(name, options = {}, &blk)
64
- @attrs << Hash.new(name, options = {}, &blk)
65
- end
25
+ def self.[](validator, options = {})
26
+ return self.get_instantiated_validator(validator, options)
27
+ end
66
28
 
67
- def dump(obj)
68
- res = {}
69
- data = if @name then get(obj) else obj end
70
- @attrs.each do |attr|
71
- res[attr.name] = attr.dump(data)
72
- end
73
- res
29
+ def self.method_missing(meth, *args, &blk)
30
+ cls = self.get_validator(meth)
31
+ if cls
32
+ cls.new(*args, &blk)
33
+ else
34
+ super
74
35
  end
75
36
  end
76
37
  end
@@ -0,0 +1,70 @@
1
+ module Trafaret
2
+ class Key
3
+ def initialize(name, validator, options = {}, &blk)
4
+ @name = name
5
+ @validator = validator.new(options)
6
+ @options = options
7
+ @blk = blk
8
+ end
9
+
10
+ def get(obj, extractors = {})
11
+ return @blk.call obj if @blk
12
+ data = begin
13
+ extractors[@name].call(obj) if extractors[@name]
14
+ rescue NoMethodError
15
+ nil
16
+ end
17
+ data ||= begin
18
+ obj.send(@name)
19
+ rescue NameError
20
+ nil
21
+ end
22
+ data ||= begin
23
+ obj[@name] || obj[@name.to_s]
24
+ rescue NoMethodError, TypeError
25
+ nil
26
+ end
27
+ end
28
+
29
+ def call(data, extractors = {})
30
+ [@name, @validator.call(get(data, extractors), &@blk)]
31
+ end
32
+ end
33
+
34
+ class Extractor
35
+ def initialize(&blk)
36
+ @blk = blk
37
+ end
38
+
39
+ def call(data)
40
+ @blk.call data
41
+ end
42
+ end
43
+
44
+ class Base < Validator
45
+ module ClassMethods
46
+ attr_accessor :keys, :extractors
47
+ def inherited(base)
48
+ base.keys = (keys || []).dup
49
+ base.extractors = (extractors || {}).dup
50
+ end
51
+
52
+ def key(name, validator, options = {}, &blk)
53
+ @keys << Key.new(name, Trafaret.get_validator(validator), options, &blk)
54
+ end
55
+
56
+ def extract(name, &blk)
57
+ @extractors[name] = Extractor.new(&blk)
58
+ end
59
+ end
60
+ extend ClassMethods
61
+
62
+ def validate(data)
63
+ res = []
64
+ self.class.keys.each do |key|
65
+ res << key.call(data, extractors = self.class.extractors)
66
+ end
67
+ Hash[res]
68
+ end
69
+ end
70
+ end
@@ -0,0 +1,9 @@
1
+ module Trafaret
2
+ class Error < Exception
3
+ attr_reader :message
4
+
5
+ def initialize(message)
6
+ @message = message
7
+ end
8
+ end
9
+ end
@@ -0,0 +1,33 @@
1
+ class Trafaret::Validator
2
+ def initialize(options = {})
3
+ @options = options
4
+ end
5
+
6
+ def validate(data)
7
+ data # or return Trafaret::Error
8
+ end
9
+
10
+ def convert(data)
11
+ data
12
+ end
13
+
14
+ def call(data)
15
+ val = validate(data)
16
+ return val if val.is_a? Trafaret::Error
17
+ if block_given?
18
+ yield val
19
+ else
20
+ convert(val)
21
+ end
22
+ end
23
+
24
+ # ADT
25
+ def |(other)
26
+ Trafaret::Or.new(self, other)
27
+ end
28
+
29
+ # Helpers
30
+ def failure(msg)
31
+ Trafaret::Error.new msg
32
+ end
33
+ end
@@ -0,0 +1,65 @@
1
+ module Trafaret
2
+ class Any < Validator
3
+ end
4
+
5
+ class Or < Validator
6
+ attr_reader :validators
7
+
8
+ def initialize(*args)
9
+ args = args.first if args.first.is_a? ::Array
10
+ @validators = args.map { |v| Trafaret.get_instantiated_validator(v) }
11
+ end
12
+
13
+ def validate(data)
14
+ errors = []
15
+ @validators.each do |v|
16
+ res = v.call(data)
17
+ if res.is_a? Trafaret::Error
18
+ errors << res
19
+ else
20
+ return res
21
+ end
22
+ end
23
+ return failure errors
24
+ end
25
+
26
+ def |(other)
27
+ Trafaret::Or.new(*validators, other)
28
+ end
29
+ end
30
+
31
+ class String < Validator
32
+ def validate(data)
33
+ return failure('Not a String') unless data.is_a? ::String
34
+ return failure('Should not be blank') if !@options[:allow_blank] && data.empty?
35
+ return failure('Too short') if @options[:min_length] && data.size < @options[:min_length]
36
+ return failure('Too long') if @options[:max_length] && data.size > @options[:max_length]
37
+ if @options[:regex]
38
+ match = @options[:regex].match(data)
39
+ return failure('Does not match') unless match
40
+ return match
41
+ end
42
+ data
43
+ end
44
+ end
45
+
46
+ class Integer < Validator
47
+ def validate(data)
48
+ data.to_i
49
+ end
50
+ end
51
+
52
+ class Array < Validator
53
+ def self.[](validator, options = {})
54
+ self.new(options.merge(validator: validator))
55
+ end
56
+
57
+ def validate(data)
58
+ return failure('Not an Array') unless data.is_a? ::Array
59
+ cls = Trafaret.get_validator(@options[:validator]).new @options
60
+ data.map do |elem|
61
+ cls.call elem
62
+ end
63
+ end
64
+ end
65
+ end
@@ -1,3 +1,3 @@
1
1
  module Trafaret
2
- VERSION = "1.0.1"
2
+ VERSION = "1.1.0"
3
3
  end
@@ -1,20 +1,21 @@
1
1
  # -*- coding: utf-8 -*-
2
2
  require 'trafaret'
3
3
 
4
- describe Trafaret do
5
- Provider = Trafaret::Hash.new do
6
- attribute :url
7
- end
4
+ class ProviderTrafaret < Trafaret::Base
5
+ key :url, Trafaret::String, min_length: 3, max_length: 50
6
+ end
8
7
 
9
- Checker = Trafaret::Hash.new do
10
- attribute :name
11
- array :providers, class: Provider do |obj|
12
- obj['oa'].flat_map do |prov_name, accs|
13
- accs.map {|uuid, data| data}
14
- end
8
+ class FacebookResponseTrafaret < Trafaret::Base
9
+ key :name, :string, optional: true, min_length: 2
10
+ extract :providers do |data|
11
+ data['oa'].flat_map do |prov_name, accs|
12
+ accs.map { |uuid, data| data }
15
13
  end
16
14
  end
15
+ key :providers, :array, validator: :provider_trafaret
16
+ end
17
17
 
18
+ describe Trafaret::Base do
18
19
  let :raw do
19
20
  {'name' => 'kuku',
20
21
  'oa' => {
@@ -26,6 +27,35 @@ describe Trafaret do
26
27
  }
27
28
  end
28
29
  it 'should work' do
29
- Checker.dump(raw).should == ({"name"=>"kuku", "providers"=>[{"url"=>"http://ya.ru"}, {"url"=>"http://www.ru"}]})
30
+ FacebookResponseTrafaret.new.call(raw).should == ({name: "kuku", providers: [{url: "http://ya.ru"}, {url: "http://www.ru"}]})
31
+ end
32
+ end
33
+
34
+ describe Trafaret::String do
35
+ it 'should check errors' do
36
+ Trafaret.string.call('').message.should == 'Should not be blank'
37
+ Trafaret.string(min_length: 10).call('abc').message.should == 'Too short'
38
+ Trafaret.string(max_length: 1).call('abc').message.should == 'Too long'
39
+ Trafaret.string(regex: /abc/).call('bca').message.should == 'Does not match'
30
40
  end
31
41
  end
42
+
43
+ describe Trafaret::Array do
44
+ it 'should check' do
45
+ Trafaret::Array[:string].call(['a', 'b', 'c']).should == ['a', 'b', 'c']
46
+ end
47
+ end
48
+
49
+ describe Trafaret::Or do
50
+ it 'should return value' do
51
+ Trafaret[:or, [:string, :integer]].call('krukatuka').should == 'krukatuka'
52
+
53
+ (Trafaret[:string] | Trafaret[:integer]).call('krukatuka').should == 'krukatuka'
54
+
55
+ (Trafaret.string | Trafaret.integer).call('krukatuka').should == 'krukatuka'
56
+ end
57
+
58
+ it 'should return errors' do
59
+ Trafaret[:or, Trafaret[:array, validator: :string]].call('krukatuka').message.first.message.should == 'Not an Array'
60
+ end
61
+ end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: trafaret
3
3
  version: !ruby/object:Gem::Version
4
- version: 1.0.1
4
+ version: 1.1.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - Mikhail Krivushin
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2014-02-02 00:00:00.000000000 Z
11
+ date: 2014-03-26 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: bundler
@@ -53,6 +53,10 @@ files:
53
53
  - README.md
54
54
  - Rakefile
55
55
  - lib/trafaret.rb
56
+ - lib/trafaret/base.rb
57
+ - lib/trafaret/errors.rb
58
+ - lib/trafaret/validator.rb
59
+ - lib/trafaret/validators.rb
56
60
  - lib/trafaret/version.rb
57
61
  - spec/trafaret_spec.rb
58
62
  - trafaret.gemspec