makumba_import 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
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: []