schematic 0.2.1 → 0.2.3
Sign up to get free protection for your applications and to get access to all the features.
- data/lib/schematic.rb +2 -1
- data/lib/schematic/generator/column.rb +9 -5
- data/lib/schematic/generator/column_validator.rb +25 -0
- data/lib/schematic/generator/restrictions/base.rb +3 -18
- data/lib/schematic/generator/uniqueness.rb +25 -0
- data/lib/schematic/generator/xsd.rb +12 -4
- data/lib/schematic/version.rb +1 -1
- data/spec/schematic/generator/restrictions/mixin_spec.rb +65 -0
- data/spec/schematic/generator/{restrictions/uniqueness_spec.rb → uniqueness_spec.rb} +1 -1
- data/spec/schematic_serializers_xsd_spec.rb +39 -0
- metadata +11 -6
- data/lib/schematic/generator/restrictions/uniqueness.rb +0 -26
data/lib/schematic.rb
CHANGED
@@ -9,7 +9,9 @@ module Schematic
|
|
9
9
|
autoload :Names, 'schematic/generator/names'
|
10
10
|
autoload :Namespaces, 'schematic/generator/namespaces'
|
11
11
|
autoload :Column, 'schematic/generator/column'
|
12
|
+
autoload :ColumnValidator, 'schematic/generator/column_validator'
|
12
13
|
autoload :Types, 'schematic/generator/types'
|
14
|
+
autoload :Uniqueness, 'schematic/generator/uniqueness'
|
13
15
|
|
14
16
|
module Restrictions
|
15
17
|
autoload :Base, 'schematic/generator/restrictions/base'
|
@@ -18,7 +20,6 @@ module Schematic
|
|
18
20
|
autoload :Length, 'schematic/generator/restrictions/length'
|
19
21
|
autoload :Pattern, 'schematic/generator/restrictions/pattern'
|
20
22
|
autoload :Numericality, 'schematic/generator/restrictions/numericality'
|
21
|
-
autoload :Uniqueness, 'schematic/generator/restrictions/uniqueness'
|
22
23
|
end
|
23
24
|
end
|
24
25
|
module Serializers
|
@@ -1,6 +1,12 @@
|
|
1
1
|
module Schematic
|
2
2
|
module Generator
|
3
3
|
class Column
|
4
|
+
attr_accessor :restriction_classes
|
5
|
+
class << self
|
6
|
+
def restriction_classes
|
7
|
+
@restriction_classes ||= [Restrictions::Length, Restrictions::Enumeration, Restrictions::Numericality, Restrictions::Pattern, Restrictions::Custom]
|
8
|
+
end
|
9
|
+
end
|
4
10
|
|
5
11
|
def initialize(klass, column, additional_methods = {}, ignored_methods = {})
|
6
12
|
@klass = klass
|
@@ -16,11 +22,9 @@ module Schematic
|
|
16
22
|
field.xs :complexType do |complex_type|
|
17
23
|
complex_type.xs :simpleContent do |simple_content|
|
18
24
|
simple_content.xs :restriction, "base" => map_type(@column) do |restriction|
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
Restrictions::Numericality.new(@klass, @column).generate(restriction)
|
23
|
-
Restrictions::Custom.new(@klass, @column).generate(restriction)
|
25
|
+
self.class.restriction_classes.each do |restriction_class|
|
26
|
+
restriction_class.new(@klass, @column).generate(restriction)
|
27
|
+
end
|
24
28
|
end
|
25
29
|
end
|
26
30
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Schematic
|
2
|
+
module Generator
|
3
|
+
class ColumnValidator
|
4
|
+
attr_reader :klass, :column
|
5
|
+
|
6
|
+
def initialize(klass, column)
|
7
|
+
@klass = klass
|
8
|
+
@column = column
|
9
|
+
end
|
10
|
+
|
11
|
+
def for_validator(validator_klass)
|
12
|
+
validators_for_column.each do |column_validation|
|
13
|
+
next unless column_validation.is_a? validator_klass
|
14
|
+
next unless column_validation.options[:if].nil? || column_validation.options[:unless].nil?
|
15
|
+
yield(column_validation)
|
16
|
+
return
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def validators_for_column
|
21
|
+
klass._validators[column.name.to_sym]
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -1,25 +1,10 @@
|
|
1
1
|
module Schematic
|
2
2
|
module Generator
|
3
3
|
module Restrictions
|
4
|
-
class Base
|
5
|
-
def
|
6
|
-
|
7
|
-
@column = column
|
4
|
+
class Base < Schematic::Generator::ColumnValidator
|
5
|
+
def self.inherited(klass)
|
6
|
+
Schematic::Generator::Column.restriction_classes << klass unless Schematic::Generator::Column.restriction_classes.include?(klass)
|
8
7
|
end
|
9
|
-
|
10
|
-
def for_validator(validator_klass)
|
11
|
-
validators_for_column.each do |column_validation|
|
12
|
-
next unless column_validation.is_a? validator_klass
|
13
|
-
next unless column_validation.options[:if].nil? || column_validation.options[:unless].nil?
|
14
|
-
yield(column_validation)
|
15
|
-
return
|
16
|
-
end
|
17
|
-
end
|
18
|
-
|
19
|
-
def validators_for_column
|
20
|
-
@klass._validators[@column.name.to_sym]
|
21
|
-
end
|
22
|
-
|
23
8
|
end
|
24
9
|
end
|
25
10
|
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
module Schematic
|
2
|
+
module Generator
|
3
|
+
class Uniqueness < ColumnValidator
|
4
|
+
|
5
|
+
def generate(builder)
|
6
|
+
for_validator ActiveRecord::Validations::UniquenessValidator do |validator|
|
7
|
+
unique_name = validator.attributes.first.to_s.dasherize
|
8
|
+
additional_fields = (validator.options[:scope] || []).map(&:to_s).map(&:dasherize)
|
9
|
+
|
10
|
+
names = Schematic::Generator::Names.new(@klass)
|
11
|
+
builder.xs :unique, "name" => "#{unique_name}-must-be-unique" do |unique|
|
12
|
+
unique.xs :selector, "xpath" => "./#{names.element}"
|
13
|
+
unique.xs :field, "xpath" => unique_name
|
14
|
+
additional_fields.each do |additional_field|
|
15
|
+
unique.xs :field, "xpath" => additional_field
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
|
24
|
+
|
25
|
+
|
@@ -7,7 +7,13 @@ module Schematic
|
|
7
7
|
def initialize(klass, options = {})
|
8
8
|
@klass = klass
|
9
9
|
@names = Names.new(klass)
|
10
|
-
|
10
|
+
self.options = options
|
11
|
+
end
|
12
|
+
|
13
|
+
def options=(hash = {})
|
14
|
+
@options = {:generated_types => []}.merge(hash)
|
15
|
+
@options[:generated_types] << @klass unless @options[:generated_types].include?(@klass)
|
16
|
+
@options
|
11
17
|
end
|
12
18
|
|
13
19
|
def header(builder)
|
@@ -30,9 +36,11 @@ module Schematic
|
|
30
36
|
|
31
37
|
def generate(builder, klass)
|
32
38
|
nested_attributes.each do |nested_attribute|
|
33
|
-
next if nested_attribute.klass == klass
|
34
|
-
|
39
|
+
next if nested_attribute.klass == klass
|
40
|
+
next if nested_attribute.klass == klass.superclass
|
41
|
+
next if @options && @options[:generated_types] && @options[:generated_types].include?(klass)
|
35
42
|
nested_attribute.klass.generate_xsd(builder, klass, @options)
|
43
|
+
@options[:generated_types] << klass
|
36
44
|
end
|
37
45
|
|
38
46
|
generate_complex_type_for_collection(builder)
|
@@ -72,7 +80,7 @@ module Schematic
|
|
72
80
|
|
73
81
|
def generate_uniqueness_constraints(builder)
|
74
82
|
@klass.columns.each do |column|
|
75
|
-
|
83
|
+
Uniqueness.new(@klass, column).generate(builder)
|
76
84
|
end
|
77
85
|
end
|
78
86
|
|
data/lib/schematic/version.rb
CHANGED
@@ -0,0 +1,65 @@
|
|
1
|
+
require "spec_helper"
|
2
|
+
|
3
|
+
describe "Schematic::Generator::Restrictions::Mixin" do
|
4
|
+
describe ".to_xsd" do
|
5
|
+
context "with a model with a mixed in restriction" do
|
6
|
+
before do
|
7
|
+
class MixedInRestriction < Schematic::Generator::Restrictions::Base
|
8
|
+
def generate(builder)
|
9
|
+
for_validator ActiveModel::BlockValidator do |validator|
|
10
|
+
builder.xs(:enumeration, "value" => "cheese")
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
subject { sanitize_xml(TestModel.to_xsd) }
|
17
|
+
with_model :test_model do
|
18
|
+
table :id => false do |t|
|
19
|
+
t.string "title"
|
20
|
+
end
|
21
|
+
|
22
|
+
model do
|
23
|
+
validates_each :title do |object, attr, value|
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
it "should validate against it's own XSD" do
|
29
|
+
invalid_instance = TestModel.new(:title => "cake")
|
30
|
+
xml = [invalid_instance].to_xml
|
31
|
+
lambda {
|
32
|
+
validate_xml_against_xsd(xml, subject)
|
33
|
+
}.should raise_error
|
34
|
+
valid_instance = TestModel.new(:title => "cheese")
|
35
|
+
xml = [valid_instance].to_xml
|
36
|
+
lambda {
|
37
|
+
validate_xml_against_xsd(xml, subject)
|
38
|
+
}.should_not raise_error
|
39
|
+
end
|
40
|
+
|
41
|
+
it "should mark that the field with the allowed values" do
|
42
|
+
xsd = generate_xsd_for_model(TestModel) do
|
43
|
+
<<-XML
|
44
|
+
<xs:element name="title" minOccurs="0" maxOccurs="1">
|
45
|
+
<xs:complexType>
|
46
|
+
<xs:simpleContent>
|
47
|
+
<xs:restriction base="String">
|
48
|
+
<xs:enumeration value="cheese"/>
|
49
|
+
</xs:restriction>
|
50
|
+
</xs:simpleContent>
|
51
|
+
</xs:complexType>
|
52
|
+
</xs:element>
|
53
|
+
XML
|
54
|
+
end
|
55
|
+
|
56
|
+
subject.should == xsd
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
|
63
|
+
|
64
|
+
|
65
|
+
|
@@ -154,6 +154,45 @@ describe Schematic::Serializers::Xsd do
|
|
154
154
|
end
|
155
155
|
|
156
156
|
end
|
157
|
+
|
158
|
+
context "when the model has a nested reference that references another nested reference" do
|
159
|
+
with_model :blog do
|
160
|
+
table {}
|
161
|
+
model do
|
162
|
+
has_many :posts
|
163
|
+
has_many :readers
|
164
|
+
accepts_nested_attributes_for :posts
|
165
|
+
accepts_nested_attributes_for :readers
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
with_model :post do
|
170
|
+
table do |t|
|
171
|
+
t.integer :blog_id
|
172
|
+
end
|
173
|
+
|
174
|
+
model do
|
175
|
+
belongs_to :blog
|
176
|
+
has_many :readers
|
177
|
+
accepts_nested_attributes_for :blog
|
178
|
+
accepts_nested_attributes_for :readers
|
179
|
+
end
|
180
|
+
end
|
181
|
+
|
182
|
+
with_model :reader do
|
183
|
+
table do |t|
|
184
|
+
t.integer :blog_id
|
185
|
+
t.integer :post_id
|
186
|
+
end
|
187
|
+
end
|
188
|
+
|
189
|
+
subject { Post.to_xsd }
|
190
|
+
|
191
|
+
it "should generate a valid XSD" do
|
192
|
+
validate_xsd(subject)
|
193
|
+
end
|
194
|
+
|
195
|
+
end
|
157
196
|
end
|
158
197
|
|
159
198
|
context "for an empty model with no attributes or validations" do
|
metadata
CHANGED
@@ -2,7 +2,7 @@
|
|
2
2
|
name: schematic
|
3
3
|
version: !ruby/object:Gem::Version
|
4
4
|
prerelease:
|
5
|
-
version: 0.2.
|
5
|
+
version: 0.2.3
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
8
8
|
- Case Commons, LLC
|
@@ -10,7 +10,8 @@ autorequire:
|
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
12
|
|
13
|
-
date: 2011-
|
13
|
+
date: 2011-06-01 00:00:00 -04:00
|
14
|
+
default_executable:
|
14
15
|
dependencies:
|
15
16
|
- !ruby/object:Gem::Dependency
|
16
17
|
name: activerecord
|
@@ -109,6 +110,7 @@ files:
|
|
109
110
|
- TODO
|
110
111
|
- lib/schematic.rb
|
111
112
|
- lib/schematic/generator/column.rb
|
113
|
+
- lib/schematic/generator/column_validator.rb
|
112
114
|
- lib/schematic/generator/names.rb
|
113
115
|
- lib/schematic/generator/namespaces.rb
|
114
116
|
- lib/schematic/generator/restrictions/base.rb
|
@@ -117,8 +119,8 @@ files:
|
|
117
119
|
- lib/schematic/generator/restrictions/length.rb
|
118
120
|
- lib/schematic/generator/restrictions/numericality.rb
|
119
121
|
- lib/schematic/generator/restrictions/pattern.rb
|
120
|
-
- lib/schematic/generator/restrictions/uniqueness.rb
|
121
122
|
- lib/schematic/generator/types.rb
|
123
|
+
- lib/schematic/generator/uniqueness.rb
|
122
124
|
- lib/schematic/generator/xsd.rb
|
123
125
|
- lib/schematic/serializers/xsd.rb
|
124
126
|
- lib/schematic/version.rb
|
@@ -126,9 +128,10 @@ files:
|
|
126
128
|
- spec/schematic/generator/restrictions/custom_spec.rb
|
127
129
|
- spec/schematic/generator/restrictions/enumeration_spec.rb
|
128
130
|
- spec/schematic/generator/restrictions/length_spec.rb
|
131
|
+
- spec/schematic/generator/restrictions/mixin_spec.rb
|
129
132
|
- spec/schematic/generator/restrictions/numericality_spec.rb
|
130
133
|
- spec/schematic/generator/restrictions/pattern_spec.rb
|
131
|
-
- spec/schematic/generator/
|
134
|
+
- spec/schematic/generator/uniqueness_spec.rb
|
132
135
|
- spec/schematic/serializers/xsd_extend_spec.rb
|
133
136
|
- spec/schematic/serializers/xsd_validation_presence_spec.rb
|
134
137
|
- spec/schematic/serializers/xsd_xsd_ignore_methods_spec.rb
|
@@ -138,6 +141,7 @@ files:
|
|
138
141
|
- spec/spec_helper.rb
|
139
142
|
- spec/xsd/XMLSchema.xsd
|
140
143
|
- spec/xsd/xml.xsd
|
144
|
+
has_rdoc: true
|
141
145
|
homepage: https://github.com/Casecommons/schematic
|
142
146
|
licenses: []
|
143
147
|
|
@@ -161,7 +165,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
161
165
|
requirements: []
|
162
166
|
|
163
167
|
rubyforge_project: schematic
|
164
|
-
rubygems_version: 1.
|
168
|
+
rubygems_version: 1.6.2
|
165
169
|
signing_key:
|
166
170
|
specification_version: 3
|
167
171
|
summary: Automatic XSD generation from ActiveRecord models
|
@@ -169,9 +173,10 @@ test_files:
|
|
169
173
|
- spec/schematic/generator/restrictions/custom_spec.rb
|
170
174
|
- spec/schematic/generator/restrictions/enumeration_spec.rb
|
171
175
|
- spec/schematic/generator/restrictions/length_spec.rb
|
176
|
+
- spec/schematic/generator/restrictions/mixin_spec.rb
|
172
177
|
- spec/schematic/generator/restrictions/numericality_spec.rb
|
173
178
|
- spec/schematic/generator/restrictions/pattern_spec.rb
|
174
|
-
- spec/schematic/generator/
|
179
|
+
- spec/schematic/generator/uniqueness_spec.rb
|
175
180
|
- spec/schematic/serializers/xsd_extend_spec.rb
|
176
181
|
- spec/schematic/serializers/xsd_validation_presence_spec.rb
|
177
182
|
- spec/schematic/serializers/xsd_xsd_ignore_methods_spec.rb
|
@@ -1,26 +0,0 @@
|
|
1
|
-
module Schematic
|
2
|
-
module Generator
|
3
|
-
module Restrictions
|
4
|
-
class Uniqueness < Base
|
5
|
-
def generate(builder)
|
6
|
-
for_validator ActiveRecord::Validations::UniquenessValidator do |validator|
|
7
|
-
unique_name = validator.attributes.first.to_s.dasherize
|
8
|
-
additional_fields = (validator.options[:scope] || []).map(&:to_s).map(&:dasherize)
|
9
|
-
|
10
|
-
names = Schematic::Generator::Names.new(@klass)
|
11
|
-
builder.xs :unique, "name" => "#{unique_name}-must-be-unique" do |unique|
|
12
|
-
unique.xs :selector, "xpath" => "./#{names.element}"
|
13
|
-
unique.xs :field, "xpath" => unique_name
|
14
|
-
additional_fields.each do |additional_field|
|
15
|
-
unique.xs :field, "xpath" => additional_field
|
16
|
-
end
|
17
|
-
end
|
18
|
-
end
|
19
|
-
end
|
20
|
-
end
|
21
|
-
end
|
22
|
-
end
|
23
|
-
end
|
24
|
-
|
25
|
-
|
26
|
-
|