dm-metamapper 0.0.3 → 0.0.4
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/.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
|
-
*
|