makumba_import 0.0.1

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,38 @@
1
+ Makumba Import
2
+ ===
3
+
4
+ This gem provides functionality to use a database described by Makumba MDDs within your Rails application.
5
+
6
+ More specifically it generates a database schema and models matching what's described with the MDDs.
7
+
8
+ It supports all sorts of pointers, links, etc.
9
+
10
+ Usage
11
+ ---
12
+
13
+ 1. Configure your database.yml file to use the same database.
14
+
15
+ 2. Add this to your Gemfile:
16
+
17
+ ```
18
+ gem "makumba_import"
19
+ ```
20
+
21
+ 3. Add this to your Rakefile:
22
+
23
+ ```
24
+ Dir["#{Gem.searcher.find('makumba_import').full_gem_path}/lib/tasks/*.rake"].each { |ext| load ext }
25
+ ```
26
+
27
+ 4. Generate a initializer called makumba_import.rb with the following contents:
28
+
29
+ ```
30
+ MakumbaImport::Importer.setMddPath "/..your.path../WEB-INF/classes/dataDefinitions"
31
+ MakumbaImport::Importer.setOutputPath "./" # where to generate the .rb files. Leave blank to import straight into the app folders
32
+ ```
33
+
34
+ 5. Run
35
+ ```
36
+ rake makumba_import:schema
37
+ rake makumba_import:models
38
+ ```
@@ -0,0 +1,248 @@
1
+ module MakumbaImport
2
+ class Importer
3
+
4
+ @mddPath = ""
5
+ @outputPath = ""
6
+
7
+ def self.setMddPath(mddPath)
8
+ @mddPath = mddPath
9
+ end
10
+
11
+ def self.setOutputPath(outputPath)
12
+ @outputPath = outputPath
13
+ end
14
+
15
+ def self.get_data(lines, mdd)
16
+ fieldRegexp = /^([a-zA-Z\_]+)\s*=\s*([^;]+);?(.*)/
17
+ fieldTypes = ["int", "text", "real", "date", "boolean", "binary", "file"]
18
+
19
+ schema = {}
20
+ schema[mdd] = {}
21
+ primary = mdd.split(".").last
22
+ schema[mdd][primary] = {'type' => 'primary'}
23
+
24
+ lines.each do |line|
25
+ unless line.match("^#") or line.strip == "" or line.match("->")
26
+ if m = fieldRegexp.match(line)
27
+ obj = {}
28
+ field = m[1].strip
29
+ attrs = m[2].strip
30
+ comment = m[3] ? m[3].strip.gsub(/^;/,"").strip : ""
31
+
32
+ attrs.split(" ").each do |attr|
33
+ if fieldTypes.include?(attr)
34
+ obj['type'] = attr
35
+ end
36
+ if attr.match(/fixed/)
37
+ obj['not_null'] = true
38
+ end
39
+ end
40
+ if m2 = attrs.match(/char\[(\d+)\]/)
41
+ obj['type'] = "char"
42
+ obj['length'] = m2[1]
43
+ end
44
+ if attrs.match(/set$/)
45
+ newmdd = mdd+".."+field
46
+ lines2 = []
47
+ lines.each do |l|
48
+ if l.start_with?(field+"->")
49
+ lines2.push l.gsub(field+"->", "")
50
+ end
51
+ end
52
+ data2 = get_data(lines2, newmdd)
53
+ schema.merge!(data2)
54
+ schema[newmdd][primary] = {'type' => "ptr", 'ptr' => mdd}
55
+ end
56
+ if m3 = attrs.match(/int\s?\{([^\}]+)\}/)
57
+ obj['type'] = "enum"
58
+ obj['fields'] = {}
59
+ # assuming there's no comma in the enum strings, (this is true for cherry)
60
+ m3[1].split(",").each do |part|
61
+ m4 = part.strip.match(/"([^"]+)"\s*=\s*(-?[0-9]+)/)
62
+ obj['fields'][m4[2]] = m4[1]
63
+ end
64
+ end
65
+ if m3 = attrs.match(/ptr\s+([a-zA-Z\.\_]+)/)
66
+ obj['type'] = "ptr"
67
+ obj['ptr'] = m3[1]
68
+ end
69
+ if m3 = attrs.match(/set\s+([a-zA-Z\.\_]+)/)
70
+ newmdd = mdd+".."+field
71
+ fieldname = m3[1].split('.').last
72
+ schema[newmdd] = {}
73
+ schema[newmdd][field] = {'type' => 'primary'}
74
+ schema[newmdd][primary] = {'type' => "ptr", 'ptr' => mdd}
75
+ schema[newmdd][fieldname] = {'type' => "ptr", 'ptr' => m3[1]}
76
+ end
77
+ if m3 = attrs.match(/set int\s?\{([^\}]+)\}/)
78
+ fields = {}
79
+ # assuming there's no comma in the enum strings, (this is true for cherry)
80
+ m3[1].split(",").each do |part|
81
+ m4 = part.strip.match(/"([^"]+)"\s*=\s*(-?[0-9]+)/)
82
+ fields[m4[2]] = m4[1]
83
+ end
84
+
85
+ newmdd = mdd+".."+field
86
+ schema[newmdd] = {}
87
+ schema[newmdd][field] = {'type' => 'primary'}
88
+ schema[newmdd][primary] = {'type' => "ptr", 'ptr' => mdd}
89
+ schema[newmdd]['enum'] = {'type' => "set enum", 'fields' => fields}
90
+ end
91
+ if attrs.match(/not null/)
92
+ obj['not_null'] = true
93
+ end
94
+ if attrs.match(/unique/)
95
+ obj['unique'] = true
96
+ end
97
+
98
+ unless obj['type'].blank?
99
+ schema[mdd][field] = obj
100
+ end
101
+ end
102
+
103
+ end
104
+ end
105
+ #puts schema
106
+ schema
107
+
108
+ end
109
+
110
+ def self.load_mdds
111
+ dir = @mddPath
112
+
113
+ @files = Dir.glob(dir+"/*/*.mdd")
114
+ @files |= Dir.glob(dir+"/*/*/*.mdd")
115
+ @files |= Dir.glob(dir+"/*/*/*/*.mdd")
116
+
117
+ schema = {}
118
+
119
+ for file in @files
120
+ unless File.directory?(file)
121
+ filename = file.gsub(dir+"/", "").gsub(".mdd","")
122
+ mdd = filename.gsub("/", ".")
123
+
124
+ lines = open(file).map { |line| line }
125
+ schema.merge!(get_data(lines, mdd))
126
+ end
127
+ end
128
+
129
+ schema
130
+ end
131
+
132
+ def self.generate_ruby_schema(schema)
133
+
134
+ txt = "# encoding: UTF-8\n\n";
135
+
136
+ txt << "ActiveRecord::Schema.define(:version => "+Time.now.strftime("%Y%m%d%H%M%S")+") do\n\n"
137
+
138
+ schema.each do |key, table|
139
+ tablename = key.gsub(".", "_")
140
+ lastpart = key.split(".").last
141
+
142
+ txt << " create_table \""+tablename+"_\", :force => true do |t|\n"
143
+
144
+ table.each do |name, field|
145
+ #type = "integer "
146
+ type = field['type']
147
+ type = "integer " if ["int", "primary", "ptr", "enum", "set enum"].include? field['type']
148
+ type = "string " if ["char"].include? field['type']
149
+ type = "boolean " if ["boolean"].include? field['type']
150
+ type = "datetime" if ["date"].include? field['type']
151
+ type = "text " if ["text"].include? field['type']
152
+ type = "float " if ["real"].include? field['type']
153
+
154
+ enum = "";
155
+
156
+ if field['type'] == "enum"
157
+ enum = "\t\t # "
158
+ field['fields'].each {|id,f| enum << id+" = \""+f+"\", "}
159
+ enum = enum[0...-2]
160
+ end
161
+
162
+ txt << " t."+type+" \""+name+"_\""+(field['not_null'].blank? ? "" : ", :null => false")+enum+"\n"
163
+
164
+ if field['type'] == 'primary'
165
+ txt << " t.datetime \"TS_modify_\", :null => false\n"
166
+ txt << " t.datetime \"TS_create_\", :null => false\n"
167
+ end
168
+
169
+ end
170
+
171
+ txt << " end\n\n"
172
+
173
+ txt << " add_index \""+tablename+"_\", [\""+lastpart+"_\"], :name => \""+lastpart+"_\", :unique => true\n"
174
+ table.each do |name, field|
175
+ unless field['unique'].blank?
176
+ txt << " add_index \""+tablename+"_\", [\""+name+"_\"], :name => \""+name+"_\", :unique => true\n"
177
+ end
178
+ end
179
+
180
+ txt << " \n\n"
181
+
182
+ end
183
+
184
+ txt << "end\n\n"
185
+
186
+ File.open(@outputPath+"db/schema.rb", "w+") do |f|
187
+ f.write(txt)
188
+ end
189
+ end
190
+
191
+ def self.generate_models(schema)
192
+ txt = '';
193
+ newOnes = {}
194
+
195
+ schema.clone.each do |key, table|
196
+ table.each do |name, field|
197
+ if ["ptr"].include? field['type']
198
+ newOnes[field['ptr']] = {} if newOnes[field['ptr']].blank?
199
+ newOnes[field['ptr']][key+"_"+name] = {"type" => "has_many", "primary_key" => name, "link_from" => key}
200
+ end
201
+ end
202
+ end
203
+
204
+ newOnes.each do |k, v|
205
+ schema[k]['ref'] = v
206
+ end
207
+
208
+ schema.each do |key, table|
209
+ tablename = key.gsub(".", "_")
210
+ lastpart = key.split(".").last
211
+ filename = tablename.classify.tableize.singularize + '.rb';
212
+
213
+ txt = ''
214
+ txt << "# " + tablename.classify.tableize.singularize + ".rb\n\n"
215
+
216
+ txt << "class "+tablename.classify+" < ActiveRecord::Base\n"
217
+ txt << " set_table_name \""+tablename+"_\"\n"
218
+ txt << " set_primary_key \""+lastpart+"_\"\n"
219
+ txt << " fix_makumba_columns\n\n"
220
+
221
+ table.each do |name, field|
222
+ if name == 'ref'
223
+ field.each do |i, f|
224
+ txt << " has_many :"+f['link_from'].split('.').last.downcase.pluralize+", :foreign_key => '"+f['primary_key']+"_', :class_name => \""+f['link_from'].gsub(".","_").classify+"\"\n"
225
+ end
226
+ else
227
+ #puts key
228
+ if ["ptr"].include? field['type']
229
+ txt << " belongs_to :"+name.downcase+", :foreign_key => '"+name+"_', :class_name => '"+field['ptr'].gsub(".", "_").classify+"'\n"
230
+ #puts " belongs_to :"+name.downcase+", :foreign_key => '"+name+"_', :class_name => '"+field['ptr'].gsub(".", "_").classify+"'\n"
231
+ end
232
+ end
233
+
234
+ end
235
+
236
+ txt << "end\n\n"
237
+
238
+ File.open(@outputPath+"app/models/"+filename, "w+") do |f|
239
+ f.write(txt)
240
+ end
241
+
242
+ end
243
+
244
+ txt
245
+ end
246
+
247
+ end
248
+ end
@@ -0,0 +1,21 @@
1
+ module LegacyMakumba
2
+ def self.append_features(base)
3
+ super
4
+ base.extend(ClassMethods)
5
+ end
6
+ module ClassMethods
7
+ def fix_makumba_columns
8
+ column_names.each do |old_name|
9
+ if old_name.match(/_$/)
10
+ new_name = old_name[0...-1]
11
+ self.send(:define_method, new_name) { self.send(old_name) }
12
+ self.send(:define_method, "#{new_name}=") { |value| self.send("#{old_name}=", value) }
13
+ end
14
+ end
15
+ end
16
+ end
17
+ end
18
+
19
+ ActiveRecord::Base.class_eval do
20
+ include LegacyMakumba
21
+ end
@@ -0,0 +1,7 @@
1
+ Dir["tasks/**/*.rake"].each { |ext| load ext } if defined?(Rake)
2
+
3
+ require 'open-uri'
4
+ require 'fileutils'
5
+
6
+ require 'makumba_import/importer'
7
+ require 'makumba_import/legacy'
@@ -0,0 +1,16 @@
1
+ require 'makumba_import'
2
+
3
+ namespace :makumba_import do
4
+ desc 'Generate a new schema.rb file'
5
+ task :schema => :environment do |t, args|
6
+ schema = MakumbaImport::Importer::load_mdds
7
+ MakumbaImport::Importer::generate_ruby_schema(schema)
8
+ end
9
+
10
+ desc 'Regenerate models'
11
+ task :models => :environment do |t, args|
12
+ schema = MakumbaImport::Importer::load_mdds
13
+ MakumbaImport::Importer::generate_models(schema)
14
+ end
15
+
16
+ end
metadata ADDED
@@ -0,0 +1,71 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: makumba_import
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.1
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Marius Andra
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2012-05-29 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: rubyzip
16
+ requirement: &17594580 !ruby/object:Gem::Requirement
17
+ none: false
18
+ requirements:
19
+ - - ! '>='
20
+ - !ruby/object:Gem::Version
21
+ version: '0'
22
+ type: :runtime
23
+ prerelease: false
24
+ version_requirements: *17594580
25
+ - !ruby/object:Gem::Dependency
26
+ name: rubyzip
27
+ requirement: &17593240 !ruby/object:Gem::Requirement
28
+ none: false
29
+ requirements:
30
+ - - ! '>='
31
+ - !ruby/object:Gem::Version
32
+ version: '0'
33
+ type: :development
34
+ prerelease: false
35
+ version_requirements: *17593240
36
+ description: Generate models matching your Makumba MDDs
37
+ email: marius.andra@gmail.com
38
+ executables: []
39
+ extensions: []
40
+ extra_rdoc_files: []
41
+ files:
42
+ - lib/makumba_import/importer.rb
43
+ - lib/makumba_import/legacy.rb
44
+ - lib/makumba_import.rb
45
+ - lib/tasks/makumba_import.rake
46
+ - README.md
47
+ homepage: http://rubygems.org/gems/makumba_import
48
+ licenses: []
49
+ post_install_message:
50
+ rdoc_options: []
51
+ require_paths:
52
+ - lib
53
+ required_ruby_version: !ruby/object:Gem::Requirement
54
+ none: false
55
+ requirements:
56
+ - - ! '>='
57
+ - !ruby/object:Gem::Version
58
+ version: '0'
59
+ required_rubygems_version: !ruby/object:Gem::Requirement
60
+ none: false
61
+ requirements:
62
+ - - ! '>='
63
+ - !ruby/object:Gem::Version
64
+ version: '0'
65
+ requirements: []
66
+ rubyforge_project:
67
+ rubygems_version: 1.8.11
68
+ signing_key:
69
+ specification_version: 3
70
+ summary: Makumba database integration with Rails applications
71
+ test_files: []