dslize 0.0.1

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/.gitignore ADDED
@@ -0,0 +1,20 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ coverage
6
+ InstalledFiles
7
+ lib/bundler/man
8
+ pkg
9
+ rdoc
10
+ spec/reports
11
+ test/tmp
12
+ test/version_tmp
13
+ tmp
14
+
15
+ Gemfile.lock
16
+
17
+ # YARD artifacts
18
+ .yardoc
19
+ _yardoc
20
+ doc/
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
data/README.md ADDED
@@ -0,0 +1,92 @@
1
+ # DSLize #
2
+
3
+ ## Summary ##
4
+
5
+ Finally an way to generate code with a custom DSL the ruby way !
6
+
7
+ ### In brief: ###
8
+
9
+ * Use real ruby classes to define your DSL
10
+ * Add custom behaviors defining ruby methods
11
+ * Create custom formatters/generators extending a base class
12
+ * Module `DSLize::Methods` defines how your attributes are interpreted, include `DSLize::Methods::Base` to has the standard attributes
13
+ * Module `DSLize::Definition` defines your DSL
14
+
15
+ ## Installation ##
16
+
17
+ gem install dslize
18
+
19
+ then:
20
+
21
+ require "dslize"
22
+
23
+ ## Sample ##
24
+
25
+ #! /usr/bin/env ruby
26
+
27
+ require 'dslize'
28
+
29
+ module DSLize::Methods
30
+ include DSLize::Methods::Base
31
+
32
+ def self.my_first_custom_method(attr, args = {})
33
+ args[:type] = :custom
34
+ DSLize.current_object[attr] = args
35
+ end
36
+
37
+ def self.my_second_custom_method
38
+ DSLize.current_object['baz'] = true
39
+ end
40
+
41
+ end
42
+
43
+ module DSLize::Definition
44
+
45
+ class City
46
+ string :name
47
+ integer :population, :default => 42
48
+ end
49
+
50
+ class Country
51
+ string :name, :default => 'France'
52
+
53
+ has_many City, :as => :cities
54
+
55
+ has_one City, :as => :capital
56
+ end
57
+
58
+ class World
59
+ root
60
+
61
+ has_many Country
62
+
63
+ my_first_custom_method :foo, :default => 'bar'
64
+
65
+ my_second_custom_method
66
+ end
67
+
68
+ class Planet
69
+ abstract
70
+ end
71
+
72
+ class GazPlanet < Planet
73
+ end
74
+
75
+ class WaterPlanet < Planet
76
+ end
77
+
78
+ end
79
+
80
+ class MyCustomFormatter < DSLize::Formatter::Base
81
+ def do_stuff
82
+ # with self.object
83
+ # and self.superclasses
84
+ end
85
+ end
86
+
87
+ DSLize::Formatter::XSD.new.generate!("/tmp/schema.xsd")
88
+ MyCustomFormatter.new.do_stuff
89
+
90
+ ## About me ##
91
+
92
+ Sylvain UTARD - http://sylvain.utard.info
data/Rakefile ADDED
@@ -0,0 +1,3 @@
1
+ require 'bundler'
2
+
3
+ Bundler::GemHelper.install_tasks
data/dslize.gemspec ADDED
@@ -0,0 +1,20 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "dslize/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "dslize"
7
+ s.version = DSLize::VERSION
8
+ s.platform = Gem::Platform::RUBY
9
+ s.authors = ['redox']
10
+ s.email = ['sylvain.utard@gmail.com']
11
+ s.homepage = "https://github.com/utard/dslize"
12
+ s.summary = %q{DSL made easy}
13
+ s.description = %q{}
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+ s.requirements << 'xpain'
20
+ end
@@ -0,0 +1,91 @@
1
+ class Object
2
+
3
+ def self.method_missing(method_name, *args, &block)
4
+ return DSLize::Methods.send(method_name, *args) if self.name['DSLize::Definition::'] and DSLize::Methods.respond_to?(method_name)
5
+ super.method_missing(method_name, args, &block)
6
+ end
7
+
8
+ def self.inherited(subclass)
9
+ if subclass.name['DSLize::Definition::']
10
+ superclass = subclass.superclass
11
+ subclass = subclass.name.split('::').last
12
+ DSLize.objects ||= {}
13
+ DSLize.objects[subclass] = {}
14
+ DSLize.current_object = DSLize.objects[subclass]
15
+ DSLize.superclasses ||= {}
16
+ DSLize.superclasses[subclass] = superclass.name.split('::').last
17
+ end
18
+ end
19
+
20
+ end
21
+
22
+ module DSLize
23
+
24
+ class << self
25
+ attr_accessor :objects
26
+ attr_accessor :current_object
27
+ attr_accessor :superclasses
28
+ end
29
+
30
+ module Methods
31
+
32
+ module Base
33
+
34
+ def self.included(receiver)
35
+ receiver.extend(ClassMethods)
36
+ end
37
+
38
+ module ClassMethods
39
+
40
+ def string(attr, args = {})
41
+ attribute(:string, attr, args)
42
+ end
43
+
44
+ def integer(attr, args = {})
45
+ attribute(:integer, attr, args)
46
+ end
47
+
48
+ def double(attr, args = {})
49
+ attribute(:double, attr, args)
50
+ end
51
+
52
+ def has_many(attr, args = {})
53
+ relation(:has_many, attr, args)
54
+ end
55
+
56
+ def has_one(attr, args = {})
57
+ relation(:has_one, attr, args)
58
+ end
59
+
60
+ def root
61
+ DSLize.current_object[:root] = true
62
+ end
63
+
64
+ def abstract
65
+ DSLize.current_object[:abstract] = true
66
+ end
67
+
68
+ private
69
+ def attribute(type, name, args)
70
+ args[:type] = type
71
+ DSLize.current_object[:attributes] = {}
72
+ DSLize.current_object[:attributes][name] = args
73
+ end
74
+
75
+ def relation(type, name, args)
76
+ name = (name.name rescue name.to_s).split('::').last
77
+ args[:type] = name
78
+ if as = args.delete(:as)
79
+ name = as.to_s
80
+ end
81
+ DSLize.current_object[type] ||= {}
82
+ DSLize.current_object[type][name] = args
83
+ end
84
+
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+
91
+ end
@@ -0,0 +1,16 @@
1
+ module DSLize
2
+ module Formatter
3
+
4
+ class Base
5
+ attr_accessor :objects
6
+ attr_accessor :superclasses
7
+
8
+ def initialize
9
+ self.objects = DSLize.objects
10
+ self.superclasses = DSLize.superclasses
11
+ end
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,91 @@
1
+ require File.dirname(__FILE__) + '/formatter'
2
+
3
+ module DSLize
4
+ module Formatter
5
+
6
+ class XSD < Base
7
+
8
+ def generate!(*args)
9
+ schema = XPain::Builder.new do |xsd|
10
+ xsd.schema do
11
+ objects.each do |name, options|
12
+ parent = superclasses[name]
13
+
14
+ xsd.element(name, :type => (options[:type] or name))
15
+
16
+ xsd.complexType({ :name => name, :abstract => options[:abstract], :mixed => false }.select { |k,v| !v.nil? }) do
17
+ extends_base_if_needed(xsd, parent) do
18
+
19
+ # relations
20
+ xsd.sequence do
21
+ { :has_one => nil, :has_many => "unbounded"}.each do |relation, max_occurs|
22
+ (options[relation] or []).each do |k, v|
23
+ named_object_if_needed(xsd, k, v) do
24
+ xsd.element(nil, { :ref => (v[:type] or k), :maxOccurs => max_occurs }.select { |k,v| !v.nil? })
25
+ end
26
+ end
27
+ end
28
+ end
29
+
30
+ # attributes
31
+ (options[:attributes] or []).each do |k, v|
32
+ xsd.attribute({ :name => k, :default => v[:default], :type => xsd_type(v[:type]) }.select { |k,v| !v.nil? })
33
+ end
34
+
35
+ end
36
+ end
37
+
38
+ end
39
+ end
40
+ end
41
+
42
+ File.open(args[0], "w") do |f|
43
+ f << schema.to_xml.gsub(' name=""', '') # xpain is buggy and always write a name on <element>
44
+ end
45
+ end
46
+
47
+ private
48
+ def extends_base_if_needed(xsd, parent)
49
+ if parent != "Object"
50
+ xsd.complexContent :mixed => false do
51
+ xsd.extension :base => parent do
52
+ yield
53
+ end
54
+ end
55
+ else
56
+ yield
57
+ end
58
+ end
59
+
60
+ def named_object_if_needed(xsd, name, options)
61
+ if options[:type] and name != options[:type]
62
+ xsd.element name, :contains => 'none' do
63
+ xsd.complexType do
64
+ xsd.sequence do
65
+ yield
66
+ end
67
+ end
68
+ end
69
+ else
70
+ yield
71
+ end
72
+ end
73
+
74
+ def xsd_type(type)
75
+ case type
76
+ when :float
77
+ "xsd:double"
78
+ when :integer
79
+ "xsd:int"
80
+ when :string
81
+ "xsd:string"
82
+ else
83
+ type
84
+ end
85
+ end
86
+
87
+ end
88
+
89
+ end
90
+
91
+ end
@@ -0,0 +1,3 @@
1
+ module DSLize
2
+ VERSION = "0.0.1"
3
+ end
data/lib/dslize.rb ADDED
@@ -0,0 +1,6 @@
1
+ module DSLize
2
+ require 'xpain'
3
+
4
+ require File.dirname(__FILE__) + '/dslize/dslize'
5
+ require File.dirname(__FILE__) + '/dslize/formatter/xsd_formatter'
6
+ end
data/sample.rb ADDED
@@ -0,0 +1,61 @@
1
+ #! /usr/bin/env ruby
2
+
3
+ begin
4
+ # dev mode
5
+ require File.dirname(__FILE__) + '/lib/dslize'
6
+ rescue
7
+ require 'dslize'
8
+ end
9
+
10
+ module DSLize::Methods
11
+ include DSLize::Methods::Base
12
+
13
+ def self.my_first_custom_method(attr, args = {})
14
+ args[:type] = :custom
15
+ DSLize.current_object[attr] = args
16
+ end
17
+
18
+ def self.my_second_custom_method
19
+ DSLize.current_object['baz'] = true
20
+ end
21
+
22
+ end
23
+
24
+ module DSLize::Definition
25
+
26
+ class City
27
+ string :name
28
+ integer :population, :default => 42
29
+ end
30
+
31
+ class Country
32
+ string :name, :default => 'France'
33
+
34
+ has_many City, :as => :cities
35
+
36
+ has_one City, :as => :capital
37
+ end
38
+
39
+ class World
40
+ root
41
+
42
+ has_many Country
43
+
44
+ my_first_custom_method :foo, :default => 'bar'
45
+
46
+ my_second_custom_method
47
+ end
48
+
49
+ class Planet
50
+ abstract
51
+ end
52
+
53
+ class GazPlanet < Planet
54
+ end
55
+
56
+ class WaterPlanet < Planet
57
+ end
58
+
59
+ end
60
+
61
+ DSLize::Formatter::XSD.new.generate!(ARGV[0])
metadata ADDED
@@ -0,0 +1,73 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: dslize
3
+ version: !ruby/object:Gem::Version
4
+ prerelease: false
5
+ segments:
6
+ - 0
7
+ - 0
8
+ - 1
9
+ version: 0.0.1
10
+ platform: ruby
11
+ authors:
12
+ - redox
13
+ autorequire:
14
+ bindir: bin
15
+ cert_chain: []
16
+
17
+ date: 2012-07-10 00:00:00 +02:00
18
+ default_executable:
19
+ dependencies: []
20
+
21
+ description: ""
22
+ email:
23
+ - sylvain.utard@gmail.com
24
+ executables: []
25
+
26
+ extensions: []
27
+
28
+ extra_rdoc_files: []
29
+
30
+ files:
31
+ - .gitignore
32
+ - Gemfile
33
+ - README.md
34
+ - Rakefile
35
+ - dslize.gemspec
36
+ - lib/dslize.rb
37
+ - lib/dslize/dslize.rb
38
+ - lib/dslize/formatter/formatter.rb
39
+ - lib/dslize/formatter/xsd_formatter.rb
40
+ - lib/dslize/version.rb
41
+ - sample.rb
42
+ has_rdoc: true
43
+ homepage: https://github.com/utard/dslize
44
+ licenses: []
45
+
46
+ post_install_message:
47
+ rdoc_options: []
48
+
49
+ require_paths:
50
+ - lib
51
+ required_ruby_version: !ruby/object:Gem::Requirement
52
+ requirements:
53
+ - - ">="
54
+ - !ruby/object:Gem::Version
55
+ segments:
56
+ - 0
57
+ version: "0"
58
+ required_rubygems_version: !ruby/object:Gem::Requirement
59
+ requirements:
60
+ - - ">="
61
+ - !ruby/object:Gem::Version
62
+ segments:
63
+ - 0
64
+ version: "0"
65
+ requirements:
66
+ - xpain
67
+ rubyforge_project:
68
+ rubygems_version: 1.3.6
69
+ signing_key:
70
+ specification_version: 3
71
+ summary: DSL made easy
72
+ test_files: []
73
+