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 ADDED
@@ -0,0 +1,6 @@
1
+ Autotest.add_hook :reset do |at|
2
+ at.clear_mappings
3
+ at.add_exception(/\.git/)
4
+ at.add_mapping(%r{^spec/.*_spec}) {|name,_| at.files_matching(/#{name}/)}
5
+ at.add_mapping(//) {|_,_| at.files_matching %r{spec/.*_spec}}
6
+ end
data/.gitignore CHANGED
@@ -3,3 +3,5 @@
3
3
  .bundle/*
4
4
  .rvmrc
5
5
  *.gem
6
+ *.gemspec
7
+ output
data/Gemfile CHANGED
@@ -10,6 +10,7 @@ group :test do
10
10
  gem "data_objects"
11
11
  gem "do_sqlite3", do_gems_version
12
12
  gem "do_mysql", do_gems_version
13
+ gem "ZenTest"
13
14
  end
14
15
 
15
16
  group :deploy do
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.0.3
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 generates(*layouts)
5
- @_generation_formats = Array(layouts)
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
- @_generation_formats.include?(format)
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(:@_generation_formats, [])
29
- class <<base; attr_reader :_generation_formats end
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 GeneratedFile
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
- :generated_model_files,
29
- :generated_global_files,
30
- :proxy_blk
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
- private
42
-
43
- def generates_file(&blk)
44
- @generated_model_files ||= []
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
- def generates_global_file(&blk)
49
- @generated_global_files ||= []
50
- @generated_global_files << GeneratedFile.new(&blk)
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 proxy(&blk)
54
- @proxy_blk = blk
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, @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
- class DataMapper::MetaMapper::Proxy; end
68
-
69
- class CPPGenerator < DataMapper::MetaMapper::Generator
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
- properties.each do |e|
90
- cpp_name = if e.serial?
91
- "Field<I_#{e.model.name.sub(/::/,'_')}>"
92
- elsif !key_to_parent[e.name.to_s].nil?
93
- "Field<I_#{key_to_parent[e.name.to_s]}>"
94
- else
95
- "F_#{e.primitive}"
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
- e.instance_variable_set(:@cpp_name, cpp_name)
99
- end
100
- end
63
+ attr_reader :model
101
64
 
102
- generates_file do
103
- suffix ".hpp"
104
- prefix "O_"
105
- template_name "instance.hpp.erb"
106
- end
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, context=nil)
20
+ def generate(format, opts = {})
21
+ context = opts.delete(:context)
12
22
  generator = Generator[format]
23
+ generator.run(context, opts)
13
24
 
14
- if context
15
- context.instance_eval(&generator.proxy_blk) if generator.proxy_blk
16
- type, _binding = :generated_model_files, context._get_binding
17
- else
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 = self.name.sub(/::/,'_') %>
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
- <% self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |r| %>
26
- <% parent = r[1].parent_model_name.sub(/::/,'_') %>
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.instance_variable_get(:@cpp_name) %>::Base ComparerType;
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.instance_variable_get(:@cpp_name) %>::Base>(res[i]["<%= property.name %>"]);
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)
@@ -6,7 +6,7 @@
6
6
  namespace DMMM {
7
7
 
8
8
  <% models.each do |model| %>
9
- <% model_name = model.name.sub(/::/,'_') %>
9
+ <% model_name = decolonize(model.name) %>
10
10
  class DummyO_<%= model_name %>;
11
11
  typedef UTILS::Id<DummyO_<%= model_name %>> I_<%= model_name %>;
12
12
  <% end %>
@@ -1,4 +1,4 @@
1
- <% class_name = self.name.sub(/::/,'_') %>
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
- <% self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |relative| %>
14
- #include "T_<%= relative[1].parent_model.to_s.sub(/::/,'_') %>.hpp"
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
- <% self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |r| %>
26
- <% parent = r[1].parent_model_name.sub(/::/,'_') %>
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.instance_variable_get(:@cpp_name) %>::Base& _<%= property.name %>() const {
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.instance_variable_get(:@cpp_name) %>::Base& _<%= property.name %>() {
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
- <% self.relationships.select{|r,m| m.class.name == 'DataMapper::Associations::ManyToOne::Relationship'}.each do |r| %>
92
- <% parent = r[1].parent_model_name.sub(/::/,'_') %>
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.instance_variable_get(:@cpp_name) %> _f_<%= property.name %>;
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
@@ -0,0 +1,4 @@
1
+ --colour
2
+ --loadby random
3
+ --format profile
4
+ --backtrace
data/spec/spec_helper.rb CHANGED
@@ -1,4 +1,4 @@
1
- $:.push(File.join(File.dirname(__FILE__), "../lib"))
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
- - 3
9
- version: 0.0.3
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-09 00:00:00 +03:00
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
- - output/.gitignore
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
@@ -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
- *