simple_schema 0.0.1 → 0.0.2

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -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