simple_schema 0.0.1 → 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,89 @@
1
+ # Simple Schema
2
+
3
+ simple schema gem is a fantastic converter / validator (only presence)
4
+
5
+ # Features
6
+
7
+ * Agnostic
8
+ * Easy Use
9
+ * Lambda support
10
+ * Usefull with rack-api
11
+ * Code Base Small < 2000 lines
12
+ * Support Add On-the-fly Strategies
13
+
14
+ # How to install
15
+
16
+ ## for Rails 3 app
17
+
18
+ ### Add on your Gemfile
19
+
20
+ gem "simple_schema"
21
+
22
+ # Examples
23
+
24
+ ## to conveter
25
+
26
+ schema = SimpleSchema::Schema.new({
27
+ :name => {
28
+ :key_name => :nome
29
+ }
30
+ })
31
+ converter = SimpleSchema::Converter.new(schema)
32
+ output = converter.translate({
33
+ :name => "renato"
34
+ })
35
+ #output is: {:nome => "renato"}
36
+
37
+
38
+ ## to validate
39
+ validator = SimpleSchema::Validator.new(
40
+ SimpleSchema::Schema.new({
41
+ :friends => {
42
+ :items => {
43
+ :name => {}
44
+ }
45
+ }
46
+ })
47
+ )
48
+
49
+ check_valid = validator.valid?({
50
+ :friends => [{:name => "Lenon"},{:name => "Madson"}]
51
+ })
52
+
53
+ #check_valid is true
54
+
55
+
56
+ validator.validate!({
57
+ :friends => [{:name => "Lenon"},{}]
58
+ })
59
+ }
60
+
61
+ # raise error SimpleSchema::MissingAttribute with "Missing friends/1/name"
62
+
63
+
64
+ # License
65
+
66
+ (The MIT License)
67
+
68
+ Copyright (c) 2011
69
+
70
+ Permission is hereby granted, free of charge, to any person obtaining
71
+ a copy of this software and associated documentation files (the
72
+ 'Software'), to deal in the Software without restriction, including
73
+ without limitation the rights to use, copy, modify, merge, publish,
74
+ distribute, sublicense, and/or sell copies of the Software, and to
75
+ permit persons to whom the Software is furnished to do so, subject to
76
+ the following conditions:
77
+
78
+ The above copyright notice and this permission notice shall be
79
+ included in all copies or substantial portions of the Software.
80
+
81
+ THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
82
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
83
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
84
+ IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
85
+ CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
86
+ TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
87
+ SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
88
+
89
+
@@ -1,3 +1,26 @@
1
1
  require 'simple_schema/errors'
2
+ require 'simple_schema/injection'
3
+ require 'simple_schema/schema_items'
4
+ require 'simple_schema/schema_properties'
5
+ require 'simple_schema/schema'
6
+ require 'simple_schema/validator_items'
7
+ require 'simple_schema/validator_properties'
8
+ require 'simple_schema/validator_lambda'
2
9
  require 'simple_schema/validator'
10
+ require 'simple_schema/converter_items'
11
+ require 'simple_schema/converter_properties'
12
+ require 'simple_schema/converter'
3
13
 
14
+
15
+ module SimpleSchema
16
+ def self.translate(key, key_name)
17
+ begin
18
+ translated_key = key_name
19
+ translated_key = key if translated_key.empty?
20
+ translated_key = translated_key.to_sym
21
+ rescue
22
+ translated_key = key
23
+ end
24
+ translated_key
25
+ end
26
+ end
@@ -0,0 +1,34 @@
1
+ module SimpleSchema
2
+ class Converter
3
+ attr_reader :schema, :options
4
+
5
+ def initialize(schema, options = {})
6
+ options[:translates] ||= [ConverterItems,ConverterProperties]
7
+ @schema = schema
8
+ @schema = @schema.schema if @schema.respond_to?(:schema)
9
+ @options = options
10
+ end
11
+
12
+ def translate(data)
13
+ if !data.respond_to?(:each) && !data.respond_to?(:fetch)
14
+ raise InvalidDataType.new(data.class)
15
+ end
16
+
17
+ translated_data = {}
18
+ @schema.each do |key, properties|
19
+
20
+ translated_key = SimpleSchema.translate(key, properties[:key_name])
21
+ value = data.fetch(key, nil)
22
+
23
+ @options[:translates].each do |normalizer|
24
+ value = normalizer.build(value, properties, @options)
25
+ end
26
+
27
+ translated_data[translated_key] = value
28
+ end
29
+
30
+ translated_data
31
+ end
32
+ end
33
+ end
34
+
@@ -0,0 +1,14 @@
1
+ module SimpleSchema
2
+ class ConverterItems
3
+ def self.build(data, schema, options)
4
+ return data unless (schema[:type] == :array)
5
+ conveter = Converter::new(schema[:items], options)
6
+ items = []
7
+ data.each do |item|
8
+ items << conveter.translate(item)
9
+ end
10
+ return items
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,9 @@
1
+ module SimpleSchema
2
+ class ConverterProperties
3
+ def self.build(data, schema, options)
4
+ return data unless (schema[:type] == :object)
5
+ return Converter::new(schema[:properties], options).translate(data)
6
+ end
7
+ end
8
+ end
9
+
@@ -1,29 +1,30 @@
1
1
  module SimpleSchema
2
- class Validator
3
- class InvalidSchemaType < Exception
2
+ class InvalidBuilder < Exception
3
+
4
+ end
5
+
6
+ class InvalidSchemaType < Exception
4
7
  attr_reader :type
5
8
  def initialize(type)
6
9
  @type = type
7
10
  super "Schema must be either an Array or a Hash, got #{type}"
8
11
  end
9
- end
12
+ end
10
13
 
11
- class InvalidDataType < Exception
12
- attr_reader :type
13
- def initialize(type)
14
- @type = type
15
- super "Data must be a Hash, got #{type}"
16
- end
14
+ class InvalidDataType < Exception
15
+ attr_reader :type
16
+ def initialize(type)
17
+ @type = type
18
+ super "Data must be a Hash, got #{type}"
17
19
  end
20
+ end
18
21
 
19
- class MissingAttribute < Exception
20
- attr_reader :attribute, :fragments
22
+ class MissingAttribute < Exception
23
+ attr_reader :fragments
21
24
 
22
- def initialize(attribute, fragments)
23
- @attribute = attribute
24
- @fragments = fragments
25
- super "Missing #{fragments.join('/')}"
26
- end
25
+ def initialize(fragments)
26
+ @fragments = fragments
27
+ super "Missing #{fragments.join('/')}"
27
28
  end
28
29
  end
29
30
  end
@@ -0,0 +1,23 @@
1
+ module SimpleSchema
2
+ module Injection
3
+
4
+ def normalizers
5
+ build_injection
6
+ end
7
+
8
+ def registry(normalizer)
9
+ raise SimpleSchema::InvalidBuilder.new unless normalizer.respond_to?(:build)
10
+ build_injection << normalizer
11
+ end
12
+
13
+ def unregistry(class_name)
14
+ build_injection.slice!(build_injection.index(class_name))
15
+ end
16
+
17
+ def build_injection
18
+ self.class_variable_set(:@@normalizers_table, []) unless self.class_variable_defined?(:@@normalizers_table)
19
+ self.class_variable_get(:@@normalizers_table)
20
+ end
21
+ end
22
+ end
23
+
@@ -0,0 +1,31 @@
1
+ module SimpleSchema
2
+ class Schema
3
+ attr_reader :schema, :options
4
+
5
+ def initialize(defined_schema, options = {})
6
+ options[:normalizers] ||= [SchemaItems, SchemaProperties]
7
+ options[:defaults] ||= {:required => true, :type => :string}
8
+ raise InvalidSchemaType.new(defined_schema.class) unless defined_schema.is_a?(Hash) || defined_schema.is_a?(Array)
9
+ @options = options
10
+ @schema = normalize(defined_schema)
11
+ end
12
+
13
+ private
14
+
15
+ def normalize(properties)
16
+ h = {}
17
+ properties.each do |key,value|
18
+ value = {} if value.nil?
19
+ key = key.to_sym
20
+ value = {:key_name => key}.merge(@options[:defaults].merge(value))
21
+ @options[:normalizers].each do |normalizer|
22
+ value = normalizer.build(value, options)
23
+ end
24
+ h[key] = value
25
+ end
26
+
27
+ h
28
+ end
29
+ end
30
+ end
31
+
@@ -0,0 +1,12 @@
1
+ module SimpleSchema
2
+ class SchemaItems
3
+ def self.build(schema, options)
4
+ if schema[:items]
5
+ schema[:type] = :array
6
+ schema[:items] = Schema.new(schema[:items], options).schema
7
+ end
8
+ schema
9
+ end
10
+ end
11
+ end
12
+
@@ -0,0 +1,12 @@
1
+ module SimpleSchema
2
+ class SchemaProperties
3
+ def self.build(schema, options)
4
+ if schema[:properties]
5
+ schema[:type] = :object
6
+ schema[:properties] = Schema.new(schema[:properties], options).schema
7
+ end
8
+ schema
9
+ end
10
+ end
11
+ end
12
+
@@ -1,159 +1,77 @@
1
1
  module SimpleSchema
2
2
  class Validator
3
- attr_reader :schema, :fragments, :data
4
-
5
- def initialize(schema, data)
6
- if !schema.is_a?(Hash) && !schema.is_a?(Array)
7
- raise InvalidSchemaType.new(schema.class)
8
- end
9
-
10
- if !data.is_a?(Hash)
11
- raise InvalidDataType.new(data.class)
12
- end
13
-
14
- @data = data
15
- @fragments = []
16
- @schema = build_schema({ :properties => schema })[:properties]
3
+ attr_reader :schema, :options
4
+
5
+ def initialize(schema, options = {})
6
+ options[:validators] ||= [ValidatorItems, ValidatorLambda, ValidatorProperties]
7
+ @options = options
8
+ @schema = schema
9
+ @schema = @schema.schema if @schema.respond_to?(:schema)
17
10
  end
18
11
 
19
- def valid?
12
+ def valid?(data, options = {
13
+ :original_data => nil,
14
+ :original_schema => nil
15
+ })
20
16
  begin
21
- validate(@schema, @data)
22
- rescue MissingAttribute
17
+ self.validate(data, options)
18
+ rescue MissingAttribute => e
23
19
  false
24
20
  end
25
21
  end
26
22
 
27
- def validate!
28
- validate(@schema, @data)
29
- end
30
-
31
- def translated_data
32
- translate_data(@data, @schema)
23
+ def validate!(data, options = {
24
+ :original_data => nil,
25
+ :original_schema => nil
26
+ })
27
+ self.validate(data, options)
33
28
  end
34
29
 
35
- private
36
-
37
- def schema_defaults
38
- { :required => true, :type => :string }
39
- end
40
-
41
- def normalize_properties(properties)
42
- return properties unless properties.is_a?(Array)
43
- h = {}
44
- properties.each do |key|
45
- h[key] = {}
46
- end
47
- h
48
- end
49
-
50
- def build_schema(current_schema)
51
- schema = schema_defaults
52
-
53
- current_schema.each do |property, value|
54
- property = property.to_sym
55
-
56
- case property
57
- when :required
58
- schema[:required] = value
59
- when :type
60
- schema[:type] = value.to_sym
61
- when :properties
62
- schema[:type] = :object
63
- schema[:properties] = Hash.new
64
-
65
- normalize_properties(value).each do |property, value|
66
- original_key = property.to_sym
67
- property = value[:key_name] unless value[:key_name].nil?
68
- value[:key_name] = original_key
69
- schema[:properties][property.to_sym] = build_schema(value)
70
- end
71
- when :items
72
- schema[:type] = :array
73
- schema[:items] = Hash.new
74
-
75
- normalize_properties(value).each do |property, value|
76
- original_key = property.to_sym
77
- property = value[:key_name] unless value[:key_name].nil?
78
- value[:key_name] = original_key
79
- schema[:items][property.to_sym] = build_schema(value)
80
- end
81
- when :key_name
82
- schema[:key_name] = value
83
- end
30
+ protected
31
+ def validate(data, options)
32
+ if !data.is_a?(Hash)
33
+ raise InvalidDataType.new(data.class)
84
34
  end
35
+
36
+ options[:original_data] ||= data
37
+ options[:original_schema] ||= @schema
38
+ options[:path] ||= []
85
39
 
86
- schema
87
- end
40
+ @schema.each do |key, properties|
41
+ required = properties[:required]
42
+ required = false if properties[:required].is_a?(Proc)
88
43
 
89
- def validate(current_schema, data)
90
- current_schema.each do |property_name, schema|
91
-
92
- @fragments << property_name
93
-
94
- required_value = schema[:required]
95
-
96
- if required_value.respond_to?(:call)
97
- required_value = required_value.call(@data, @schema)
98
- end
44
+ requireds = [required]
99
45
 
100
- if required_value && (data.respond_to?(:has_key?) && !data.has_key?(property_name))
101
- raise MissingAttribute.new(property_name, fragments)
46
+ translated_key = if options[:translate]
47
+ SimpleSchema.translate(key, properties[:key_name])
48
+ else
49
+ key
102
50
  end
51
+
52
+ value = data.fetch(translated_key, nil)
103
53
 
104
- if required_value
105
-
106
- case schema[:type]
107
- when :string
108
- if !data[property_name].is_a?(String) || data[property_name].strip.empty?
109
- raise MissingAttribute.new(property_name, fragments)
110
- end
111
- when :object
112
- if !data[property_name].is_a?(Hash) || !data[property_name].any?
113
- raise MissingAttribute.new(property_name, fragments)
114
- end
115
- validate(schema[:properties], data[property_name])
116
- when :array
117
- if !data[property_name].is_a?(Array) || !data[property_name].any?
118
- raise MissingAttribute.new(property_name, fragments)
119
- end
120
- data[property_name].each_with_index do |item, index|
121
- @fragments << index
122
- validate(schema[:items], item)
123
- @fragments.pop
124
- end
125
- end
54
+ if value.respond_to?(:empty?)
55
+ nuller = value.nil? || value.empty?
56
+ elsif value.respond_to?(:blank?)
57
+ nuller = value.nil? || value.blank?
58
+ else
59
+ nuller = value.nil?
126
60
  end
127
61
 
128
- @fragments.pop
129
- end
130
- end
131
-
132
- def translate_data(data, current_schema)
133
- new_data = {}
134
-
135
- data.each do |key, value|
136
- if !current_schema || !current_schema.has_key?(key)
137
- new_data[key] = value
138
- next
62
+ path = options[:path] + [translated_key]
63
+
64
+ @options[:validators].each do |normalizer|
65
+ requireds << normalizer.build(value, properties, @options, options.merge({:path => path}))
139
66
  end
140
67
 
141
- new_key = current_schema[key][:key_name]
68
+ requireds.each { |required|
69
+ raise MissingAttribute.new(path) if required && nuller
70
+ }
142
71
 
143
- if value.is_a?(Array)
144
- new_value = []
145
- value.each do |value|
146
- new_value << translate_data(value, current_schema[key][:items])
147
- end
148
- new_data[new_key] = new_value
149
- elsif value.is_a?(Hash)
150
- new_data[new_key] = translate_data(value, current_schema[key][:properties])
151
- else
152
- new_data[new_key] = value
153
- end
154
72
  end
155
73
 
156
- new_data
74
+ true
157
75
  end
158
76
  end
159
77
  end
@@ -0,0 +1,14 @@
1
+ module SimpleSchema
2
+ class ValidatorItems
3
+ def self.build(data, schema, class_options, options)
4
+ return false unless (schema[:type] == :array)
5
+ raise MissingAttribute.new(options[:path]) unless data.respond_to?(:each_index)
6
+ data.each_index do |index|
7
+ options_item = options.merge({:path => options[:path] + [index] })
8
+ validator = Validator::new(schema[:items], class_options)
9
+ validator.validate!(data[index], options_item)
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -0,0 +1,9 @@
1
+ module SimpleSchema
2
+ class ValidatorLambda
3
+ def self.build(data, schema, class_options, options)
4
+ return false unless (schema[:required].is_a?(Proc))
5
+ schema[:required].call(options[:original_data], options[:original_schema])
6
+ end
7
+ end
8
+ end
9
+
@@ -0,0 +1,14 @@
1
+ module SimpleSchema
2
+ class ValidatorProperties
3
+ def self.build(data, schema, class_options, options)
4
+ return false unless (schema[:type] == :object)
5
+ begin
6
+ validator = Validator::new(schema[:properties], class_options)
7
+ validator.validate!(data, options)
8
+ rescue InvalidDataType
9
+ raise MissingAttribute.new(options[:path])
10
+ end
11
+ end
12
+ end
13
+ end
14
+
@@ -1,4 +1,4 @@
1
1
  module SimpleSchema
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
4
4
 
metadata CHANGED
@@ -1,7 +1,7 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: simple_schema
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.0.1
4
+ version: 0.0.2
5
5
  prerelease:
6
6
  platform: ruby
7
7
  authors:
@@ -13,11 +13,12 @@ authors:
13
13
  autorequire:
14
14
  bindir: bin
15
15
  cert_chain: []
16
- date: 2011-08-16 00:00:00.000000000Z
16
+ date: 2011-09-02 00:00:00.000000000 -03:00
17
+ default_executable:
17
18
  dependencies:
18
19
  - !ruby/object:Gem::Dependency
19
20
  name: rspec
20
- requirement: &12972440 !ruby/object:Gem::Requirement
21
+ requirement: &14768220 !ruby/object:Gem::Requirement
21
22
  none: false
22
23
  requirements:
23
24
  - - ! '>='
@@ -25,7 +26,7 @@ dependencies:
25
26
  version: '0'
26
27
  type: :development
27
28
  prerelease: false
28
- version_requirements: *12972440
29
+ version_requirements: *14768220
29
30
  description: Simple schema validator for Ruby
30
31
  email:
31
32
  - lenon.marcel@gmail.com
@@ -37,12 +38,23 @@ executables: []
37
38
  extensions: []
38
39
  extra_rdoc_files: []
39
40
  files:
40
- - lib/simple_schema/version.rb
41
+ - lib/simple_schema/validator_items.rb
42
+ - lib/simple_schema/schema.rb
43
+ - lib/simple_schema/validator_lambda.rb
44
+ - lib/simple_schema/converter.rb
45
+ - lib/simple_schema/schema_items.rb
46
+ - lib/simple_schema/injection.rb
47
+ - lib/simple_schema/converter_properties.rb
41
48
  - lib/simple_schema/validator.rb
49
+ - lib/simple_schema/version.rb
50
+ - lib/simple_schema/schema_properties.rb
42
51
  - lib/simple_schema/errors.rb
52
+ - lib/simple_schema/validator_properties.rb
53
+ - lib/simple_schema/converter_items.rb
43
54
  - lib/simple_schema.rb
44
55
  - LICENSE
45
- - README
56
+ - README.md
57
+ has_rdoc: true
46
58
  homepage: http://github.com/concretesolutions/simple_schema/
47
59
  licenses: []
48
60
  post_install_message:
@@ -63,7 +75,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
63
75
  version: '0'
64
76
  requirements: []
65
77
  rubyforge_project:
66
- rubygems_version: 1.8.6
78
+ rubygems_version: 1.6.2
67
79
  signing_key:
68
80
  specification_version: 3
69
81
  summary: Simple schema validator for Ruby
data/README DELETED
File without changes