· 8 years ago · Mar 10, 2018, 03:34 AM
1class Blog < Sequel::Model(:blogs)
2 set_schema do
3 primary_key :id
4 varchar :name
5 varchar :subdomain
6 end
7
8 module Sequel
9 class Model
10 # Create a class for renaming and modifying the model's table info
11 class Migration
12 include Sequel::Schema::SQL
13 attr_reader :db, :table_name
14 def initialize(db, table_name)
15 @db, @table_name = db, table_name
16 end
17
18 def get_column_type(column_name)
19 if (column = db.table_columns(table_name)[column_name.to_s])
20 column[:Type]
21 end
22 end
23
24 def rename_column(names = {})
25 names.each_pair do |old_name, new_name|
26 modify_column(old_name, :name => new_name)
27 end
28 end
29
30 def modify_column(column_name, opts = {})
31 opts[:name] ||= column_name
32 opts[:type] ||= get_column_type(column_name)
33 raise "Can't get column type for #{column_name}" unless opts[:type]
34 db.execute("ALTER TABLE `#{table_name}` CHANGE #{column_name} #{column_definition_sql(opts)}")
35 end
36 end
37
38 # Let the user call "migrate" on a model to bring it up to date
39 class << self
40 def migration
41 Migration.new(db, table_name)
42 end
43
44 # Executes +sql+ if the model's table is not up to date
45 def migrate(sql = nil)
46 if (memory_revision = get_memory_revision) < (table_revision = get_table_revision)
47 set_memory_revision(memory_revision += 1)
48 else
49 db.query(sql) if sql
50 yield migration if block_given?
51 table_revision += 1
52 set_table_revision(table_revision)
53 set_memory_revision(table_revision)
54 end
55 end
56
57 alias :model_migration_drop_table :drop_table
58 def drop_table
59 model_migration_drop_table
60 # Reset the table revision counter when we drop a table
61 set_table_revision(0)
62 end
63
64 def create_table
65 db.create_table_sql_list(*schema.create_info).each {|s| db << s}
66 end
67
68 def start_at_revision(revision = 0) set_memory_revision(revision) end
69
70 protected
71 # Gets the current migration revision stored in memory.
72 def get_memory_revision
73 @memory_revision || 0
74 end
75
76 # Sets the current migration revision stored in memory.
77 def set_memory_revision(revision = 0)
78 @memory_revision = revision
79 end
80
81 # Gets the current migration revision stored in the database. Returns a
82 # tuple: [major, minor] (e.g. [2, 0])
83 def get_table_revision
84 r = table_revisions_dataset.filter(:table_name => table_name.to_s).first
85 r ? r[:major] : 0
86 end
87
88 # Sets the current migration version stored in the database.
89 def set_table_revision(revision = 0)
90 dataset = table_revisions_dataset.filter(:table_name => table_name.to_s)
91 if dataset.first
92 dataset.update(:major => revision, :minor => 0)
93 else
94 dataset << {:table_name => table_name.to_s, :major => revision, :minor => 0}
95 end
96 end
97
98 # Returns the dataset for the table_revisions table. If no such table
99 # exists, it is automatically created.
100 def table_revisions_dataset
101 unless db.table_exists?(:table_revisions)
102 db.create_table(:table_revisions) do
103 primary_key :id
104 text :table_name
105 integer :major, :default => 0
106 integer :minor, :default => 0
107 end
108 end
109 db[:table_revisions]
110 end
111 end
112 end
113end