schematic 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.
data/README.rdoc CHANGED
@@ -1,3 +1,41 @@
1
1
  = Schematic
2
2
 
3
- Automatic schema generation.
3
+ * http://github.com/casecommons/schematic/
4
+
5
+ == DESCRIPTION
6
+
7
+ Automatic XSD generation for your ActiveRecord models
8
+
9
+ == INSTALL
10
+
11
+ Add schematic to your Gemfile
12
+
13
+ gem 'schematic'
14
+
15
+ Then run:
16
+
17
+ $ bundle install
18
+
19
+ == USAGE
20
+
21
+ class Post < ActiveRecord::Base
22
+ end
23
+
24
+ Post.to_xsd => (a bunch of xml)
25
+
26
+ You can include additional elements by defining a ".xsd_methods" on your class:
27
+
28
+ class Post < ActiveRecord::Base
29
+ def self.xsd_methods
30
+ {:title => nil, :author => [:name, :email, :url]}
31
+ end
32
+ end
33
+
34
+ == REQUIREMENTS
35
+
36
+ * ActiveRecord 3.x
37
+
38
+ == LICENSE
39
+
40
+ MIT
41
+
@@ -33,7 +33,7 @@ module Schematic
33
33
  xsd_columns.each do |column|
34
34
  next if additional_methods.keys.map(&:to_s).include?(column.name)
35
35
 
36
- all.xs :element, "name" => column.name.dasherize, "minOccurs" => "0", "maxOccurs" => "1" do |field|
36
+ all.xs :element, "name" => column.name.dasherize, "minOccurs" => xsd_minimum_occurrences_for_column(column), "maxOccurs" => "1" do |field|
37
37
  field.xs :complexType do |complex_type|
38
38
  complex_type.xs :simpleContent do |simple_content|
39
39
  simple_content.xs :extension, "base" => map_column_type_to_xsd_type(column) do |extension|
@@ -69,6 +69,14 @@ module Schematic
69
69
  end
70
70
  end
71
71
 
72
+ def xsd_minimum_occurrences_for_column(column)
73
+ self._validators[column.name.to_sym].each do |column_validation|
74
+ next unless column_validation.is_a? ActiveModel::Validations::PresenceValidator
75
+ return "1" if column_validation.options[:allow_blank] != true
76
+ end
77
+ "0"
78
+ end
79
+
72
80
  def xsd_methods
73
81
  {}
74
82
  end
@@ -1,3 +1,3 @@
1
1
  module Schematic
2
- VERSION = "0.0.1"
2
+ VERSION = "0.0.2"
3
3
  end
@@ -37,6 +37,37 @@ describe Schematic::Serializers::Xsd do
37
37
  end
38
38
 
39
39
  describe ".to_xsd" do
40
+
41
+ context "XSD validation" do
42
+ subject { SomeModel.to_xsd }
43
+
44
+ with_model :some_model do
45
+ table do |t|
46
+ t.string "some_string"
47
+ t.float "some_float"
48
+ t.datetime "some_datetime"
49
+ t.date "some_date"
50
+ t.boolean "some_boolean"
51
+ end
52
+
53
+ model do
54
+ validates :some_string, :presence => true
55
+ validates :some_date, :presence => true, :allow_blank => true
56
+ validates :some_datetime, :presence => true, :allow_blank => false
57
+ end
58
+
59
+ end
60
+ it "should generate a valid XSD" do
61
+ xsd_schema_file = File.join(File.dirname(__FILE__), "xsd", "XMLSchema.xsd")
62
+ meta_xsd = Nokogiri::XML::Schema(File.open(xsd_schema_file))
63
+
64
+ doc = Nokogiri::XML.parse(subject)
65
+ meta_xsd.validate(doc).each do |error|
66
+ error.message.should be_nil
67
+ end
68
+ end
69
+ end
70
+
40
71
  context "for an empty model with no attributes or validations" do
41
72
  subject { EmptyModel.to_xsd }
42
73
 
@@ -99,7 +130,7 @@ describe Schematic::Serializers::Xsd do
99
130
  end
100
131
 
101
132
  it "should include the additional method" do
102
- xsd = generate_xsd_for_model(SomeModel) do
133
+ xsd = generate_xsd_for_model(SomeModel) do
103
134
  <<-XML
104
135
  <xs:element name="id" minOccurs="0" maxOccurs="1">
105
136
  <xs:complexType>
@@ -125,12 +156,68 @@ describe Schematic::Serializers::Xsd do
125
156
  end
126
157
 
127
158
  context "with a model with validations" do
159
+ subject { SomeModel.to_xsd }
160
+
128
161
  context "presence of validation" do
162
+
129
163
  context "when allow blank is true" do
164
+ with_model :some_model do
165
+ table :id => false do |t|
166
+ t.string "title"
167
+ end
130
168
 
169
+ model do
170
+ validate :title, :presence => true, :allow_blank => true
171
+ end
172
+ end
173
+
174
+ it "should mark that the field minimum occurrences is 0" do
175
+ xsd = generate_xsd_for_model(SomeModel) do
176
+ <<-XML
177
+ <xs:element name="title" minOccurs="0" maxOccurs="1">
178
+ <xs:complexType>
179
+ <xs:simpleContent>
180
+ <xs:extension base="xs:string">
181
+ <xs:attribute name="type" type="xs:string" use="optional"/>
182
+ </xs:extension>
183
+ </xs:simpleContent>
184
+ </xs:complexType>
185
+ </xs:element>
186
+ XML
187
+ end
188
+
189
+ subject.should == sanitize_xml(xsd)
190
+ end
131
191
  end
132
192
 
133
193
  context "when allow blank is false" do
194
+ with_model :some_model do
195
+ table :id => false do |t|
196
+ t.string "title"
197
+ end
198
+
199
+ model do
200
+ validates :title, :presence => true
201
+ end
202
+ end
203
+
204
+ it "should mark that the field minimum occurrences is 1" do
205
+ xsd = generate_xsd_for_model(SomeModel) do
206
+ <<-XML
207
+ <xs:element name="title" minOccurs="1" maxOccurs="1">
208
+ <xs:complexType>
209
+ <xs:simpleContent>
210
+ <xs:extension base="xs:string">
211
+ <xs:attribute name="type" type="xs:string" use="optional"/>
212
+ </xs:extension>
213
+ </xs:simpleContent>
214
+ </xs:complexType>
215
+ </xs:element>
216
+ XML
217
+ end
218
+
219
+ subject.should == sanitize_xml(xsd)
220
+ end
134
221
  end
135
222
  end
136
223
 
@@ -144,6 +231,52 @@ describe Schematic::Serializers::Xsd do
144
231
  end
145
232
  end
146
233
 
234
+ describe ".xsd_minimum_occurrences_for" do
235
+
236
+ context "given a column with no validations" do
237
+ with_model :some_model do
238
+ table :id => false do |t|
239
+ t.string "title"
240
+ end
241
+ model {}
242
+ end
243
+
244
+ it "should return 0" do
245
+ SomeModel.xsd_minimum_occurrences_for_column(SomeModel.columns.first).should == "0"
246
+ end
247
+ end
248
+
249
+ context "given a column with presence of but allow blank" do
250
+ with_model :some_model do
251
+ table :id => false do |t|
252
+ t.string "title"
253
+ end
254
+ model do
255
+ validates :title, :presence => true, :allow_blank => true
256
+ end
257
+ end
258
+
259
+ it "should return 0" do
260
+ SomeModel.xsd_minimum_occurrences_for_column(SomeModel.columns.first).should == "0"
261
+ end
262
+ end
263
+
264
+ context "given a column with presence of and no allow blank" do
265
+ with_model :some_model do
266
+ table :id => false do |t|
267
+ t.string "title"
268
+ end
269
+ model do
270
+ validates :title, :presence => true
271
+ end
272
+ end
273
+
274
+ it "should return 1" do
275
+ SomeModel.xsd_minimum_occurrences_for_column(SomeModel.columns.first).should == "1"
276
+ end
277
+ end
278
+ end
279
+
147
280
  private
148
281
 
149
282
  def sanitize_xml(xml)
@@ -154,18 +287,18 @@ describe Schematic::Serializers::Xsd do
154
287
  <<-XML
155
288
  <?xml version="1.0" encoding="UTF-8"?>
156
289
  <xs:schema xmlns:xs="http://www.w3.org/2001/XMLSchema">
157
- <xs:element name="#{model.xsd_element_collection_name}" type="#{model.xsd_type_collection_name}"/>
158
- <xs:complexType name="#{model.xsd_type_collection_name}">
159
- <xs:sequence>
160
- <xs:element name="#{model.xsd_element_name}" type="#{model.xsd_type_name}" minOccurs="0" maxOccurs="unbounded"/>
161
- </xs:sequence>
162
- <xs:attribute name="type" type="xs:string" fixed="array"/>
163
- </xs:complexType>
164
- <xs:complexType name="#{model.xsd_type_name}">
165
- <xs:all>
166
- #{yield}
167
- </xs:all>
168
- </xs:complexType>
290
+ <xs:element name="#{model.xsd_element_collection_name}" type="#{model.xsd_type_collection_name}"/>
291
+ <xs:complexType name="#{model.xsd_type_collection_name}">
292
+ <xs:sequence>
293
+ <xs:element name="#{model.xsd_element_name}" type="#{model.xsd_type_name}" minOccurs="0" maxOccurs="unbounded"/>
294
+ </xs:sequence>
295
+ <xs:attribute name="type" type="xs:string" fixed="array"/>
296
+ </xs:complexType>
297
+ <xs:complexType name="#{model.xsd_type_name}">
298
+ <xs:all>
299
+ #{yield}
300
+ </xs:all>
301
+ </xs:complexType>
169
302
  </xs:schema>
170
303
  XML
171
304
  end
data/spec/spec_helper.rb CHANGED
@@ -1,5 +1,6 @@
1
1
  require "active_record"
2
2
  require "with_model"
3
+ require "nokogiri"
3
4
  require "schematic"
4
5
 
5
6
  RSpec.configure do |config|