schematic 0.6.2 → 0.7.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (49) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +14 -8
  3. data/.travis.yml +17 -0
  4. data/Gemfile +6 -1
  5. data/LICENSE +1 -1
  6. data/README.md +106 -0
  7. data/Rakefile +3 -8
  8. data/lib/schematic.rb +3 -42
  9. data/lib/schematic/exceptions.rb +13 -0
  10. data/lib/schematic/generator/column.rb +17 -11
  11. data/lib/schematic/generator/namespaces.rb +3 -3
  12. data/lib/schematic/generator/restrictions/base.rb +5 -5
  13. data/lib/schematic/generator/restrictions/custom.rb +3 -2
  14. data/lib/schematic/generator/restrictions/enumeration.rb +5 -2
  15. data/lib/schematic/generator/restrictions/length.rb +4 -2
  16. data/lib/schematic/generator/restrictions/numericality.rb +3 -1
  17. data/lib/schematic/generator/restrictions/pattern.rb +4 -3
  18. data/lib/schematic/generator/sandbox.rb +4 -1
  19. data/lib/schematic/generator/types.rb +14 -13
  20. data/lib/schematic/generator/uniqueness.rb +7 -8
  21. data/lib/schematic/generator/xsd.rb +32 -26
  22. data/lib/schematic/serializers/xsd.rb +6 -6
  23. data/lib/schematic/version.rb +1 -1
  24. data/schematic.gemspec +23 -24
  25. data/spec/schematic/generator/restrictions/custom_spec.rb +15 -18
  26. data/spec/schematic/generator/restrictions/enumeration_spec.rb +31 -31
  27. data/spec/schematic/generator/restrictions/length_spec.rb +35 -30
  28. data/spec/schematic/generator/restrictions/mixin_spec.rb +11 -15
  29. data/spec/schematic/generator/restrictions/numericality_spec.rb +11 -11
  30. data/spec/schematic/generator/restrictions/pattern_spec.rb +20 -21
  31. data/spec/schematic/generator/sandbox_spec.rb +17 -17
  32. data/spec/schematic/generator/uniqueness_spec.rb +38 -37
  33. data/spec/schematic/serializers/xsd_extend_spec.rb +11 -11
  34. data/spec/schematic/serializers/xsd_validation_presence_spec.rb +16 -11
  35. data/spec/schematic/serializers/xsd_xsd_ignore_methods_spec.rb +3 -3
  36. data/spec/schematic/serializers/xsd_xsd_methods_spec.rb +27 -24
  37. data/spec/schematic/serializers/xsd_xsd_minimum_occurrences_for_spec.rb +13 -8
  38. data/spec/schematic_serializers_xsd_spec.rb +70 -67
  39. data/spec/spec_helper.rb +8 -113
  40. data/spec/support/database.rb +9 -0
  41. data/spec/support/helpers.rb +111 -0
  42. data/spec/support/with_model.rb +5 -0
  43. data/spec/{xsd → support/xsd}/XMLSchema.xsd +0 -0
  44. data/spec/{xsd → support/xsd}/xml.xsd +0 -0
  45. metadata +54 -69
  46. data/.rspec +0 -1
  47. data/.rvmrc +0 -1
  48. data/README.rdoc +0 -103
  49. data/spec/support/extensions/active_model/validations/inclusion.rb +0 -69
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9c76641aa454b778d4e26f79dc681629dcf6ef6a
4
+ data.tar.gz: dd47b6effb9ca6bc3036f8a71ebc840faba17fa4
5
+ SHA512:
6
+ metadata.gz: 910d7a63f610016582b3c8d0a9e569e5c0d5cb2846582c7f142dfe6fa693d024d8f149ea37dc812eecf572c8e83bcbf2b635fd6bb84c6ff81f2f91265f99952a
7
+ data.tar.gz: 0846991be161e75ac8e44c4c22b2f097ad5a2536926c11cf697603314560b6098f2936237c81919fc94af325eced78b1c139d11a423542faa8d47d83fad24710
data/.gitignore CHANGED
@@ -1,11 +1,17 @@
1
- .pairs
2
1
  *.gem
3
- *~
4
- .DS_Store
2
+ *.rbc
5
3
  .bundle
6
- .idea
7
- .vimlog
4
+ .config
5
+ .yardoc
8
6
  Gemfile.lock
9
- doc
10
- pkg/*
11
- tags
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
data/.travis.yml ADDED
@@ -0,0 +1,17 @@
1
+ language: ruby
2
+
3
+ rvm:
4
+ - "1.9"
5
+ - "2.0"
6
+ - "2.1"
7
+ - "jruby-19mode"
8
+ - "rbx-2.2"
9
+
10
+ env:
11
+ - ACTIVE_RECORD_BRANCH="master"
12
+ - ACTIVE_RECORD_VERSION="~> 4.1.0"
13
+ - ACTIVE_RECORD_VERSION="~> 4.0.0"
14
+
15
+ matrix:
16
+ allow_failures:
17
+ - env: ACTIVE_RECORD_BRANCH="master"
data/Gemfile CHANGED
@@ -1,4 +1,9 @@
1
- source "http://rubygems.org"
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in schematic.gemspec
4
4
  gemspec
5
+
6
+ gem 'activerecord', :github => 'rails', :branch => ENV['ACTIVE_RECORD_BRANCH'] if ENV['ACTIVE_RECORD_BRANCH']
7
+ gem 'activerecord', ENV['ACTIVE_RECORD_VERSION'] if ENV['ACTIVE_RECORD_VERSION']
8
+ gem 'activerecord-jdbcsqlite3-adapter', :platforms => :jruby
9
+ gem 'sqlite3', '1.3.8', :platforms => :ruby
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010-11 Case Commons, LLC
1
+ Copyright (c) 2010-2014 Case Commons, LLC
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining a copy
4
4
  of this software and associated documentation files (the "Software"), to deal
data/README.md ADDED
@@ -0,0 +1,106 @@
1
+ # [Schematic](http://github.com/casecommons/schematic/)
2
+
3
+ [![Build Status](https://secure.travis-ci.org/Casecommons/schematic.svg?branch=master)](https://travis-ci.org/Casecommons/schematic)
4
+ [![Code Climate](https://img.shields.io/codeclimate/github/Casecommons/schematic.svg)](https://codeclimate.com/github/Casecommons/schematic)
5
+ [![Gem Version](https://badge.fury.io/rb/schematic.svg)](https://rubygems.org/gems/schematic)
6
+
7
+ Automatic XSD generation for your ActiveRecord models.
8
+
9
+ ## Installation
10
+
11
+ Install as usual: `gem install schematic` or add `gem 'schematic'` to your Gemfile. See `.travis.yml` for supported (tested) Ruby versions.
12
+
13
+ ## Usage
14
+
15
+ ```ruby
16
+ class Post < ActiveRecord::Base
17
+ end
18
+
19
+ Post.to_xsd #=> (a bunch of xml)
20
+ ```
21
+
22
+ Validations will automatically add restrictions to the XSD for fields. If a validation has a conditional if or unless option it will be skipped. However if you wish to force the inclusion of the validation in the XSD you can set: `{ :xsd => { :include => true } }` in the options e.g.
23
+
24
+ ```ruby
25
+ class Post < ActiveRecord::Base
26
+ validates :category, :inclusion => { :in => ["foo", "bar"], :xsd => { :include => true } }, :if => lambda { ... }
27
+ end
28
+ ```
29
+
30
+ You can include or exclude additional elements:
31
+
32
+ ```ruby
33
+ class Post < ActiveRecord::Base
34
+ schematic do
35
+ element :title
36
+ element :author => [:name, :email, :url]
37
+ element :blog => { :post => { :category => nil } }
38
+ ignore :comments
39
+ ignore :attachments => [:filetype]
40
+ end
41
+ end
42
+ ```
43
+
44
+ You can also change the name of the root tag:
45
+
46
+ ```ruby
47
+ class Post < ActiveRecord::Base
48
+ schematic do
49
+ root "blog-post"
50
+ end
51
+ end
52
+ ```
53
+
54
+ If you want to programatically include or exclude elements use `Post#schematic_sandbox.added_elements` and `Post#schematic_sandbox.ignored_elements`.
55
+
56
+ The former is a Hash and the latter is an Array.
57
+
58
+ You can define your own custom restrictions by inheriting from the Restrictions Base class:
59
+
60
+ ```ruby
61
+ class MyCustomRestriction < Schematic::Generator::Restrictions::Base
62
+ def generate(builder)
63
+ for_validator ActiveModel::BlockValidator do |validator|
64
+ builder.xs(:enumeration, "value" => "foo")
65
+ builder.xs(:enumeration, "value" => "bar")
66
+ end
67
+ end
68
+ end
69
+ ```
70
+
71
+ You can have a custom pattern restriction from a custom validator:
72
+
73
+ ```ruby
74
+ class MyValidator < ActiveModel::EachValidator
75
+ def validate_each(record, attribute, value)
76
+ # ...
77
+ end
78
+
79
+ def xsd_pattern_restrictions
80
+ [/foo/, /bar/]
81
+ end
82
+ end
83
+ ```
84
+
85
+ You can have a custom enumeration restriction from a custom validator:
86
+
87
+ ```ruby
88
+ class MyValidator < ActiveModel::EachValidator
89
+ def validate_each(record, attribute, value)
90
+ # ...
91
+ end
92
+
93
+ def xsd_field_enumeration_restrictions
94
+ ["foo", "bar"]
95
+ end
96
+ end
97
+ ```
98
+
99
+ ## Requirements
100
+
101
+ - ActiveRecord 4.x
102
+
103
+ ## License
104
+
105
+ Copyright © 2010–2014 Case Commons, LLC.
106
+ Licensed under the MIT license, available in the “LICENSE” file.
data/Rakefile CHANGED
@@ -1,12 +1,7 @@
1
- require 'rake'
2
- require 'rspec/core'
1
+ require 'bundler/gem_tasks'
3
2
  require 'rspec/core/rake_task'
4
3
 
5
- require 'bundler'
6
- Bundler::GemHelper.install_tasks
4
+ desc 'Run specs'
5
+ RSpec::Core::RakeTask.new
7
6
 
8
7
  task :default => :spec
9
-
10
- desc "Run all specs in spec directory (excluding plugin specs)"
11
- RSpec::Core::RakeTask.new(:spec)
12
-
data/lib/schematic.rb CHANGED
@@ -1,44 +1,5 @@
1
- module Schematic
2
- class ClassMissingXmlSerializer < Exception
3
- def message
4
- "This class does not include ActiveModel::Serializers::Xml. You cannot generate an XSD from it."
5
- end
6
- end
7
-
8
- class ClassMissingAttributes < Exception
9
- def message
10
- "This class does not implement #attributes. You cannot generate an XSD from it."
11
- end
12
- end
13
-
14
- module Generator
15
- autoload :Sandbox, 'schematic/generator/sandbox'
16
- autoload :Xsd, 'schematic/generator/xsd'
17
- autoload :Names, 'schematic/generator/names'
18
- autoload :Namespaces, 'schematic/generator/namespaces'
19
- autoload :Column, 'schematic/generator/column'
20
- autoload :ColumnValidator, 'schematic/generator/column_validator'
21
- autoload :Types, 'schematic/generator/types'
22
- autoload :Uniqueness, 'schematic/generator/uniqueness'
23
-
24
- module Restrictions
25
- autoload :Base, 'schematic/generator/restrictions/base'
26
- autoload :Custom, 'schematic/generator/restrictions/custom'
27
- autoload :Enumeration, 'schematic/generator/restrictions/enumeration'
28
- autoload :Length, 'schematic/generator/restrictions/length'
29
- autoload :Pattern, 'schematic/generator/restrictions/pattern'
30
- autoload :Numericality, 'schematic/generator/restrictions/numericality'
31
- end
32
- end
33
- module Serializers
34
- autoload :Xsd, 'schematic/serializers/xsd'
35
- end
36
-
37
- autoload :Version, 'schematic/version'
38
- end
39
-
40
- require "builder"
41
- require 'active_support/inflector/inflections'
42
- require 'active_support/inflections'
1
+ require 'schematic/version'
2
+ require 'schematic/serializers/xsd'
43
3
 
4
+ require 'active_record/base'
44
5
  ActiveRecord::Base.send(:extend, Schematic::Serializers::Xsd)
@@ -0,0 +1,13 @@
1
+ module Schematic
2
+ class ClassMissingXmlSerializer < Exception
3
+ def message
4
+ 'This class does not include ActiveModel::Serializers::Xml. You cannot generate an XSD from it.'
5
+ end
6
+ end
7
+
8
+ class ClassMissingAttributes < Exception
9
+ def message
10
+ 'This class does not implement #attributes. You cannot generate an XSD from it.'
11
+ end
12
+ end
13
+ end
@@ -1,11 +1,17 @@
1
+ require 'active_model/validations/presence'
2
+ require 'schematic/generator/restrictions/custom'
3
+ require 'schematic/generator/restrictions/enumeration'
4
+ require 'schematic/generator/restrictions/length'
5
+ require 'schematic/generator/restrictions/numericality'
6
+ require 'schematic/generator/restrictions/pattern'
7
+
1
8
  module Schematic
2
9
  module Generator
3
10
  class Column
4
11
  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
12
+
13
+ def self.restriction_classes
14
+ Restrictions::Base.descendants.freeze
9
15
  end
10
16
 
11
17
  def initialize(klass, column, additional_methods = {}, ignored_methods = {}, required_methods = [], non_required_methods = [])
@@ -21,16 +27,16 @@ module Schematic
21
27
  return if skip_generation?
22
28
 
23
29
  options = {
24
- "name" => @column.name.dasherize,
25
- "minOccurs" => minimum_occurrences_for_column.to_s,
26
- "maxOccurs" => "1"
30
+ 'name' => @column.name.dasherize,
31
+ 'minOccurs' => minimum_occurrences_for_column.to_s,
32
+ 'maxOccurs' => '1'
27
33
  }
28
- options.merge!({"nillable" => "false"}) if minimum_occurrences_for_column > 0
34
+ options.merge!({'nillable' => 'false'}) if minimum_occurrences_for_column > 0
29
35
 
30
36
  builder.xs :element, options do |field|
31
37
  field.xs :complexType do |complex_type|
32
38
  complex_type.xs :simpleContent do |simple_content|
33
- simple_content.xs :restriction, "base" => map_type(@column) do |restriction|
39
+ simple_content.xs :restriction, 'base' => map_type(@column) do |restriction|
34
40
  self.class.restriction_classes.each do |restriction_class|
35
41
  restriction_class.new(@klass, @column).generate(restriction)
36
42
  end
@@ -45,7 +51,7 @@ module Schematic
45
51
  return 1 if @required_methods.include?(@column.name.to_sym)
46
52
  return 0 unless @klass.respond_to?(:_validators)
47
53
  @klass._validators[@column.name.to_sym].each do |column_validation|
48
- next unless column_validation.is_a? ActiveModel::Validations::PresenceValidator
54
+ next unless column_validation.is_a? ActiveModel::Validations::PresenceValidator
49
55
  if column_validation.options[:allow_blank] != true &&
50
56
  column_validation.options[:if].nil? &&
51
57
  column_validation.options[:unless].nil?
@@ -57,7 +63,7 @@ module Schematic
57
63
  end
58
64
 
59
65
  def map_type(column)
60
- Types::COMPLEX[column.type][:complex_type]
66
+ Types::COMPLEX.fetch(column.type)[:complex_type]
61
67
  end
62
68
 
63
69
  def skip_generation?
@@ -3,9 +3,9 @@ module Schematic
3
3
  class Namespaces
4
4
  PROVIDERS = {
5
5
  :w3 => {
6
- :schema => "http://www.w3.org/2001/XMLSchema"
7
- }
8
- }
6
+ :schema => 'http://www.w3.org/2001/XMLSchema'.freeze
7
+ }.freeze
8
+ }.freeze
9
9
  end
10
10
  end
11
11
  end
@@ -1,13 +1,13 @@
1
+ require 'active_support/descendants_tracker'
2
+ require 'schematic/generator/column'
3
+ require 'schematic/generator/column_validator'
4
+
1
5
  module Schematic
2
6
  module Generator
3
7
  module Restrictions
4
8
  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)
7
- end
9
+ extend ActiveSupport::DescendantsTracker
8
10
  end
9
11
  end
10
12
  end
11
13
  end
12
-
13
-
@@ -1,3 +1,5 @@
1
+ require 'schematic/generator/restrictions/base'
2
+
1
3
  module Schematic
2
4
  module Generator
3
5
  module Restrictions
@@ -6,7 +8,7 @@ module Schematic
6
8
  validators_for_column.each do |validator|
7
9
  if validator.respond_to?(:xsd_pattern_restrictions)
8
10
  validator.xsd_pattern_restrictions.each do |restriction|
9
- builder.xs(:pattern, "value" => restriction.is_a?(Regexp) ? restriction.source : restriction)
11
+ builder.xs(:pattern, 'value' => restriction.is_a?(Regexp) ? restriction.source : restriction)
10
12
  end
11
13
  return
12
14
  end
@@ -16,4 +18,3 @@ module Schematic
16
18
  end
17
19
  end
18
20
  end
19
-
@@ -1,3 +1,6 @@
1
+ require 'active_model/validations/inclusion'
2
+ require 'schematic/generator/restrictions/base'
3
+
1
4
  module Schematic
2
5
  module Generator
3
6
  module Restrictions
@@ -11,13 +14,13 @@ module Schematic
11
14
  valid_values = validator.options[:in]
12
15
  end
13
16
  valid_values.each do |value|
14
- builder.xs(:enumeration, "value" => value)
17
+ builder.xs(:enumeration, 'value' => value)
15
18
  end
16
19
  end
17
20
  enumeration_method = "xsd_#{column.name}_enumeration_restrictions".to_sym
18
21
  if klass.respond_to? enumeration_method
19
22
  klass.send(enumeration_method).each do |enumeration|
20
- builder.xs(:enumeration, "value" => enumeration)
23
+ builder.xs(:enumeration, 'value' => enumeration)
21
24
  end
22
25
  end
23
26
  end
@@ -1,11 +1,13 @@
1
+ require 'schematic/generator/restrictions/base'
2
+
1
3
  module Schematic
2
4
  module Generator
3
5
  module Restrictions
4
6
  class Length < Base
5
7
  def generate(builder)
6
8
  for_validator ActiveModel::Validations::LengthValidator do |validator|
7
- builder.xs(:maxLength, "value" => validator.options[:maximum]) if validator.options[:maximum]
8
- builder.xs(:minLength, "value" => validator.options[:minimum]) if validator.options[:minimum]
9
+ builder.xs(:maxLength, 'value' => validator.options[:maximum]) if validator.options[:maximum]
10
+ builder.xs(:minLength, 'value' => validator.options[:minimum]) if validator.options[:minimum]
9
11
  end
10
12
  end
11
13
  end
@@ -1,10 +1,12 @@
1
+ require 'schematic/generator/restrictions/base'
2
+
1
3
  module Schematic
2
4
  module Generator
3
5
  module Restrictions
4
6
  class Numericality < Base
5
7
  def generate(builder)
6
8
  for_validator ActiveModel::Validations::NumericalityValidator do |validator|
7
- builder.xs(:pattern, "value" => "\\d+")
9
+ builder.xs(:pattern, 'value' => '\d+')
8
10
  end
9
11
  end
10
12
  end
@@ -1,3 +1,6 @@
1
+ require 'active_model/validations/format'
2
+ require 'schematic/generator/restrictions/base'
3
+
1
4
  module Schematic
2
5
  module Generator
3
6
  module Restrictions
@@ -10,7 +13,7 @@ module Schematic
10
13
  value.gsub!(/(?:\$|\\Z|\\z)?$/, '')
11
14
  value.gsub!(/\\\$/, '$')
12
15
  value.gsub!(/\(\?:/, '(')
13
- builder.xs(:pattern, "value" => value)
16
+ builder.xs(:pattern, 'value' => value)
14
17
  end
15
18
  end
16
19
  end
@@ -18,5 +21,3 @@ module Schematic
18
21
  end
19
22
  end
20
23
  end
21
-
22
-