active_extend 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/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +26 -0
- data/lib/active_extend/active_disablable.rb +61 -0
- data/lib/active_extend/string_helper.rb +9 -0
- data/lib/active_extend/version.rb +3 -0
- data/lib/active_extend.rb +5 -0
- data/lib/external_migration/converters/rtf_to_html.rb +123 -0
- data/lib/external_migration/dictionary.rb +19 -0
- data/lib/external_migration/migration.rb +211 -0
- data/lib/external_migration/schemas.rb +143 -0
- data/lib/external_migration/spelling_fix.rb +20 -0
- data/lib/external_migration/transformer/grouped_field_fixed_spelling.rb +110 -0
- data/lib/external_migration.rb +10 -0
- data/lib/tasks/active_extends_tasks.rake +4 -0
- metadata +92 -0
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2012 YOURNAME
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.rdoc
ADDED
data/Rakefile
ADDED
@@ -0,0 +1,26 @@
|
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
begin
|
3
|
+
require 'bundler/setup'
|
4
|
+
rescue LoadError
|
5
|
+
puts 'You must `gem install bundler` and `bundle install` to run rake tasks'
|
6
|
+
end
|
7
|
+
begin
|
8
|
+
require 'rdoc/task'
|
9
|
+
rescue LoadError
|
10
|
+
require 'rdoc/rdoc'
|
11
|
+
require 'rake/rdoctask'
|
12
|
+
RDoc::Task = Rake::RDocTask
|
13
|
+
end
|
14
|
+
|
15
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
16
|
+
rdoc.rdoc_dir = 'rdoc'
|
17
|
+
rdoc.title = 'ActiveExtend'
|
18
|
+
rdoc.options << '--line-numbers'
|
19
|
+
rdoc.rdoc_files.include('README.rdoc')
|
20
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
|
26
|
+
Bundler::GemHelper.install_tasks
|
@@ -0,0 +1,61 @@
|
|
1
|
+
|
2
|
+
#require 'devise/orm/active_record'
|
3
|
+
|
4
|
+
module ActiveExtend
|
5
|
+
module ActiveDisablable
|
6
|
+
|
7
|
+
def self.included(base)
|
8
|
+
base.extend(ClassMethods)
|
9
|
+
base.send(:default_scope) { base.where(:enabled => true) }
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def all_include_disabled
|
14
|
+
unscoped
|
15
|
+
end
|
16
|
+
|
17
|
+
def all_disabled
|
18
|
+
where(:enabled => false)
|
19
|
+
end
|
20
|
+
|
21
|
+
end
|
22
|
+
|
23
|
+
|
24
|
+
|
25
|
+
def disable
|
26
|
+
self.enabled = false
|
27
|
+
end
|
28
|
+
|
29
|
+
def enable
|
30
|
+
self.enabled = true
|
31
|
+
end
|
32
|
+
|
33
|
+
def enabled?
|
34
|
+
self.enabled
|
35
|
+
end
|
36
|
+
|
37
|
+
def disabled?
|
38
|
+
!self.enabled
|
39
|
+
end
|
40
|
+
|
41
|
+
def destroy
|
42
|
+
if (@destroy_fully || self.disabled?)
|
43
|
+
super
|
44
|
+
else
|
45
|
+
disable
|
46
|
+
self.save
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
def recovery
|
51
|
+
enable
|
52
|
+
self.save
|
53
|
+
end
|
54
|
+
|
55
|
+
def destroy_fully
|
56
|
+
@destroy_fully = true
|
57
|
+
self.destroy
|
58
|
+
end
|
59
|
+
|
60
|
+
end
|
61
|
+
end
|
@@ -0,0 +1,123 @@
|
|
1
|
+
|
2
|
+
require 'ruby-rtf'
|
3
|
+
require 'pp'
|
4
|
+
|
5
|
+
module ExternalMigration
|
6
|
+
module Converters
|
7
|
+
class RtfToHtml
|
8
|
+
|
9
|
+
def initialize()
|
10
|
+
@prefix = ''
|
11
|
+
@suffix = ''
|
12
|
+
end
|
13
|
+
|
14
|
+
def add(open, close = open)
|
15
|
+
@prefix << "<#{open}>"
|
16
|
+
@suffix = "</#{close}>#{@suffix}"
|
17
|
+
end
|
18
|
+
|
19
|
+
def format(str, section)
|
20
|
+
@prefix = ''
|
21
|
+
@suffix = ''
|
22
|
+
|
23
|
+
mods = section[:modifiers]
|
24
|
+
|
25
|
+
if mods[:paragraph]
|
26
|
+
if section[:text].empty?
|
27
|
+
str << "<p></p>\n"
|
28
|
+
else
|
29
|
+
add('p')
|
30
|
+
end
|
31
|
+
|
32
|
+
elsif mods[:tab]
|
33
|
+
str << " "
|
34
|
+
return
|
35
|
+
elsif mods[:newline]
|
36
|
+
str << "<br />\n"
|
37
|
+
return
|
38
|
+
elsif mods[:rquote]
|
39
|
+
str << "’"
|
40
|
+
return
|
41
|
+
elsif mods[:lquote]
|
42
|
+
str << "‘"
|
43
|
+
return
|
44
|
+
elsif mods[:ldblquote]
|
45
|
+
str << "“"
|
46
|
+
return
|
47
|
+
elsif mods[:rdblquote]
|
48
|
+
str << "”"
|
49
|
+
return
|
50
|
+
elsif mods[:emdash]
|
51
|
+
str << "—"
|
52
|
+
return
|
53
|
+
elsif mods[:endash]
|
54
|
+
str << "–"
|
55
|
+
return
|
56
|
+
elsif mods[:nbsp]
|
57
|
+
str << " "
|
58
|
+
return
|
59
|
+
end
|
60
|
+
return if section[:text].empty?
|
61
|
+
|
62
|
+
add('b') if mods[:bold]
|
63
|
+
add('i') if mods[:italic]
|
64
|
+
add('u') if mods[:underline]
|
65
|
+
add('sup') if mods[:superscript]
|
66
|
+
add('sub') if mods[:subscript]
|
67
|
+
add('del') if mods[:strikethrough]
|
68
|
+
|
69
|
+
style = ''
|
70
|
+
style << "font-variant: small-caps;" if mods[:smallcaps]
|
71
|
+
style << "font-size: #{mods[:font_size]}pt;" if mods[:font_size]
|
72
|
+
style << "font-family: \"#{mods[:font].name}\";" if mods[:font]
|
73
|
+
if mods[:foreground_colour] && !mods[:foreground_colour].use_default?
|
74
|
+
colour = mods[:foreground_colour]
|
75
|
+
style << "color: rgb(#{colour.red},#{colour.green},#{colour.blue});"
|
76
|
+
end
|
77
|
+
if mods[:background_colour] && !mods[:background_colour].use_default?
|
78
|
+
colour = mods[:background_colour]
|
79
|
+
style << "background-color: rgb(#{colour.red},#{colour.green},#{colour.blue});"
|
80
|
+
end
|
81
|
+
|
82
|
+
add("span style='#{style}'", 'span') unless style.empty?
|
83
|
+
|
84
|
+
str << @prefix + section[:text].force_encoding('UTF-8') + @suffix
|
85
|
+
end
|
86
|
+
|
87
|
+
def parse_from_file(file)
|
88
|
+
parse(File.open(ARGV[0]).read)
|
89
|
+
end
|
90
|
+
|
91
|
+
def parse(contents)
|
92
|
+
doc = RubyRTF::Parser.new.parse(contents)
|
93
|
+
|
94
|
+
str = ''
|
95
|
+
|
96
|
+
doc.sections.each do |section|
|
97
|
+
mods = section[:modifiers]
|
98
|
+
|
99
|
+
if mods[:table]
|
100
|
+
str << "<table width=\"100%\">\n"
|
101
|
+
mods[:table].rows.each do |row|
|
102
|
+
str << "<tr>\n"
|
103
|
+
row.cells.each do |cell|
|
104
|
+
str << "<td width=\"#{cell.width}%\">\n"
|
105
|
+
cell.sections.each do |sect|
|
106
|
+
format(str, sect)
|
107
|
+
end
|
108
|
+
str << "</td>\n"
|
109
|
+
end
|
110
|
+
str << "</tr>\n"
|
111
|
+
end
|
112
|
+
str << "</table>\n"
|
113
|
+
next
|
114
|
+
end
|
115
|
+
|
116
|
+
format(str, section)
|
117
|
+
end
|
118
|
+
|
119
|
+
str
|
120
|
+
end
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
|
2
|
+
module ExternalMigration
|
3
|
+
class Dictionary
|
4
|
+
|
5
|
+
def initialize(url)
|
6
|
+
@dictionary = YAML::load(File.open(url))
|
7
|
+
end
|
8
|
+
|
9
|
+
def find(term)
|
10
|
+
if @dictionary.include? term.to_s
|
11
|
+
@dictionary[term.to_s]
|
12
|
+
else
|
13
|
+
term.to_s
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,211 @@
|
|
1
|
+
|
2
|
+
require 'spreadsheet'
|
3
|
+
require 'active_support'
|
4
|
+
|
5
|
+
module ExternalMigration
|
6
|
+
class ActiveMigartionError < StandardError; end
|
7
|
+
class ActiveMigartionDataSourceError < ActiveMigartionError; end
|
8
|
+
class AciteMigrationInvalidRecordError < ActiveMigartionError; end
|
9
|
+
|
10
|
+
|
11
|
+
class Schema
|
12
|
+
##
|
13
|
+
# @attr columns Hash with name and type
|
14
|
+
# @attr format Describe data format
|
15
|
+
# @attr url define path or object schema
|
16
|
+
attr_accessor :columns, :format, :url
|
17
|
+
|
18
|
+
end
|
19
|
+
|
20
|
+
##
|
21
|
+
# Module Data Transformation
|
22
|
+
# When passing schema file or struct, the data between datasources
|
23
|
+
# needs a transformations
|
24
|
+
module Transformer
|
25
|
+
##
|
26
|
+
# called on start of migration
|
27
|
+
def begin(schema_from, schema_to)
|
28
|
+
# nothing
|
29
|
+
end
|
30
|
+
|
31
|
+
##
|
32
|
+
# called on start of transaction
|
33
|
+
def begin_transaction(schema_from, schema_to)
|
34
|
+
# nothing
|
35
|
+
end
|
36
|
+
|
37
|
+
##
|
38
|
+
# transform from data row to destinate data row
|
39
|
+
# @result true, false or :ignore to ignore this row
|
40
|
+
def transform(row)
|
41
|
+
raise "Implements transform method!"
|
42
|
+
end
|
43
|
+
|
44
|
+
##
|
45
|
+
# called on ending migration
|
46
|
+
def end(schema_from, schema_to)
|
47
|
+
# nothing
|
48
|
+
end
|
49
|
+
|
50
|
+
##
|
51
|
+
# called on ending transaction
|
52
|
+
def end_transaction(schema_from, schema_to)
|
53
|
+
# nothing
|
54
|
+
end
|
55
|
+
|
56
|
+
##
|
57
|
+
#
|
58
|
+
def after_row_saved(row, object)
|
59
|
+
#
|
60
|
+
end
|
61
|
+
|
62
|
+
def transform_ignore_fields(row)
|
63
|
+
#delete ignore
|
64
|
+
row.reject! { |key,value| key.to_s.start_with?("ignore") }
|
65
|
+
end
|
66
|
+
|
67
|
+
end
|
68
|
+
|
69
|
+
|
70
|
+
##
|
71
|
+
# == Class Migration
|
72
|
+
#
|
73
|
+
# Migrate data between data source and transforme to destination
|
74
|
+
#
|
75
|
+
class Migration
|
76
|
+
attr_accessor :schema_from, :schema_to, :transformer, :name
|
77
|
+
|
78
|
+
# constructor
|
79
|
+
def initialize(schema_url=nil)
|
80
|
+
self.load_schema(schema_url) unless schema_url.nil?
|
81
|
+
end
|
82
|
+
|
83
|
+
##
|
84
|
+
# load yml schemas from and to
|
85
|
+
def load_schema(url)
|
86
|
+
schema = YAML::load(File.open(url))
|
87
|
+
self.schema_from = schema[:from]
|
88
|
+
self.schema_to = schema[:to]
|
89
|
+
end
|
90
|
+
|
91
|
+
|
92
|
+
##
|
93
|
+
# Running migration from configured files
|
94
|
+
#
|
95
|
+
# ps> Default Behaviour Ignore First line - assumes head line
|
96
|
+
|
97
|
+
def migrate!
|
98
|
+
|
99
|
+
raise "schema_from needs" if @schema_from.nil?
|
100
|
+
raise "schema_to needs" if @schema_to.nil?
|
101
|
+
|
102
|
+
res = @transformer.begin_transaction(@schema_from, @schema_to) unless @transformer.nil?
|
103
|
+
|
104
|
+
ActiveRecord::Base.transaction do
|
105
|
+
begin_migration()
|
106
|
+
|
107
|
+
# TODO: Make flexible configurable and more input formats
|
108
|
+
if @schema_from[:format].to_s.to_sym == :XLS
|
109
|
+
xls_migrate()
|
110
|
+
end
|
111
|
+
|
112
|
+
end_migration()
|
113
|
+
end
|
114
|
+
|
115
|
+
res = @transformer.end_transaction(@schema_from, @schema_to) unless @transformer.nil?
|
116
|
+
|
117
|
+
return true
|
118
|
+
end
|
119
|
+
|
120
|
+
|
121
|
+
def xls_migrate
|
122
|
+
begin
|
123
|
+
@xls = Spreadsheet.open @schema_from[:url]
|
124
|
+
# TODO: make others workbook accessible by configuration
|
125
|
+
sheet = @xls.worksheet 0
|
126
|
+
|
127
|
+
@line = 0
|
128
|
+
|
129
|
+
# ignore head line
|
130
|
+
sheet.each 1 do |row|
|
131
|
+
@column = 0
|
132
|
+
row_to = { }
|
133
|
+
|
134
|
+
#read schema columns and types
|
135
|
+
@schema_from[:columns].each do |schema_column, schema_type|
|
136
|
+
row_to.merge!(schema_column.to_sym => row[@column])
|
137
|
+
@column+=1
|
138
|
+
end
|
139
|
+
|
140
|
+
#transform row to @schema_to
|
141
|
+
res = true
|
142
|
+
res = @transformer.transform(row_to) unless @transformer.nil?
|
143
|
+
|
144
|
+
if (res!=:ignore)
|
145
|
+
res = res==true && send_row_to_schema(row_to)
|
146
|
+
raise_migration if (res==false)
|
147
|
+
|
148
|
+
@transformer.after_row_saved(row_to, @last_object) unless @transformer.nil?
|
149
|
+
end
|
150
|
+
|
151
|
+
@line+=1
|
152
|
+
end
|
153
|
+
rescue Exception => e
|
154
|
+
line = @line.nil? ? 0 : @line
|
155
|
+
column = @column.nil? ? 0 : @column
|
156
|
+
raise ActiveMigartionDataSourceError.new ("Failing import excel source format from %s. %d:%d [ignored head]. " % [@schema_from[:url], column, line]).concat(e.message).concat("\n----"+e.backtrace.to_yaml)
|
157
|
+
end
|
158
|
+
end
|
159
|
+
|
160
|
+
|
161
|
+
def begin_migration
|
162
|
+
# TODO: make transactional
|
163
|
+
res = @transformer.begin(@schema_from, @schema_to) unless @transformer.nil?
|
164
|
+
end
|
165
|
+
|
166
|
+
|
167
|
+
def end_migration
|
168
|
+
res = @transformer.end(@schema_from, @schema_to) unless @transformer.nil?
|
169
|
+
end
|
170
|
+
|
171
|
+
def raise_migration
|
172
|
+
raise "failing migration %s. Line: %d, Column: %d" % [@name, @line, @column]
|
173
|
+
end
|
174
|
+
|
175
|
+
def send_row_to_schema(row)
|
176
|
+
if @schema_to[:format].to_sym == :ACTIVE_RECORD
|
177
|
+
|
178
|
+
# TODO: optimize on initialize migration
|
179
|
+
class_schema_to = eval @schema_to[:url]
|
180
|
+
|
181
|
+
@last_object = class_schema_to.new(row)
|
182
|
+
res = @last_object.save
|
183
|
+
|
184
|
+
if (!res)
|
185
|
+
raise AciteMigrationInvalidRecordError.new "[Schema:%s] Error on send to ACTIVE_RECORD %s. \n%s \nrow: \n%s" % [@name, @schema_to[:url], @last_object.errors.to_yaml, row.to_yaml]
|
186
|
+
end
|
187
|
+
|
188
|
+
return res
|
189
|
+
|
190
|
+
else
|
191
|
+
raise "Not valid schema::TO format! %s" % @name
|
192
|
+
end
|
193
|
+
end
|
194
|
+
|
195
|
+
##
|
196
|
+
# loads yml file and convert to hash on schema_from
|
197
|
+
# @deprecated
|
198
|
+
def load_schema_from(url)
|
199
|
+
self.schema_from = YAML::load(File.open(url))
|
200
|
+
end
|
201
|
+
|
202
|
+
##
|
203
|
+
# load yml file and convert to hash on schema_to
|
204
|
+
# @deprecated
|
205
|
+
def load_schema_to(url)
|
206
|
+
self.schema_to = YAML::load(File.open(url))
|
207
|
+
end
|
208
|
+
|
209
|
+
end
|
210
|
+
|
211
|
+
end
|
@@ -0,0 +1,143 @@
|
|
1
|
+
|
2
|
+
module ExternalMigration
|
3
|
+
|
4
|
+
module Schemas
|
5
|
+
class ActiveMigartionSchemasError < StandardError; end
|
6
|
+
|
7
|
+
##
|
8
|
+
# Façade class
|
9
|
+
# make easy way to running batchs schemas migrations
|
10
|
+
#
|
11
|
+
# === File Format
|
12
|
+
# name_migration:
|
13
|
+
# :type: CUSTOM, SCHEMA
|
14
|
+
# from: URL to from schema or Custom Param
|
15
|
+
# to: URL to destinate schema or Custom Param
|
16
|
+
# transformer: class will be called to data transformations
|
17
|
+
class SchemasMigration
|
18
|
+
|
19
|
+
attr_accessor :transformer, :schemas
|
20
|
+
|
21
|
+
def initialize(file_schemas)
|
22
|
+
raise "Invalid File: should not null!" if file_schemas.nil?
|
23
|
+
raise "Invalid File: should not exists!" if not File.exists?(file_schemas)
|
24
|
+
@schemas = YAML::load(File.open(file_schemas))
|
25
|
+
end
|
26
|
+
|
27
|
+
def migrate!
|
28
|
+
ActiveRecord::Base.transaction do
|
29
|
+
@schemas.each do |key,schema|
|
30
|
+
|
31
|
+
@migration_name = key
|
32
|
+
@schema = schema
|
33
|
+
|
34
|
+
msg = "Starting external migration: %s..." % @migration_name
|
35
|
+
Rails.logger.info msg
|
36
|
+
puts msg
|
37
|
+
|
38
|
+
result = run_migration_job
|
39
|
+
|
40
|
+
raise ActiveMigartionSchemasError.new("Failing Migrate Schemas: %s" % key) if not result
|
41
|
+
|
42
|
+
msg = "Ending: %s." % key
|
43
|
+
Rails.logger.info msg
|
44
|
+
puts msg
|
45
|
+
end
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
|
50
|
+
def eval_class(class_str)
|
51
|
+
begin
|
52
|
+
class_found = eval class_str
|
53
|
+
raise "its %s not a class" % class_str if !class_found.is_a?(Class)
|
54
|
+
rescue
|
55
|
+
class_found = false
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
def transformer_class=(class_str)
|
60
|
+
file_name = class_str.underscore + ".rb"
|
61
|
+
|
62
|
+
class_found = eval_class(class_str)
|
63
|
+
|
64
|
+
if class_found==false
|
65
|
+
require_dependence(file_name)
|
66
|
+
class_found = eval_class(class_str)
|
67
|
+
raise "[%s] Invald informed Transformer: %s. Schema: %s" % [@migration_name, class_str, @schema.to_yaml] if class_found == false
|
68
|
+
end
|
69
|
+
|
70
|
+
@transformer = (eval class_str).new @schema
|
71
|
+
end
|
72
|
+
|
73
|
+
def require_dependence(file_name)
|
74
|
+
|
75
|
+
Rails.logger.warn "Requiring file %s" % file_name
|
76
|
+
|
77
|
+
search_dependency(file_name).each do |file|
|
78
|
+
if File.exists? file
|
79
|
+
Rails.logger.debug "Including file %s" % file
|
80
|
+
require file
|
81
|
+
break
|
82
|
+
end
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
##
|
87
|
+
# @return Array with possible location of file
|
88
|
+
def search_dependency(file_name)
|
89
|
+
files = []
|
90
|
+
files << Rails.root.join("db/external_migrate/" + file_name)
|
91
|
+
|
92
|
+
#possibility paths
|
93
|
+
unless File.exists?(files[0])
|
94
|
+
Dir[file_name,
|
95
|
+
File.expand_path("**/external_migrate/**/" + file_name),
|
96
|
+
"../" + file_name,
|
97
|
+
"../../" + file_name,
|
98
|
+
File.expand_path("**/" + file_name)].each { |f| files << f }
|
99
|
+
end
|
100
|
+
|
101
|
+
files
|
102
|
+
end
|
103
|
+
|
104
|
+
def run_migration_job
|
105
|
+
transformer_from_schema
|
106
|
+
|
107
|
+
case @schema[:type]
|
108
|
+
when :SCHEMA
|
109
|
+
self.migrate_schema
|
110
|
+
when :CUSTOM
|
111
|
+
self.migrate_custom
|
112
|
+
end
|
113
|
+
end
|
114
|
+
|
115
|
+
def migrate_schema
|
116
|
+
migration = ExternalMigration::Migration.new
|
117
|
+
migration.name = @migration_name
|
118
|
+
migration.schema_from = @schema[:from]
|
119
|
+
migration.schema_to = @schema[:to]
|
120
|
+
migration.transformer = @transformer if not @transformer.nil?
|
121
|
+
#rock!
|
122
|
+
migration.migrate!
|
123
|
+
end
|
124
|
+
|
125
|
+
def migrate_custom
|
126
|
+
raise "Transformer not assigned" if @transformer.nil?
|
127
|
+
raise "Invalid Custom Migration Transformer" if not @transformer.respond_to?(:migrate!)
|
128
|
+
|
129
|
+
@transformer.migrate!
|
130
|
+
end
|
131
|
+
|
132
|
+
def transformer_from_schema
|
133
|
+
if @schema.include? :transformer
|
134
|
+
self.transformer_class = @schema[:transformer]
|
135
|
+
else
|
136
|
+
@transformer = nil
|
137
|
+
end
|
138
|
+
end
|
139
|
+
|
140
|
+
|
141
|
+
end
|
142
|
+
end
|
143
|
+
end
|
@@ -0,0 +1,20 @@
|
|
1
|
+
|
2
|
+
module ExternalMigration
|
3
|
+
class SpellingFix
|
4
|
+
|
5
|
+
def initialize(url)
|
6
|
+
@rules = YAML::load(File.open(url))
|
7
|
+
end
|
8
|
+
|
9
|
+
def fix!(term)
|
10
|
+
return term if term.nil? || term.empty?
|
11
|
+
@rules.each do |before,after|
|
12
|
+
term.gsub! before, after
|
13
|
+
end
|
14
|
+
|
15
|
+
term
|
16
|
+
end
|
17
|
+
|
18
|
+
|
19
|
+
end
|
20
|
+
end
|
@@ -0,0 +1,110 @@
|
|
1
|
+
|
2
|
+
module ActiveMigration
|
3
|
+
module Transformer
|
4
|
+
class GroupedFieldFixedSpelling
|
5
|
+
|
6
|
+
include ActiveMigration::Transformer
|
7
|
+
include ApplicationHelper
|
8
|
+
|
9
|
+
attr_accessor :domain_name, :domain_dest
|
10
|
+
|
11
|
+
def initialize(schema)
|
12
|
+
@schema = schema
|
13
|
+
@field_group = :name
|
14
|
+
@field_group_fixed = :name_correct
|
15
|
+
|
16
|
+
@group = {}
|
17
|
+
@rows = []
|
18
|
+
|
19
|
+
@domain_name = "domain"
|
20
|
+
end
|
21
|
+
|
22
|
+
def begin(schema_from, schema_to)
|
23
|
+
@schema_from = schema_from
|
24
|
+
@schema_to = schema_to
|
25
|
+
@group = {}
|
26
|
+
@domain_dictionary = {}
|
27
|
+
@rows = []
|
28
|
+
end
|
29
|
+
|
30
|
+
def transform(row)
|
31
|
+
begin
|
32
|
+
#cache
|
33
|
+
@rows << row
|
34
|
+
|
35
|
+
fix_field row
|
36
|
+
|
37
|
+
return :ignore if row[@field_group].nil?
|
38
|
+
|
39
|
+
#validating and cleanup
|
40
|
+
row[@field_group].gsub! /\s{2,}/, ' '
|
41
|
+
row.delete @field_group_fixed
|
42
|
+
|
43
|
+
@group[row[@field_group]] = row
|
44
|
+
|
45
|
+
return :ignore
|
46
|
+
rescue Exception => e
|
47
|
+
Rails.logger.debug "Error on transform. "+e.message+"\n"+e.backtrace.join("\n ")
|
48
|
+
false
|
49
|
+
end
|
50
|
+
end
|
51
|
+
|
52
|
+
def fix_field(row)
|
53
|
+
#has name_correct?
|
54
|
+
if (!row[@field_group_fixed].nil? && !row[@field_group_fixed].to_s.empty?)
|
55
|
+
row[@field_group_fixed] = row[@field_group_fixed].to_s.strip
|
56
|
+
@domain_dictionary[row[@field_group]] = row[@field_group_fixed]
|
57
|
+
row[@field_group] = row[@field_group_fixed]
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def end(schema_from, schema_to)
|
62
|
+
save_on_cache
|
63
|
+
save_on_db
|
64
|
+
end
|
65
|
+
|
66
|
+
def schema_to_class
|
67
|
+
eval @schema_to[:url]
|
68
|
+
end
|
69
|
+
|
70
|
+
def save_on_db
|
71
|
+
|
72
|
+
class_to = schema_to_class
|
73
|
+
|
74
|
+
@group.each do |key, row|
|
75
|
+
if not class_to.send(("find_by_%s" % @field_group).to_sym, row[@field_group])
|
76
|
+
record = class_to.new(row)
|
77
|
+
puts "SaveOnDB: "+row.to_yaml
|
78
|
+
record.save!
|
79
|
+
end
|
80
|
+
end
|
81
|
+
end
|
82
|
+
|
83
|
+
def save_on_cache
|
84
|
+
|
85
|
+
#cached path
|
86
|
+
@cache_path = "db/external_migrate/cache/"
|
87
|
+
Dir.mkdir path if not Dir.exists? @cache_path
|
88
|
+
|
89
|
+
puts_on_file @cache_path + "#{@domain_name}_dictionary.yml", @domain_dictionary.to_yaml
|
90
|
+
#puts_on_file @cache_path + "#{@domain_name}_raw.csv", @rows.map { |i| i.values.join(",")}.join("\n")
|
91
|
+
puts_on_file @cache_path + "#{@domain_name}_grouped.csv" do
|
92
|
+
lines = []
|
93
|
+
@group.each do |key, data|
|
94
|
+
line = []
|
95
|
+
data.each do |key, value|
|
96
|
+
if value.is_a? String
|
97
|
+
line << value
|
98
|
+
elsif value.respond_to? :name
|
99
|
+
line << value.name
|
100
|
+
end
|
101
|
+
end
|
102
|
+
lines << line.join(",")
|
103
|
+
end
|
104
|
+
lines.join("\n")
|
105
|
+
end
|
106
|
+
#puts_on_file path + "#{@domain_name}.xml", @rows.to_xml
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
metadata
ADDED
@@ -0,0 +1,92 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: active_extend
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Bruno Guerra
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-12-24 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: rails
|
16
|
+
requirement: !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ~>
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: 3.2.9
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: !ruby/object:Gem::Requirement
|
25
|
+
none: false
|
26
|
+
requirements:
|
27
|
+
- - ~>
|
28
|
+
- !ruby/object:Gem::Version
|
29
|
+
version: 3.2.9
|
30
|
+
- !ruby/object:Gem::Dependency
|
31
|
+
name: sqlite3
|
32
|
+
requirement: !ruby/object:Gem::Requirement
|
33
|
+
none: false
|
34
|
+
requirements:
|
35
|
+
- - ! '>='
|
36
|
+
- !ruby/object:Gem::Version
|
37
|
+
version: '0'
|
38
|
+
type: :development
|
39
|
+
prerelease: false
|
40
|
+
version_requirements: !ruby/object:Gem::Requirement
|
41
|
+
none: false
|
42
|
+
requirements:
|
43
|
+
- - ! '>='
|
44
|
+
- !ruby/object:Gem::Version
|
45
|
+
version: '0'
|
46
|
+
description: many cool behaviors for active_model.
|
47
|
+
email:
|
48
|
+
- bruno@woese.com
|
49
|
+
executables: []
|
50
|
+
extensions: []
|
51
|
+
extra_rdoc_files: []
|
52
|
+
files:
|
53
|
+
- lib/active_extend/active_disablable.rb
|
54
|
+
- lib/active_extend/string_helper.rb
|
55
|
+
- lib/active_extend/version.rb
|
56
|
+
- lib/active_extend.rb
|
57
|
+
- lib/external_migration/converters/rtf_to_html.rb
|
58
|
+
- lib/external_migration/dictionary.rb
|
59
|
+
- lib/external_migration/migration.rb
|
60
|
+
- lib/external_migration/schemas.rb
|
61
|
+
- lib/external_migration/spelling_fix.rb
|
62
|
+
- lib/external_migration/transformer/grouped_field_fixed_spelling.rb
|
63
|
+
- lib/external_migration.rb
|
64
|
+
- lib/tasks/active_extends_tasks.rake
|
65
|
+
- MIT-LICENSE
|
66
|
+
- Rakefile
|
67
|
+
- README.rdoc
|
68
|
+
homepage: http://www.woese.com
|
69
|
+
licenses: []
|
70
|
+
post_install_message:
|
71
|
+
rdoc_options: []
|
72
|
+
require_paths:
|
73
|
+
- lib
|
74
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
75
|
+
none: false
|
76
|
+
requirements:
|
77
|
+
- - ! '>='
|
78
|
+
- !ruby/object:Gem::Version
|
79
|
+
version: '0'
|
80
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
81
|
+
none: false
|
82
|
+
requirements:
|
83
|
+
- - ! '>='
|
84
|
+
- !ruby/object:Gem::Version
|
85
|
+
version: '0'
|
86
|
+
requirements: []
|
87
|
+
rubyforge_project:
|
88
|
+
rubygems_version: 1.8.24
|
89
|
+
signing_key:
|
90
|
+
specification_version: 3
|
91
|
+
summary: many cool behaviors for active_model
|
92
|
+
test_files: []
|