dm-metamapper 0.0.3 → 0.0.4
Sign up to get free protection for your applications and to get access to all the features.
- data/.autospec +6 -0
- data/.gitignore +2 -0
- data/Gemfile +1 -0
- data/VERSION +1 -1
- data/example/Makefile +1 -1
- data/example/example.rb +1 -6
- data/lib/dm-metamapper/config.rb +21 -0
- data/lib/dm-metamapper/extension.rb +7 -10
- data/lib/dm-metamapper/generator.rb +53 -76
- data/lib/dm-metamapper/generators/cpp.rb +68 -0
- data/lib/dm-metamapper/metamapper.rb +17 -45
- data/lib/dm-metamapper/template.rb +53 -0
- data/lib/dm-metamapper.rb +2 -0
- data/lib/templates/cpp/class.hpp.erb +14 -16
- data/lib/templates/cpp/dmmm_identifiers.hpp.erb +1 -1
- data/lib/templates/cpp/instance.hpp.erb +22 -27
- data/spec/dm-metamapper/generator_spec.rb +62 -0
- data/spec/dm-metamapper/template_spec.rb +29 -0
- data/spec/spec.opts +4 -0
- data/spec/spec_helper.rb +3 -1
- metadata +12 -5
- data/dm-metamapper.gemspec +0 -66
- data/output/.gitignore +0 -1
data/.autospec
ADDED
data/Gemfile
CHANGED
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.0.
|
1
|
+
0.0.4
|
data/example/Makefile
CHANGED
@@ -1,4 +1,4 @@
|
|
1
1
|
all:
|
2
2
|
echo "generating code"
|
3
|
-
cd ..; bundle exec ruby -r example/example.rb -e "DataMapper::MetaMapper.generate(:cpp)"
|
3
|
+
cd ..; bundle exec ruby -r example/example.rb -e "DataMapper::MetaMapper.generate(:cpp, :output_dir => './output')"
|
4
4
|
g++ ../output/dmmm_utils.cpp ../output/dmmm_dbface.cpp example.cpp -I ../output -I /usr/include/mysql -I /usr/local/include/mysql++ -I /usr/local/mysql/include/mysql -lmysqlpp -lmysqlclient /usr/lib/libboost_thread-mt.so -L/usr/lib -L/usr/local/lib -Wall -o example
|
data/example/example.rb
CHANGED
@@ -4,6 +4,7 @@ require "bundler"
|
|
4
4
|
Bundler.setup(:default, :test)
|
5
5
|
require "dm-core"
|
6
6
|
require "lib/dm-metamapper.rb"
|
7
|
+
require "dm-metamapper/generators/cpp"
|
7
8
|
|
8
9
|
#DataMapper.setup(:default, "sqlite3::memory:")
|
9
10
|
DataMapper.setup(:default, "mysql://root@localhost/dmmm")
|
@@ -12,8 +13,6 @@ class User
|
|
12
13
|
include DataMapper::Resource
|
13
14
|
extend DataMapper::MetaMapper::Extension
|
14
15
|
|
15
|
-
generates :cpp
|
16
|
-
|
17
16
|
has n, :dogs
|
18
17
|
|
19
18
|
property :id, Serial
|
@@ -26,8 +25,6 @@ class Dog
|
|
26
25
|
include DataMapper::Resource
|
27
26
|
extend DataMapper::MetaMapper::Extension
|
28
27
|
|
29
|
-
generates :cpp
|
30
|
-
|
31
28
|
belongs_to :user
|
32
29
|
has n, :little_fleas
|
33
30
|
|
@@ -41,8 +38,6 @@ class LittleFlea
|
|
41
38
|
include DataMapper::Resource
|
42
39
|
extend DataMapper::MetaMapper::Extension
|
43
40
|
|
44
|
-
generates :cpp
|
45
|
-
|
46
41
|
belongs_to :dog
|
47
42
|
|
48
43
|
property :id, Serial
|
@@ -0,0 +1,21 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module MetaMapper
|
3
|
+
class Config < Hash
|
4
|
+
def initialize
|
5
|
+
super
|
6
|
+
self.merge! DataMapper::MetaMapper._default_opts
|
7
|
+
end
|
8
|
+
|
9
|
+
alias_method :use, :merge!
|
10
|
+
|
11
|
+
def method_missing(meth, *args)
|
12
|
+
if keys.include?(meth.to_sym)
|
13
|
+
self[meth.to_sym]
|
14
|
+
else
|
15
|
+
raise NoMethodError, "undefined method `#{meth}' for #{self.class}:#{self.class.class}"
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
@@ -1,12 +1,14 @@
|
|
1
1
|
module DataMapper
|
2
2
|
module MetaMapper
|
3
3
|
module Extension
|
4
|
-
def
|
5
|
-
@
|
4
|
+
def doesnt_generate(*layouts)
|
5
|
+
@_skipped_generation_formats = Array(layouts)
|
6
6
|
end
|
7
|
+
alias_method :dont_generate, :doesnt_generate
|
8
|
+
alias_method :skip_generation, :doesnt_generate
|
7
9
|
|
8
10
|
def generates?(format)
|
9
|
-
|
11
|
+
!@_skipped_generation_formats.include?(format)
|
10
12
|
end
|
11
13
|
|
12
14
|
def generate(format)
|
@@ -19,16 +21,11 @@ module DataMapper
|
|
19
21
|
}
|
20
22
|
end
|
21
23
|
|
22
|
-
def _get_binding
|
23
|
-
binding
|
24
|
-
end
|
25
|
-
|
26
24
|
def self.extended(base)
|
27
25
|
DataMapper::MetaMapper.register(base)
|
28
|
-
base.instance_variable_set(:@
|
29
|
-
class <<base; attr_reader :
|
26
|
+
base.instance_variable_set(:@_skipped_generation_formats, [])
|
27
|
+
class <<base; attr_reader :_skipped_generation_formats end
|
30
28
|
end
|
31
|
-
|
32
29
|
end
|
33
30
|
end
|
34
31
|
end
|
@@ -1,33 +1,15 @@
|
|
1
1
|
module DataMapper
|
2
2
|
module MetaMapper
|
3
3
|
class Generator
|
4
|
-
class
|
5
|
-
def initialize(&blk)
|
6
|
-
instance_eval(&blk) if block_given?
|
7
|
-
end
|
8
|
-
|
9
|
-
attr_reader :template, :file_name_prefix, :file_name_suffix
|
10
|
-
|
11
|
-
def template_name(template)
|
12
|
-
@template = template
|
13
|
-
end
|
14
|
-
|
15
|
-
def prefix(str)
|
16
|
-
@file_name_prefix = str
|
17
|
-
end
|
18
|
-
|
19
|
-
def suffix(str)
|
20
|
-
@file_name_suffix = str
|
21
|
-
end
|
22
|
-
end
|
4
|
+
class NoTemplateError < StandardError; end
|
23
5
|
|
24
6
|
@subclasses = []
|
25
7
|
|
26
8
|
class << self
|
27
9
|
attr_reader :subclasses,
|
28
|
-
:
|
29
|
-
:
|
30
|
-
:
|
10
|
+
:generated_files,
|
11
|
+
:config,
|
12
|
+
:setup_model_blk
|
31
13
|
|
32
14
|
def [](generator)
|
33
15
|
@subclasses.find {|klass| klass.generator_name == generator}
|
@@ -38,77 +20,72 @@ module DataMapper
|
|
38
20
|
@generator_name = name
|
39
21
|
end
|
40
22
|
|
41
|
-
|
42
|
-
|
43
|
-
|
44
|
-
|
45
|
-
@generated_model_files << GeneratedFile.new(&blk)
|
23
|
+
def run(model, opts)
|
24
|
+
@model = model
|
25
|
+
@config.use :output_dir => opts[:output_dir] if opts[:output_dir]
|
26
|
+
new(model).run
|
46
27
|
end
|
47
28
|
|
48
|
-
|
49
|
-
|
50
|
-
|
29
|
+
private
|
30
|
+
|
31
|
+
def generates_file(type, name, opts={})
|
32
|
+
opts.merge! :type => type, :generator => self
|
33
|
+
@generated_files << Template.new(name, opts)
|
51
34
|
end
|
52
35
|
|
53
|
-
def
|
54
|
-
@
|
36
|
+
def setup_model(&blk)
|
37
|
+
@setup_model_blk = blk
|
55
38
|
end
|
56
39
|
|
57
40
|
def inherited(klass)
|
58
41
|
@subclasses ||= []
|
59
42
|
@subclasses << klass
|
60
|
-
klass.instance_variable_set(:@generator_name,
|
43
|
+
klass.instance_variable_set(:@generator_name, klass.name.split("::").last.snake_case.to_sym)
|
44
|
+
klass.instance_variable_set(:@setup_model_blk, Proc.new{})
|
45
|
+
klass.instance_variable_set(:@config, Config.new)
|
46
|
+
klass.instance_variable_set(:@generated_files, TemplateCollection.new)
|
61
47
|
end
|
62
48
|
end
|
63
|
-
end
|
64
|
-
end
|
65
|
-
end
|
66
49
|
|
67
|
-
|
68
|
-
|
69
|
-
|
70
|
-
generator_name :cpp
|
71
|
-
|
72
|
-
generates_global_file{ template_name "dmmm_identifiers.hpp.erb" }
|
73
|
-
generates_global_file{ template_name "dmmm_comparators.hpp.erb" }
|
74
|
-
generates_global_file{ template_name "dmmm_fields.hpp.erb" }
|
75
|
-
generates_global_file{ template_name "dmmm_utils.hpp.erb" }
|
76
|
-
generates_global_file{ template_name "dmmm_utils.cpp.erb" }
|
77
|
-
generates_global_file{ template_name "dmmm_dbface.cpp.erb" }
|
78
|
-
generates_global_file{ template_name "dmmm_dbface.h.erb" }
|
79
|
-
generates_global_file{ template_name "dmmm_id.hpp.erb" }
|
80
|
-
|
81
|
-
proxy do
|
82
|
-
puts "Generating files for model " + self.name.to_s
|
83
|
-
key_to_parent = {}
|
84
|
-
relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |r|
|
85
|
-
key_to_parent[r[1].child_key.first.name.to_s] = r[1].parent_model_name.to_const_string.sub(/::/,'_')
|
86
|
-
puts "#{r[1].child_key.first.name.to_s} -> #{key_to_parent[r[1].child_key.first.name.to_s]}"
|
87
|
-
end
|
50
|
+
# model can be nil or DataMapper::Model
|
51
|
+
def initialize(model)
|
52
|
+
@model = model
|
88
53
|
|
89
|
-
|
90
|
-
|
91
|
-
|
92
|
-
|
93
|
-
|
94
|
-
|
95
|
-
|
54
|
+
instance_eval(&self.class.setup_model_blk) if model
|
55
|
+
|
56
|
+
@templates = if model
|
57
|
+
self.class.generated_files.models
|
58
|
+
else
|
59
|
+
self.class.generated_files.global
|
60
|
+
end
|
96
61
|
end
|
97
62
|
|
98
|
-
|
99
|
-
end
|
100
|
-
end
|
63
|
+
attr_reader :model
|
101
64
|
|
102
|
-
|
103
|
-
|
104
|
-
|
105
|
-
|
106
|
-
|
65
|
+
def run
|
66
|
+
@templates.each {|template| generate template }
|
67
|
+
end
|
68
|
+
|
69
|
+
private
|
70
|
+
|
71
|
+
def models
|
72
|
+
DataMapper::MetaMapper.models
|
73
|
+
end
|
74
|
+
|
75
|
+
def generate(template)
|
76
|
+
if !File.exists? template.full_path
|
77
|
+
raise NoTemplateError, "Template does not exist at path #{template.full_path}"
|
78
|
+
end
|
79
|
+
|
80
|
+
compiled = ERB.new(File.read(template.full_path)).result(binding)
|
81
|
+
path = respond_to?(:output_path) ? output_path(model, template) : template.output_name
|
82
|
+
if !File.exists?(path) || File.read(path) != compiled
|
83
|
+
File.open(path, 'w') {|f| f << compiled}
|
84
|
+
end
|
85
|
+
|
86
|
+
end
|
87
|
+
end
|
107
88
|
|
108
|
-
generates_file do
|
109
|
-
suffix".hpp"
|
110
|
-
prefix "T_"
|
111
|
-
template_name "class.hpp.erb"
|
112
89
|
end
|
113
90
|
end
|
114
91
|
|
@@ -0,0 +1,68 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module MetaMapper
|
3
|
+
module Generators
|
4
|
+
class CPP < DataMapper::MetaMapper::Generator
|
5
|
+
config[:template_dir] = File.expand_path('../../../templates/cpp', __FILE__)
|
6
|
+
|
7
|
+
generates_file :global, "dmmm_identifiers.hpp"
|
8
|
+
generates_file :global, "dmmm_comparators.hpp"
|
9
|
+
generates_file :global, "dmmm_fields.hpp"
|
10
|
+
generates_file :global, "dmmm_utils.hpp"
|
11
|
+
generates_file :global, "dmmm_utils.cpp"
|
12
|
+
generates_file :global, "dmmm_dbface.cpp"
|
13
|
+
generates_file :global, "dmmm_dbface.h"
|
14
|
+
generates_file :global, "dmmm_id.hpp"
|
15
|
+
|
16
|
+
generates_file :model, "O_%model%.hpp", :template => "instance.hpp"
|
17
|
+
generates_file :model, "T_%model%.hpp", :template => "class.hpp"
|
18
|
+
|
19
|
+
setup_model do
|
20
|
+
key_to_parent = many_to_one.inject({}) do |hash, (r,m)|
|
21
|
+
hash[m.child_key.first.name] = decolonize(m.parent_model_name.to_const_string)
|
22
|
+
hash
|
23
|
+
end
|
24
|
+
model.properties.each do |prop|
|
25
|
+
cpp_name = if prop.serial?
|
26
|
+
"Field<I_#{decolonize(model.name)}>"
|
27
|
+
elsif key_to_parent[prop.name]
|
28
|
+
"Field<I_#{key_to_parent[prop.name]}>"
|
29
|
+
else
|
30
|
+
"F_#{decolonize(prop.primitive.to_s)}"
|
31
|
+
end
|
32
|
+
|
33
|
+
(class << prop; self; end).instance_eval{ attr_accessor :cpp_name }
|
34
|
+
prop.cpp_name = cpp_name
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def output_path(model, template)
|
39
|
+
name = model ? template.name.sub("%model%", decolonize(model.name)) : template.name
|
40
|
+
File.join(self.class.config.output_dir, name)
|
41
|
+
end
|
42
|
+
|
43
|
+
private
|
44
|
+
|
45
|
+
def decolonize(str)
|
46
|
+
str.sub(/::/,'_')
|
47
|
+
end
|
48
|
+
|
49
|
+
def many_to_one
|
50
|
+
return unless model
|
51
|
+
@many_to_one ||= model.relationships.select {|r,m|
|
52
|
+
m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'
|
53
|
+
}
|
54
|
+
#in case of ruby < 1.9
|
55
|
+
if Array === @many_to_one
|
56
|
+
temp = @many_to_one
|
57
|
+
@many_to_one = {}
|
58
|
+
temp.each{|t| @many_to_one[t[0]] = t[1]}
|
59
|
+
end
|
60
|
+
|
61
|
+
@many_to_one
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
67
|
+
|
68
|
+
|
@@ -1,59 +1,31 @@
|
|
1
1
|
module DataMapper
|
2
2
|
module MetaMapper
|
3
|
+
@_default_opts = {
|
4
|
+
:template_dir => Dir.pwd,
|
5
|
+
:output_dir => Dir.pwd
|
6
|
+
}
|
7
|
+
|
3
8
|
class << self
|
4
|
-
attr_reader :models
|
9
|
+
attr_reader :models, :_default_opts
|
10
|
+
|
11
|
+
def use(opts)
|
12
|
+
@_default_opts.merge! opts
|
13
|
+
end
|
5
14
|
|
6
15
|
def register(klass)
|
7
16
|
@models ||= []
|
8
17
|
@models << klass unless models.member?(klass)
|
9
18
|
end
|
10
19
|
|
11
|
-
def generate(format,
|
20
|
+
def generate(format, opts = {})
|
21
|
+
context = opts.delete(:context)
|
12
22
|
generator = Generator[format]
|
23
|
+
generator.run(context, opts)
|
13
24
|
|
14
|
-
|
15
|
-
context
|
16
|
-
|
17
|
-
|
18
|
-
type, _binding = :generated_global_files, binding
|
19
|
-
end
|
20
|
-
|
21
|
-
generator.send(type).each do |generated_file|
|
22
|
-
temp_filename = [
|
23
|
-
File.dirname(__FILE__),
|
24
|
-
"../templates",
|
25
|
-
generator.generator_name,
|
26
|
-
generated_file.template
|
27
|
-
].join('/')
|
28
|
-
|
29
|
-
result_base_name = context ? context.name.to_s.sub(/::/,'_') : generated_file.template.sub(/\.erb$/,'')
|
30
|
-
|
31
|
-
result_filename = File.join(
|
32
|
-
File.dirname(__FILE__), "../../output", [
|
33
|
-
generated_file.file_name_prefix,
|
34
|
-
result_base_name,
|
35
|
-
generated_file.file_name_suffix
|
36
|
-
].join
|
37
|
-
)
|
38
|
-
|
39
|
-
if File.exists?(temp_filename)
|
40
|
-
STDOUT.puts "writing file " + result_filename
|
41
|
-
template = ERB.new(File.read(temp_filename))
|
42
|
-
result = template.result(_binding)
|
43
|
-
File.open(result_filename, 'w') { |f| f << result }
|
44
|
-
else
|
45
|
-
STDERR.puts "ERROR: " + temp_filename + " does not exist"
|
46
|
-
end
|
47
|
-
end
|
48
|
-
|
49
|
-
if !context
|
50
|
-
models.select {|model|
|
51
|
-
model.generates?(format)
|
52
|
-
}.each {|model|
|
53
|
-
model.generate(format)
|
54
|
-
}
|
55
|
-
end
|
56
|
-
|
25
|
+
models.each {|model|
|
26
|
+
opts[:context] = model
|
27
|
+
generate(format, opts)
|
28
|
+
} if !context
|
57
29
|
end
|
58
30
|
end
|
59
31
|
end
|
@@ -0,0 +1,53 @@
|
|
1
|
+
module DataMapper
|
2
|
+
module MetaMapper
|
3
|
+
class NoGeneratorError < ArgumentError; end
|
4
|
+
class InvalidTypeError < StandardError; end
|
5
|
+
|
6
|
+
class TemplateCollection < Array
|
7
|
+
def models
|
8
|
+
self.select {|t| t.type == :model}
|
9
|
+
end
|
10
|
+
|
11
|
+
def global
|
12
|
+
self.select {|t| t.type == :global}
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
class Template
|
17
|
+
VALID_TYPES = [:global, :model]
|
18
|
+
|
19
|
+
def initialize(name, opts={})
|
20
|
+
@name = name.to_s
|
21
|
+
@generator = parse_generator(opts.delete(:generator))
|
22
|
+
@type = parse_type(opts.delete(:type))
|
23
|
+
@template = (opts.delete(:template) || @name).to_s + ".erb"
|
24
|
+
end
|
25
|
+
|
26
|
+
attr_reader :name, :type
|
27
|
+
|
28
|
+
def output_path
|
29
|
+
File.join(@generator.config.output_dir, @name)
|
30
|
+
end
|
31
|
+
|
32
|
+
def full_path
|
33
|
+
File.join(@generator.config.template_dir, @template)
|
34
|
+
end
|
35
|
+
|
36
|
+
private
|
37
|
+
|
38
|
+
def parse_type(type)
|
39
|
+
unless type && VALID_TYPES.include?(type.to_sym)
|
40
|
+
raise InvalidTypeError, "type `#{type}' is not a recognized template " +
|
41
|
+
"type. Valid types: #{VALID_TYPES.inspect}]"
|
42
|
+
end
|
43
|
+
|
44
|
+
type
|
45
|
+
end
|
46
|
+
|
47
|
+
def parse_generator(generator)
|
48
|
+
generator || raise(NoGeneratorError, "opts did not contain :generator")
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
data/lib/dm-metamapper.rb
CHANGED
@@ -2,7 +2,9 @@ $:.push File.dirname(__FILE__)
|
|
2
2
|
|
3
3
|
require 'dm-core'
|
4
4
|
require 'dm-metamapper/property'
|
5
|
+
require 'dm-metamapper/config'
|
5
6
|
require 'dm-metamapper/metamapper'
|
6
7
|
require 'dm-metamapper/extension'
|
8
|
+
require 'dm-metamapper/template'
|
7
9
|
require 'dm-metamapper/generator'
|
8
10
|
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<% class_name =
|
1
|
+
<% class_name = decolonize(model.name) %>
|
2
2
|
<% all_caps_name = class_name.upcase %>
|
3
3
|
#ifndef T_<%= all_caps_name %>
|
4
4
|
#define T_<%= all_caps_name %>
|
@@ -15,49 +15,47 @@ public:
|
|
15
15
|
|
16
16
|
T_<%= class_name %>()
|
17
17
|
{
|
18
|
-
_tables.push_back("<%= storage_name %>");
|
18
|
+
_tables.push_back("<%= model.storage_name %>");
|
19
19
|
}
|
20
20
|
T_<%= class_name %>(const Condition& c)
|
21
21
|
: _constraint(c)
|
22
22
|
{
|
23
|
-
_tables.push_back("<%= storage_name %>");
|
23
|
+
_tables.push_back("<%= model.storage_name %>");
|
24
24
|
}
|
25
|
-
<%
|
26
|
-
<% parent = r[1].parent_model_name
|
25
|
+
<% many_to_one.each do |r| %>
|
26
|
+
<% parent = decolonize(r[1].parent_model_name) %>
|
27
27
|
T_<%= class_name %>(const T_<%= parent %>& parent)
|
28
28
|
{
|
29
|
-
_tables.push_back("<%= storage_name %>");
|
29
|
+
_tables.push_back("<%= model.storage_name %>");
|
30
30
|
_tables.insert(_tables.end(),
|
31
31
|
parent._tables.begin(), parent._tables.end());
|
32
32
|
|
33
|
-
_constraint._cond = "(<%= storage_name + "." + r[1].child_key.first.name.to_s %> = " + parent._tables[0] + ".<%= r[1].parent_key.first.name.to_s %>)";
|
33
|
+
_constraint._cond = "(<%= model.storage_name + "." + r[1].child_key.first.name.to_s %> = " + parent._tables[0] + ".<%= r[1].parent_key.first.name.to_s %>)";
|
34
34
|
if (!parent._constraint.nil())
|
35
35
|
_constraint._cond += " AND " + parent._constraint._cond;
|
36
36
|
}
|
37
|
-
|
38
37
|
<% end %>
|
39
38
|
|
40
|
-
<% generated_properties.each do |property| %>
|
39
|
+
<% model.generated_properties.each do |property| %>
|
41
40
|
struct E_<%= property.name %>{
|
42
41
|
E_<%= property.name %>()
|
43
42
|
{
|
44
|
-
_field = "<%= storage_name %>.<%= property.name.to_s %>";
|
43
|
+
_field = "<%= model.storage_name %>.<%= property.name.to_s %>";
|
45
44
|
}
|
46
45
|
std::string _field;
|
47
46
|
typedef T_<%= class_name %>::Condition ConditionType;
|
48
|
-
typedef <%= property.
|
47
|
+
typedef <%= property.cpp_name %>::Base ComparerType;
|
49
48
|
};
|
50
49
|
|
51
50
|
E_<%= property.name %> _<%= property.name %>(){
|
52
51
|
return E_<%= property.name %>();
|
53
52
|
}
|
54
|
-
|
55
53
|
<% end %>
|
56
54
|
|
57
55
|
void getFields(std::vector<std::string>& rFields)
|
58
56
|
{
|
59
57
|
rFields.clear();
|
60
|
-
<% generated_properties.each do |property| %>
|
58
|
+
<% model.generated_properties.each do |property| %>
|
61
59
|
rFields.push_back("<%= property.name %>");
|
62
60
|
<% end %>
|
63
61
|
}
|
@@ -74,9 +72,9 @@ public:
|
|
74
72
|
additional, res);
|
75
73
|
r.resize(res.size());
|
76
74
|
for(size_t i = 0; i < res.size(); ++i){
|
77
|
-
<% generated_properties.each do |property| %>
|
75
|
+
<% model.generated_properties.each do |property| %>
|
78
76
|
r[i]._f_<%= property.name %>._base =
|
79
|
-
UTILS::fromString<<%= property.
|
77
|
+
UTILS::fromString<<%= property.cpp_name %>::Base>(res[i]["<%= property.name %>"]);
|
80
78
|
<% end %>
|
81
79
|
}
|
82
80
|
}
|
@@ -104,7 +102,7 @@ public:
|
|
104
102
|
}
|
105
103
|
|
106
104
|
std::pair<O_<%= class_name %>, bool> select(const I_<%= class_name %>& id){
|
107
|
-
return first(E_<%= serial.name %>() == id);
|
105
|
+
return first(E_<%= model.serial.name %>() == id);
|
108
106
|
}
|
109
107
|
|
110
108
|
std::pair<O_<%= class_name %>, bool> first(const Condition& c)
|
@@ -1,4 +1,4 @@
|
|
1
|
-
<% class_name =
|
1
|
+
<% class_name = decolonize(model.name) %>
|
2
2
|
<% all_caps_name = class_name.upcase %>
|
3
3
|
#ifndef O_<%= all_caps_name %>
|
4
4
|
#define O_<%= all_caps_name %>
|
@@ -10,8 +10,8 @@
|
|
10
10
|
#include "dmmm_identifiers.hpp"
|
11
11
|
#include "dmmm_fields.hpp"
|
12
12
|
#include "dmmm_comparators.hpp"
|
13
|
-
<%
|
14
|
-
#include "T_<%= relative[1].parent_model.to_s
|
13
|
+
<% many_to_one.each do |relative| %>
|
14
|
+
#include "T_<%= decolonize(relative[1].parent_model.to_s) %>.hpp"
|
15
15
|
<% end %>
|
16
16
|
|
17
17
|
<%# self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::OneToMany::Relationship'}.each do |relative| %>
|
@@ -22,8 +22,8 @@ class O_<%= class_name %>{
|
|
22
22
|
public:
|
23
23
|
|
24
24
|
O_<%= class_name %>() {}
|
25
|
-
<%
|
26
|
-
<% parent = r[1].parent_model_name
|
25
|
+
<% many_to_one.each do |r| %>
|
26
|
+
<% parent = decolonize(r[1].parent_model_name) %>
|
27
27
|
O_<%= class_name %>(const O_<%= parent %>& parent)
|
28
28
|
: _f_<%= r[1].child_key.first.name.to_s %>(parent._<%= r[1].parent_key.first.name.to_s %>())
|
29
29
|
{}
|
@@ -32,53 +32,50 @@ public:
|
|
32
32
|
{}
|
33
33
|
<% end %>
|
34
34
|
|
35
|
-
<% generated_properties.each do |property| %>
|
36
|
-
const <%= property.
|
35
|
+
<% model.generated_properties.each do |property| %>
|
36
|
+
const <%= property.cpp_name %>::Base& _<%= property.name %>() const {
|
37
37
|
return _f_<%= property.name %>._base;
|
38
38
|
}
|
39
|
-
<%= property.
|
39
|
+
<%= property.cpp_name %>::Base& _<%= property.name %>() {
|
40
40
|
_f_<%= property.name %>._dirty = true;
|
41
41
|
return _f_<%= property.name %>._base;
|
42
42
|
}
|
43
|
-
|
44
43
|
<% end %>
|
45
44
|
|
46
|
-
<% if serial %>
|
45
|
+
<% if model.serial %>
|
47
46
|
bool update(){
|
48
47
|
std::map<std::string, std::string> field2Val;
|
49
|
-
<% generated_properties.each do |property| %>
|
48
|
+
<% model.generated_properties.each do |property| %>
|
50
49
|
if (_f_<%= property.name %>._dirty)
|
51
50
|
field2Val["<%= property.name %>"] =
|
52
51
|
UTILS::toString(_f_<%= property.name %>._base);
|
53
52
|
<% end %>
|
54
53
|
std::string where =
|
55
|
-
"<%= serial.name %>=" + UTILS::toString(_f_<%= serial.name %>._base);
|
56
|
-
return DBFace::instance()->update("<%= storage_name %>",
|
54
|
+
"<%= model.serial.name %>=" + UTILS::toString(_f_<%= model.serial.name %>._base);
|
55
|
+
return DBFace::instance()->update("<%= model.storage_name %>",
|
57
56
|
field2Val, where);
|
58
57
|
}
|
59
|
-
|
60
58
|
<% end %>
|
61
59
|
|
62
|
-
|
63
60
|
bool insert(){
|
64
61
|
std::map<std::string, std::string> field2Val;
|
65
|
-
<% generated_properties.each do |property| %>
|
62
|
+
<% model.generated_properties.each do |property| %>
|
66
63
|
if (_f_<%= property.name %>._dirty)
|
67
64
|
field2Val["<%= property.name %>"] =
|
68
65
|
UTILS::toString(_f_<%= property.name %>._base);
|
69
66
|
<% end %>
|
70
|
-
<% if serial %>
|
67
|
+
<% if model.serial %>
|
71
68
|
if (DBFace::instance()->
|
72
|
-
insert("<%= storage_name %>", field2Val,
|
73
|
-
_f_<%= serial.name %>._base.serialization()))
|
69
|
+
insert("<%= model.storage_name %>", field2Val,
|
70
|
+
_f_<%= model.serial.name %>._base.serialization()))
|
74
71
|
<% else %>
|
75
72
|
size_t id;
|
76
73
|
if (DBFace::instance()->
|
77
|
-
insert("<%= storage_name %>", field2Val,
|
74
|
+
insert("<%= model.storage_name %>", field2Val,
|
78
75
|
id))
|
79
76
|
<% end %>
|
80
77
|
{
|
81
|
-
<% generated_properties.each do |property| %>
|
78
|
+
<% model.generated_properties.each do |property| %>
|
82
79
|
_f_<%= property.name %>._dirty = false;
|
83
80
|
<% end %>
|
84
81
|
return true;
|
@@ -88,21 +85,19 @@ public:
|
|
88
85
|
|
89
86
|
}
|
90
87
|
|
91
|
-
<%
|
92
|
-
<% parent = r[1].parent_model_name
|
88
|
+
<% many_to_one.each do |r| %>
|
89
|
+
<% parent = decolonize(r[1].parent_model_name) %>
|
93
90
|
std::pair<O_<%= parent %>, bool> <%= r[0] %>(){
|
94
91
|
T_<%= parent %> T(T_<%= parent %>::E_<%= r[1].parent_key.first.name.to_s %>() == _<%= r[1].child_key.first.name.to_s %>());
|
95
92
|
return T.first();
|
96
93
|
}
|
97
94
|
<% end %>
|
98
95
|
|
99
|
-
|
100
96
|
private:
|
101
|
-
<% generated_properties.each do |property| %>
|
102
|
-
<%= property.
|
97
|
+
<% model.generated_properties.each do |property| %>
|
98
|
+
<%= property.cpp_name %> _f_<%= property.name %>;
|
103
99
|
<% end %>
|
104
100
|
|
105
|
-
|
106
101
|
friend class T_<%= class_name %>;
|
107
102
|
};
|
108
103
|
|
@@ -0,0 +1,62 @@
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
class MyGenerator < DMMM::Generator;end
|
4
|
+
|
5
|
+
class LolModel
|
6
|
+
include DataMapper::Resource
|
7
|
+
|
8
|
+
property :id, Serial
|
9
|
+
property :name, String
|
10
|
+
end
|
11
|
+
|
12
|
+
describe "Generator" do
|
13
|
+
describe "General" do
|
14
|
+
it "is configurable" do
|
15
|
+
MyGenerator.config.should == DMMM.instance_variable_get(:@_default_opts)
|
16
|
+
end
|
17
|
+
|
18
|
+
it "stores a block to extend models" do
|
19
|
+
blk = proc { @__foo__ = "lol" }
|
20
|
+
MyGenerator.send(:setup_model, &blk)
|
21
|
+
MyGenerator.setup_model_blk.should == blk
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
describe "Templates" do
|
26
|
+
it "has a template store" do
|
27
|
+
DMMM::TemplateCollection.should === MyGenerator.generated_files
|
28
|
+
end
|
29
|
+
|
30
|
+
it "stores template info" do
|
31
|
+
MyGenerator.send(:generates_file, :model, "foo")
|
32
|
+
MyGenerator.generated_files.size.should == 1
|
33
|
+
MyGenerator.generated_files.first.name.should == "foo"
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
describe ".new" do
|
38
|
+
before :each do
|
39
|
+
MyGenerator.instance_variable_set :@generated_files, DMMM::TemplateCollection.new
|
40
|
+
model_files = ["foo", "bar", "baz", "bleh"]
|
41
|
+
|
42
|
+
model_files.each do |f|
|
43
|
+
MyGenerator.send :generates_file, :model, f
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
it "requires model info" do
|
48
|
+
lambda {MyGenerator.new}.should raise_error(ArgumentError)
|
49
|
+
end
|
50
|
+
|
51
|
+
it "has model templates when called with model" do
|
52
|
+
@generator = MyGenerator.new(LolModel)
|
53
|
+
@generator.instance_variable_get(:@templates).should == MyGenerator.generated_files.models
|
54
|
+
end
|
55
|
+
|
56
|
+
it "has global templates when called without model" do
|
57
|
+
@generator = MyGenerator.new nil
|
58
|
+
@generator.instance_variable_get(:@templates).should == MyGenerator.generated_files.global
|
59
|
+
end
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
@@ -0,0 +1,29 @@
|
|
1
|
+
require File.expand_path("../../spec_helper", __FILE__)
|
2
|
+
|
3
|
+
class LolGenerator < DMMM::Generator; end
|
4
|
+
|
5
|
+
describe "Template" do
|
6
|
+
describe "invalid" do
|
7
|
+
it "requires a name" do
|
8
|
+
lambda {DMMM::Template.new}.should raise_error(ArgumentError)
|
9
|
+
end
|
10
|
+
|
11
|
+
it "requires a generator" do
|
12
|
+
lambda {DMMM::Template.new(:foo)}.should raise_error(DMMM::NoGeneratorError)
|
13
|
+
end
|
14
|
+
|
15
|
+
it "requires a valid type" do
|
16
|
+
lambda {DMMM::Template.new(:few, generator: LolGenerator)}.
|
17
|
+
should raise_error(DMMM::InvalidTypeError)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
describe "valid" do
|
22
|
+
before :all do
|
23
|
+
@template = DMMM::Template.new :foo,
|
24
|
+
generator: LolGenerator,
|
25
|
+
type: :global
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
data/spec/spec.opts
ADDED
data/spec/spec_helper.rb
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
$:.push
|
1
|
+
$:.push File.expand_path('../lib', __FILE__)
|
2
2
|
|
3
3
|
require 'rubygems'
|
4
4
|
require 'bundler'
|
@@ -6,3 +6,5 @@ Bundler.setup(:default, :test)
|
|
6
6
|
require 'spec'
|
7
7
|
|
8
8
|
require 'dm-metamapper'
|
9
|
+
|
10
|
+
DMMM = DataMapper::MetaMapper
|
metadata
CHANGED
@@ -5,8 +5,8 @@ version: !ruby/object:Gem::Version
|
|
5
5
|
segments:
|
6
6
|
- 0
|
7
7
|
- 0
|
8
|
-
-
|
9
|
-
version: 0.0.
|
8
|
+
- 4
|
9
|
+
version: 0.0.4
|
10
10
|
platform: ruby
|
11
11
|
authors:
|
12
12
|
- Jonah Honeyman
|
@@ -15,7 +15,7 @@ autorequire:
|
|
15
15
|
bindir: bin
|
16
16
|
cert_chain: []
|
17
17
|
|
18
|
-
date: 2010-06-
|
18
|
+
date: 2010-06-15 00:00:00 +03:00
|
19
19
|
default_executable:
|
20
20
|
dependencies: []
|
21
21
|
|
@@ -28,21 +28,24 @@ extensions: []
|
|
28
28
|
extra_rdoc_files:
|
29
29
|
- README.md
|
30
30
|
files:
|
31
|
+
- .autospec
|
31
32
|
- .gitignore
|
32
33
|
- Gemfile
|
33
34
|
- README.md
|
34
35
|
- Rakefile
|
35
36
|
- VERSION
|
36
|
-
- dm-metamapper.gemspec
|
37
37
|
- example/.gitignore
|
38
38
|
- example/Makefile
|
39
39
|
- example/example.cpp
|
40
40
|
- example/example.rb
|
41
41
|
- lib/dm-metamapper.rb
|
42
|
+
- lib/dm-metamapper/config.rb
|
42
43
|
- lib/dm-metamapper/extension.rb
|
43
44
|
- lib/dm-metamapper/generator.rb
|
45
|
+
- lib/dm-metamapper/generators/cpp.rb
|
44
46
|
- lib/dm-metamapper/metamapper.rb
|
45
47
|
- lib/dm-metamapper/property.rb
|
48
|
+
- lib/dm-metamapper/template.rb
|
46
49
|
- lib/templates/cpp/class.hpp.erb
|
47
50
|
- lib/templates/cpp/dmmm_comparators.hpp.erb
|
48
51
|
- lib/templates/cpp/dmmm_dbface.cpp.erb
|
@@ -53,7 +56,9 @@ files:
|
|
53
56
|
- lib/templates/cpp/dmmm_utils.cpp.erb
|
54
57
|
- lib/templates/cpp/dmmm_utils.hpp.erb
|
55
58
|
- lib/templates/cpp/instance.hpp.erb
|
56
|
-
-
|
59
|
+
- spec/dm-metamapper/generator_spec.rb
|
60
|
+
- spec/dm-metamapper/template_spec.rb
|
61
|
+
- spec/spec.opts
|
57
62
|
- spec/spec_helper.rb
|
58
63
|
has_rdoc: true
|
59
64
|
homepage: http://github.com/jonuts/dm-metamapper
|
@@ -87,3 +92,5 @@ specification_version: 3
|
|
87
92
|
summary: Code generating C++ ORM
|
88
93
|
test_files:
|
89
94
|
- spec/spec_helper.rb
|
95
|
+
- spec/dm-metamapper/generator_spec.rb
|
96
|
+
- spec/dm-metamapper/template_spec.rb
|
data/dm-metamapper.gemspec
DELETED
@@ -1,66 +0,0 @@
|
|
1
|
-
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
|
-
# -*- encoding: utf-8 -*-
|
5
|
-
|
6
|
-
Gem::Specification.new do |s|
|
7
|
-
s.name = %q{dm-metamapper}
|
8
|
-
s.version = "0.0.3"
|
9
|
-
|
10
|
-
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
|
-
s.authors = ["Jonah Honeyman", "Omer Tamuz"]
|
12
|
-
s.date = %q{2010-06-09}
|
13
|
-
s.description = %q{C++ API for databases created with DM. Hard typing, compile time checked queries.}
|
14
|
-
s.email = %q{jonah@honeyman.org}
|
15
|
-
s.extra_rdoc_files = [
|
16
|
-
"README.md"
|
17
|
-
]
|
18
|
-
s.files = [
|
19
|
-
".gitignore",
|
20
|
-
"Gemfile",
|
21
|
-
"README.md",
|
22
|
-
"Rakefile",
|
23
|
-
"VERSION",
|
24
|
-
"dm-metamapper.gemspec",
|
25
|
-
"example/.gitignore",
|
26
|
-
"example/Makefile",
|
27
|
-
"example/example.cpp",
|
28
|
-
"example/example.rb",
|
29
|
-
"lib/dm-metamapper.rb",
|
30
|
-
"lib/dm-metamapper/extension.rb",
|
31
|
-
"lib/dm-metamapper/generator.rb",
|
32
|
-
"lib/dm-metamapper/metamapper.rb",
|
33
|
-
"lib/dm-metamapper/property.rb",
|
34
|
-
"lib/templates/cpp/class.hpp.erb",
|
35
|
-
"lib/templates/cpp/dmmm_comparators.hpp.erb",
|
36
|
-
"lib/templates/cpp/dmmm_dbface.cpp.erb",
|
37
|
-
"lib/templates/cpp/dmmm_dbface.h.erb",
|
38
|
-
"lib/templates/cpp/dmmm_fields.hpp.erb",
|
39
|
-
"lib/templates/cpp/dmmm_id.hpp.erb",
|
40
|
-
"lib/templates/cpp/dmmm_identifiers.hpp.erb",
|
41
|
-
"lib/templates/cpp/dmmm_utils.cpp.erb",
|
42
|
-
"lib/templates/cpp/dmmm_utils.hpp.erb",
|
43
|
-
"lib/templates/cpp/instance.hpp.erb",
|
44
|
-
"output/.gitignore",
|
45
|
-
"spec/spec_helper.rb"
|
46
|
-
]
|
47
|
-
s.homepage = %q{http://github.com/jonuts/dm-metamapper}
|
48
|
-
s.rdoc_options = ["--charset=UTF-8"]
|
49
|
-
s.require_paths = ["lib"]
|
50
|
-
s.rubygems_version = %q{1.3.6}
|
51
|
-
s.summary = %q{Code generating C++ ORM}
|
52
|
-
s.test_files = [
|
53
|
-
"spec/spec_helper.rb"
|
54
|
-
]
|
55
|
-
|
56
|
-
if s.respond_to? :specification_version then
|
57
|
-
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
58
|
-
s.specification_version = 3
|
59
|
-
|
60
|
-
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
61
|
-
else
|
62
|
-
end
|
63
|
-
else
|
64
|
-
end
|
65
|
-
end
|
66
|
-
|
data/output/.gitignore
DELETED
@@ -1 +0,0 @@
|
|
1
|
-
*
|