transform and clean utf-8

Andrew Cantino 11 年 前
コミット
21c0e5911d
共有1 個のファイルを変更した33 個の追加7 個の削除を含む
  1. 33 7
      db/migrate/20131223032112_switch_to_json_serialization.rb

+ 33 - 7
db/migrate/20131223032112_switch_to_json_serialization.rb

@@ -5,17 +5,41 @@ class SwitchToJsonSerialization < ActiveRecord::Migration
5 5
   }
6 6
 
7 7
   def up
8
-    puts "This migration will update Agent and Event storage from YAML to JSON.  It should work, but please make a backup"
9
-    puts "before proceeding."
10
-    print "Continue? (y/n) "
11
-    STDOUT.flush
12
-    exit unless STDIN.gets =~ /^y/i
8
+    if data_exists?
9
+      puts "This migration will update tables to use UTF-8 encoding and will update Agent and Event storage from YAML to JSON."
10
+      puts "It should work, but please make a backup before proceeding!"
11
+      print "Continue? (y/n) "
12
+      STDOUT.flush
13
+      exit unless STDIN.gets =~ /^y/i
13 14
 
14
-    translate YAML, JSON
15
+      set_to_utf8
16
+      translate YAML, JSON
17
+    end
15 18
   end
16 19
 
17 20
   def down
18
-    translate JSON, YAML
21
+    if data_exists?
22
+      translate JSON, YAML
23
+    end
24
+  end
25
+
26
+  def set_to_utf8
27
+    if mysql?
28
+      %w[agent_logs agents delayed_jobs events links taggings tags users].each do |table_name|
29
+        quoted_table_name = ActiveRecord::Base.connection.quote_table_name(table_name)
30
+        execute "ALTER TABLE #{quoted_table_name} CONVERT TO CHARACTER SET utf8"
31
+      end
32
+    end
33
+  end
34
+
35
+  def mysql?
36
+    ActiveRecord::Base.connection.adapter_name =~ /mysql/i
37
+  end
38
+
39
+  def data_exists?
40
+    events = ActiveRecord::Base.connection.select_rows("SELECT count(*) FROM #{ActiveRecord::Base.connection.quote_table_name("events")}").first.first
41
+    agents = ActiveRecord::Base.connection.select_rows("SELECT count(*) FROM #{ActiveRecord::Base.connection.quote_table_name("agents")}").first.first
42
+    agents + events > 0
19 43
   end
20 44
 
21 45
   def translate(from, to)
@@ -29,6 +53,8 @@ class SwitchToJsonSerialization < ActiveRecord::Migration
29 53
 
30 54
         yaml_fields = field_data.map { |f| from.load(f) }.map { |f| to.dump(f) }
31 55
 
56
+        yaml_fields.map! {|f| f.encode('utf-8', 'binary', invalid: :replace, undef: :replace, replace: '??') }
57
+
32 58
         update_sql = "UPDATE #{quoted_table_name} SET #{fields.map {|f| "#{f}=?"}.join(", ")} WHERE id = ?"
33 59
 
34 60
         sanitized_update_sql = ActiveRecord::Base.send :sanitize_sql_array, [update_sql, *yaml_fields, id]