automigration 0.2.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +6 -0
- data/Gemfile +4 -0
- data/LICENSE +22 -0
- data/README.md +50 -0
- data/Rakefile +18 -0
- data/automigration.gemspec +24 -0
- data/lib/automigration/base_extention.rb +15 -0
- data/lib/automigration/fields/belongs_to.rb +29 -0
- data/lib/automigration/fields/boolean.rb +9 -0
- data/lib/automigration/fields/date.rb +9 -0
- data/lib/automigration/fields/datetime.rb +9 -0
- data/lib/automigration/fields/float.rb +9 -0
- data/lib/automigration/fields/integer.rb +9 -0
- data/lib/automigration/fields/password.rb +9 -0
- data/lib/automigration/fields/string.rb +9 -0
- data/lib/automigration/fields/sys/base.rb +95 -0
- data/lib/automigration/fields/sys/db_column.rb +36 -0
- data/lib/automigration/fields/sys/keeper.rb +113 -0
- data/lib/automigration/fields/sys/slice_creater.rb +32 -0
- data/lib/automigration/fields/text.rb +9 -0
- data/lib/automigration/fields/time.rb +9 -0
- data/lib/automigration/migrator.rb +189 -0
- data/lib/automigration/version.rb +3 -0
- data/lib/automigration.rb +42 -0
- data/lib/tasks/automigration.rake +8 -0
- data/log/.gitkeep +0 -0
- data/test/auto_migration_test.rb +186 -0
- data/test/belongs_to_test.rb +51 -0
- data/test/db_column_test.rb +23 -0
- data/test/fields/accessible_test.rb +13 -0
- data/test/fields_test.rb +34 -0
- data/test/models/accessible_model.rb +6 -0
- data/test/models/auto_migration1.rb +14 -0
- data/test/models/auto_migration1a.rb +7 -0
- data/test/models/auto_migration2.rb +8 -0
- data/test/models/auto_migration3.rb +5 -0
- data/test/models/belongs_to_model.rb +9 -0
- data/test/models/boolean_model.rb +5 -0
- data/test/models/form_field.rb +6 -0
- data/test/models/form_field2.rb +6 -0
- data/test/models/local_name.rb +5 -0
- data/test/models/local_name2.rb +5 -0
- data/test/models/not_automigrable.rb +2 -0
- data/test/models/searchable.rb +6 -0
- data/test/models/simple.rb +5 -0
- data/test/models/user1.rb +7 -0
- data/test/test_helper.rb +34 -0
- metadata +131 -0
@@ -0,0 +1,189 @@
|
|
1
|
+
module Automigration
|
2
|
+
class Migrator
|
3
|
+
mattr_reader :system_tables
|
4
|
+
mattr_reader :migrations_path
|
5
|
+
mattr_reader :models_load_path
|
6
|
+
mattr_reader :models_to_ignore
|
7
|
+
@@system_tables = []
|
8
|
+
@@migrations_path = nil
|
9
|
+
@@models_load_path = []
|
10
|
+
@@models_to_ignore = []
|
11
|
+
|
12
|
+
def self.set_system_tables(tables)
|
13
|
+
@@system_tables = tables
|
14
|
+
end
|
15
|
+
|
16
|
+
def self.set_migrations_path(path)
|
17
|
+
@@migrations_path = path
|
18
|
+
end
|
19
|
+
|
20
|
+
def self.set_models_load_path(paths)
|
21
|
+
@@models_load_path = paths
|
22
|
+
end
|
23
|
+
|
24
|
+
def self.set_models_to_ignore(models)
|
25
|
+
@@models_to_ignore = models
|
26
|
+
end
|
27
|
+
|
28
|
+
def self.all_tables
|
29
|
+
sql = "SELECT tablename FROM pg_tables WHERE schemaname = 'public';"
|
30
|
+
ActiveRecord::Base.connection.execute(sql).map do |row|
|
31
|
+
row["tablename"]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.get_models
|
36
|
+
@@models_load_path.map do |path|
|
37
|
+
Dir[File.expand_path("**/*.rb", path)].map do |model_file|
|
38
|
+
model_name = model_file.sub(path.to_s + '/', '').sub(/.rb$/, '')
|
39
|
+
next if @@models_to_ignore.include?(model_name)
|
40
|
+
model = model_name.camelize.constantize
|
41
|
+
if model && model.is_a?(Class) && model.superclass == ActiveRecord::Base
|
42
|
+
model
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end.flatten.compact
|
46
|
+
end
|
47
|
+
|
48
|
+
def initialize(options = {})
|
49
|
+
options.assert_valid_keys(:skip_output, :models)
|
50
|
+
|
51
|
+
@models = options[:models] || self.class.get_models
|
52
|
+
@options = options
|
53
|
+
end
|
54
|
+
|
55
|
+
def update_schema!
|
56
|
+
log "Models: " + @models.map(&:to_s).join(', ')
|
57
|
+
|
58
|
+
# update tables
|
59
|
+
tables = ['schema_migrations']
|
60
|
+
@models.each do |model|
|
61
|
+
update_model_schema(model)
|
62
|
+
tables << model.table_name
|
63
|
+
|
64
|
+
# update globalize2 tables
|
65
|
+
if model.respond_to?(:translated_attribute_names)
|
66
|
+
translated_model = translated_model(model)
|
67
|
+
update_model_schema(translated_model)
|
68
|
+
tables << translated_model.table_name
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
#remove unused tables
|
73
|
+
(self.class.all_tables - tables - @@system_tables).each do |table|
|
74
|
+
con.drop_table(table)
|
75
|
+
log "Remove table '#{table}'", :red
|
76
|
+
end
|
77
|
+
|
78
|
+
# clean migration table
|
79
|
+
if con.table_exists?('schema_migrations') and @@migrations_path
|
80
|
+
sql = "SELECT version FROM schema_migrations;"
|
81
|
+
|
82
|
+
migrations_in_db = con.execute(sql).map{|row| row['version']}
|
83
|
+
current_migrations = Dir[File.expand_path("*.rb", @@migrations_path)].map do |m_file|
|
84
|
+
File.basename(m_file) =~ /(\d{14})/
|
85
|
+
$1
|
86
|
+
end
|
87
|
+
|
88
|
+
(migrations_in_db - current_migrations).each do |m|
|
89
|
+
log "Clean migration '#{m}'", :red
|
90
|
+
sql = "DELETE FROM schema_migrations WHERE version = '#{m}';"
|
91
|
+
con.execute(sql)
|
92
|
+
end
|
93
|
+
end
|
94
|
+
end
|
95
|
+
|
96
|
+
private
|
97
|
+
def translated_model(model)
|
98
|
+
Class.new(ActiveRecord::Base).tap do |out|
|
99
|
+
out.set_table_name((model.model_name.underscore + '_translation').pluralize)
|
100
|
+
|
101
|
+
out.has_fields do |f|
|
102
|
+
f.integer "#{model.table_name.singularize}_id"
|
103
|
+
f.string :locale
|
104
|
+
model.translated_attribute_names.each do |attr_name|
|
105
|
+
model.fields_keeper.db_columns_for_field(attr_name).each do |column|
|
106
|
+
f.send column.type, column.name
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
112
|
+
|
113
|
+
def update_model_schema(model)
|
114
|
+
# 0. Create table if need
|
115
|
+
unless con.table_exists?(model.table_name)
|
116
|
+
con.create_table(model.table_name) {}
|
117
|
+
log "Create table #{model.table_name}", :green
|
118
|
+
model.reset_column_information
|
119
|
+
end
|
120
|
+
|
121
|
+
unless model.fields_keeper.auto_migrable?
|
122
|
+
log "#{model.to_s} skipped", :yellow
|
123
|
+
else
|
124
|
+
log "process #{model.to_s} ..."
|
125
|
+
auto_columns = model.fields_keeper.db_columns
|
126
|
+
auto_columns_names = auto_columns.map{|c| c.name.to_s}
|
127
|
+
auto_columns_hash = Hash[auto_columns.map{|c| [c.name.to_s, c]}]
|
128
|
+
|
129
|
+
# 1. update columns
|
130
|
+
(model.column_names & auto_columns_names).each do |name|
|
131
|
+
model_column = Fields::Sys::DbColumn.from_activerecord_column(model.columns_hash[name])
|
132
|
+
auto_column = auto_columns_hash[name]
|
133
|
+
|
134
|
+
unless model_column.the_same?(auto_column)
|
135
|
+
begin
|
136
|
+
con.change_column(model.table_name, name, auto_column.type, auto_column.to_options)
|
137
|
+
|
138
|
+
log "Update column #{name} of #{model.table_name} " +
|
139
|
+
"to :#{auto_column.type} type and options #{auto_column.to_options.inspect}", :yellow
|
140
|
+
rescue
|
141
|
+
con.remove_column(model.table_name, name)
|
142
|
+
con.add_column(model.table_name, name, auto_column.type, auto_column.to_options)
|
143
|
+
log "recreate column #{name} in #{model.table_name}", :yellow
|
144
|
+
end
|
145
|
+
end
|
146
|
+
end
|
147
|
+
|
148
|
+
# 2. add new columns
|
149
|
+
(auto_columns_names - model.column_names).each do |name|
|
150
|
+
auto_column = auto_columns_hash[name]
|
151
|
+
con.add_column(model.table_name, name, auto_column.type, auto_column.to_options)
|
152
|
+
log "Add column #{name} to #{model.table_name}", :green
|
153
|
+
|
154
|
+
model.reset_column_information
|
155
|
+
|
156
|
+
if auto_column.options[:default].present?
|
157
|
+
model.update_all("#{name} = '#{auto_column.options[:default]}'")
|
158
|
+
log "Update default value for #{model.count} models", :green
|
159
|
+
end
|
160
|
+
end
|
161
|
+
|
162
|
+
# 3. remove obsoleted columns
|
163
|
+
not_to_del = ['id'] + model.fields_keeper.migration_attrs
|
164
|
+
(model.column_names - auto_columns_names - not_to_del).each do |name|
|
165
|
+
con.remove_column(model.table_name, name)
|
166
|
+
log "Remove column #{name} from #{model.table_name}", :red
|
167
|
+
end
|
168
|
+
|
169
|
+
model.reset_column_information
|
170
|
+
end
|
171
|
+
end
|
172
|
+
|
173
|
+
def con
|
174
|
+
ActiveRecord::Base.connection
|
175
|
+
end
|
176
|
+
|
177
|
+
def log(msg, color = nil)
|
178
|
+
puts "[auto] " + colored(msg, color) unless @options[:skip_output]
|
179
|
+
end
|
180
|
+
|
181
|
+
def colored(msg, color)
|
182
|
+
if [:red, :green, :yellow].include? color
|
183
|
+
ANSI.send(color){msg}
|
184
|
+
else
|
185
|
+
msg
|
186
|
+
end
|
187
|
+
end
|
188
|
+
end
|
189
|
+
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'rails/engine'
|
2
|
+
require 'ansi'
|
3
|
+
require 'automigration/version'
|
4
|
+
require 'automigration/migrator'
|
5
|
+
require 'automigration/fields/sys/base'
|
6
|
+
require 'automigration/fields/belongs_to'
|
7
|
+
require 'automigration/fields/boolean'
|
8
|
+
require 'automigration/fields/date'
|
9
|
+
require 'automigration/fields/datetime'
|
10
|
+
require 'automigration/fields/float'
|
11
|
+
require 'automigration/fields/integer'
|
12
|
+
require 'automigration/fields/password'
|
13
|
+
require 'automigration/fields/string'
|
14
|
+
require 'automigration/fields/text'
|
15
|
+
require 'automigration/fields/time'
|
16
|
+
require 'automigration/fields/sys/db_column'
|
17
|
+
require 'automigration/fields/sys/keeper'
|
18
|
+
require 'automigration/fields/sys/slice_creater'
|
19
|
+
|
20
|
+
module Automigration
|
21
|
+
class Engine < ::Rails::Engine
|
22
|
+
config.automigration = ActiveSupport::OrderedOptions.new
|
23
|
+
config.automigration.system_tables = []
|
24
|
+
config.automigration.models_load_path = []
|
25
|
+
config.automigration.models_to_ignore = []
|
26
|
+
config.automigration.migrations_path = nil
|
27
|
+
|
28
|
+
initializer 'automigration' do |app|
|
29
|
+
app.config.automigration.models_load_path << Rails.root + 'app/models'
|
30
|
+
app.config.automigration.migrations_path = Rails.root + 'db/migrate'
|
31
|
+
|
32
|
+
ActiveSupport.on_load(:active_record) do
|
33
|
+
require 'automigration/base_extention'
|
34
|
+
end
|
35
|
+
|
36
|
+
Migrator.set_models_load_path(app.config.automigration.models_load_path)
|
37
|
+
Migrator.set_models_to_ignore(app.config.automigration.models_to_ignore)
|
38
|
+
Migrator.set_system_tables(app.config.automigration.system_tables)
|
39
|
+
Migrator.set_migrations_path(app.config.automigration.migrations_path)
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
data/log/.gitkeep
ADDED
File without changes
|
@@ -0,0 +1,186 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Automigration
|
4
|
+
class AutoMigrationTest < ActiveSupport::TestCase
|
5
|
+
def setup
|
6
|
+
@migrations_path = Migrator.migrations_path
|
7
|
+
@system_tables = Migrator.system_tables
|
8
|
+
@models_to_ignore = Migrator.models_to_ignore
|
9
|
+
end
|
10
|
+
|
11
|
+
def teardown
|
12
|
+
Migrator.set_migrations_path(@migrations_path)
|
13
|
+
Migrator.set_system_tables(@system_tables)
|
14
|
+
Migrator.set_models_to_ignore(@models_to_ignore)
|
15
|
+
|
16
|
+
if connection.table_exists?('not_used_table')
|
17
|
+
connection.drop_table('not_used_table')
|
18
|
+
end
|
19
|
+
|
20
|
+
if connection.table_exists?('schema_migrations')
|
21
|
+
connection.drop_table('schema_migrations')
|
22
|
+
end
|
23
|
+
|
24
|
+
FileUtils.rm_rf(migrations_dir)
|
25
|
+
|
26
|
+
connection.drop_table('auto_migration1s') if Migrator.all_tables.index('auto_migration1s')
|
27
|
+
connection.drop_table('auto_migration2s')
|
28
|
+
Migrator.new(:skip_output => true).update_schema!
|
29
|
+
end
|
30
|
+
|
31
|
+
def test_create_table_if_need
|
32
|
+
connection.drop_table('auto_migration1s')
|
33
|
+
assert !Migrator.all_tables.index('auto_migration1s')
|
34
|
+
|
35
|
+
Migrator.new(:skip_output => true).update_schema!
|
36
|
+
assert Migrator.all_tables.index('auto_migration1s')
|
37
|
+
end
|
38
|
+
|
39
|
+
def test_not_create_table_if_ignored
|
40
|
+
connection.drop_table('auto_migration1s')
|
41
|
+
assert !Migrator.all_tables.index('auto_migration1s')
|
42
|
+
|
43
|
+
Migrator.set_models_to_ignore(['auto_migration1'])
|
44
|
+
Migrator.new(:skip_output => true).update_schema!
|
45
|
+
assert !Migrator.all_tables.index('auto_migration1s')
|
46
|
+
end
|
47
|
+
|
48
|
+
def test_remove_unused_table
|
49
|
+
connection.create_table('not_used_table')
|
50
|
+
assert Migrator.all_tables.index('not_used_table')
|
51
|
+
|
52
|
+
Migrator.new(:skip_output => true).update_schema!
|
53
|
+
assert !Migrator.all_tables.index('not_used_table')
|
54
|
+
end
|
55
|
+
|
56
|
+
def test_not_remove_unused_table_if_it_checked_as_not_migratable
|
57
|
+
connection.create_table('not_used_table')
|
58
|
+
Migrator.set_system_tables(%w(not_used_table))
|
59
|
+
assert Migrator.all_tables.index('not_used_table')
|
60
|
+
|
61
|
+
Migrator.new(:skip_output => true).update_schema!
|
62
|
+
assert Migrator.all_tables.index('not_used_table')
|
63
|
+
end
|
64
|
+
|
65
|
+
def test_clean_unused_migration
|
66
|
+
connection.create_table('schema_migrations') do |t|
|
67
|
+
t.string :version
|
68
|
+
end
|
69
|
+
connection.execute("INSERT INTO schema_migrations(version) VALUES('20110114120000')")
|
70
|
+
connection.execute("INSERT INTO schema_migrations(version) VALUES('20110114132500')")
|
71
|
+
connection.execute("INSERT INTO schema_migrations(version) VALUES('20110114193000')")
|
72
|
+
|
73
|
+
FileUtils.mkdir_p(migrations_dir)
|
74
|
+
File.open(migrations_dir + "/20110114120000_create_users.rb", "w"){|f| f.puts "# some text"}
|
75
|
+
File.open(migrations_dir + "/20110114193000_create_projects.rb", "w"){|f| f.puts "# some text"}
|
76
|
+
|
77
|
+
Migrator.set_migrations_path(migrations_dir)
|
78
|
+
|
79
|
+
count_sql = "SELECT count(*) AS count FROM schema_migrations"
|
80
|
+
assert_equal 3, connection.execute(count_sql)[0]['count'].to_i
|
81
|
+
Migrator.new(:skip_output => true).update_schema!
|
82
|
+
assert_equal 2, connection.execute(count_sql)[0]['count'].to_i
|
83
|
+
end
|
84
|
+
|
85
|
+
def test_update_column_for_model_not_change_type_dramatically
|
86
|
+
connection.remove_column(AutoMigration1.table_name, 'string_field')
|
87
|
+
connection.add_column(AutoMigration1.table_name, 'string_field', :integer)
|
88
|
+
AutoMigration1.reset_column_information
|
89
|
+
|
90
|
+
AutoMigration1.create!(:string_field => 123)
|
91
|
+
assert_equal 123, AutoMigration1.first.string_field
|
92
|
+
|
93
|
+
Migrator.new(:skip_output => true).update_schema!
|
94
|
+
|
95
|
+
assert_equal '123', AutoMigration1.first.string_field
|
96
|
+
end
|
97
|
+
|
98
|
+
def test_update_column_for_model_change_type_dramatically
|
99
|
+
connection.remove_column(AutoMigration1.table_name, 'integer_field')
|
100
|
+
connection.add_column(AutoMigration1.table_name, 'integer_field', :string)
|
101
|
+
AutoMigration1.reset_column_information
|
102
|
+
|
103
|
+
AutoMigration1.create!(:integer_field => 'abc')
|
104
|
+
assert_equal 'abc', AutoMigration1.first.integer_field
|
105
|
+
|
106
|
+
Migrator.new(:skip_output => true).update_schema!
|
107
|
+
|
108
|
+
assert_equal nil, AutoMigration1.first.integer_field
|
109
|
+
end
|
110
|
+
|
111
|
+
def test_create_columns_for_model
|
112
|
+
assert AutoMigration1.new.attributes.keys.index("boolean_field")
|
113
|
+
assert AutoMigration1.new.attributes.keys.index("integer_field")
|
114
|
+
assert AutoMigration1.new.attributes.keys.index("float_field")
|
115
|
+
assert AutoMigration1.new.attributes.keys.index("string_field")
|
116
|
+
assert AutoMigration1.new.attributes.keys.index("text_field")
|
117
|
+
assert AutoMigration1.new.attributes.keys.index("datetime_field")
|
118
|
+
assert AutoMigration1.new.attributes.keys.index("date_field")
|
119
|
+
assert AutoMigration1.new.attributes.keys.index("time_field")
|
120
|
+
assert AutoMigration1.new.attributes.keys.index("additional_field")
|
121
|
+
|
122
|
+
assert AutoMigration1.new.attributes.keys.index("created_at")
|
123
|
+
assert AutoMigration1.new.attributes.keys.index("updated_at")
|
124
|
+
end
|
125
|
+
|
126
|
+
def test_create_columns_for_model_add_field
|
127
|
+
assert AutoMigration1a.new.attributes.keys.index("additional_field")
|
128
|
+
assert AutoMigration1a.new.attributes.keys.index("integer_field")
|
129
|
+
|
130
|
+
assert AutoMigration1a.new.attributes.keys.index("created_at")
|
131
|
+
assert AutoMigration1a.new.attributes.keys.index("updated_at")
|
132
|
+
end
|
133
|
+
|
134
|
+
def test_create_model_without_timestamps
|
135
|
+
assert !AutoMigration3.new.attributes.keys.index("created_at")
|
136
|
+
assert !AutoMigration3.new.attributes.keys.index("updated_at")
|
137
|
+
end
|
138
|
+
|
139
|
+
def test_destroy_columns_for_model
|
140
|
+
connection.add_column(AutoMigration1.table_name, 'new_column', :string)
|
141
|
+
AutoMigration1.reset_column_information
|
142
|
+
|
143
|
+
assert AutoMigration1.column_names.index('new_column')
|
144
|
+
Migrator.new(:skip_output => true).update_schema!
|
145
|
+
assert !AutoMigration1.column_names.index('new_column')
|
146
|
+
end
|
147
|
+
|
148
|
+
def test_destroy_columns_for_model
|
149
|
+
connection.add_column(AutoMigration1.table_name, 'new_column', :string)
|
150
|
+
AutoMigration1.reset_column_information
|
151
|
+
|
152
|
+
assert AutoMigration1.column_names.index('new_column')
|
153
|
+
Migrator.new(:skip_output => true).update_schema!
|
154
|
+
assert !AutoMigration1.column_names.index('new_column')
|
155
|
+
end
|
156
|
+
|
157
|
+
def test_destroy_columns_for_model_if_they_are_not_migrate_attr
|
158
|
+
connection.add_column(AutoMigration2.table_name, 'some_attr1', :string)
|
159
|
+
connection.add_column(AutoMigration2.table_name, 'some_attr2', :string)
|
160
|
+
connection.add_column(AutoMigration2.table_name, 'some_attr3', :string)
|
161
|
+
connection.add_column(AutoMigration2.table_name, 'some_attr4', :string)
|
162
|
+
AutoMigration2.reset_column_information
|
163
|
+
|
164
|
+
assert AutoMigration2.column_names.index('some_attr1')
|
165
|
+
assert AutoMigration2.column_names.index('some_attr2')
|
166
|
+
assert AutoMigration2.column_names.index('some_attr3')
|
167
|
+
assert AutoMigration2.column_names.index('some_attr4')
|
168
|
+
|
169
|
+
Migrator.new(:skip_output => true).update_schema!
|
170
|
+
|
171
|
+
assert AutoMigration2.column_names.index('some_attr1')
|
172
|
+
assert AutoMigration2.column_names.index('some_attr2')
|
173
|
+
assert AutoMigration2.column_names.index('some_attr3')
|
174
|
+
assert !AutoMigration2.column_names.index('some_attr4')
|
175
|
+
end
|
176
|
+
|
177
|
+
private
|
178
|
+
def migrations_dir
|
179
|
+
File.expand_path("../../../tmp/migrations", __FILE__)
|
180
|
+
end
|
181
|
+
|
182
|
+
def connection
|
183
|
+
ActiveRecord::Base.connection
|
184
|
+
end
|
185
|
+
end
|
186
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Automigration
|
4
|
+
class BelongsTest < ActiveSupport::TestCase
|
5
|
+
include ActionDispatch::Assertions::SelectorAssertions
|
6
|
+
|
7
|
+
setup do
|
8
|
+
@simple = Simple.create
|
9
|
+
@obj = BelongsToModel.create
|
10
|
+
end
|
11
|
+
|
12
|
+
teardown do
|
13
|
+
Simple.destroy_all
|
14
|
+
end
|
15
|
+
|
16
|
+
test "properties" do
|
17
|
+
assert_nil @obj.simple
|
18
|
+
assert_nil @obj.simple_id
|
19
|
+
end
|
20
|
+
|
21
|
+
test "mass assignment by object" do
|
22
|
+
@obj.update_attributes(:simple => @simple)
|
23
|
+
assert_equal @simple.id, @obj.simple_id
|
24
|
+
end
|
25
|
+
|
26
|
+
test "mass assignment by id" do
|
27
|
+
@obj.update_attributes(:simple_id => @simple.id)
|
28
|
+
assert_equal @simple.id, @obj.simple_id
|
29
|
+
end
|
30
|
+
|
31
|
+
test "use different class name" do
|
32
|
+
@obj.update_attributes(:some => @simple)
|
33
|
+
assert_equal @simple, @obj.some
|
34
|
+
end
|
35
|
+
|
36
|
+
test "raise if wrong name" do
|
37
|
+
assert_raise RuntimeError do
|
38
|
+
Fields::Sys::Base.from_meta(
|
39
|
+
:as => :belongs_to,
|
40
|
+
:name => "simple_id"
|
41
|
+
)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
test "parent and children" do
|
46
|
+
child = BelongsToModel.find(BelongsToModel.create(:parent => @obj).id)
|
47
|
+
assert_equal @obj, child.parent
|
48
|
+
assert_equal @obj.id, child.parent_id
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Automigration
|
4
|
+
class DbColumnTest < ActiveSupport::TestCase
|
5
|
+
def test_the_same
|
6
|
+
a = Fields::Sys::DbColumn.new('field', 'integer',
|
7
|
+
:default => 3,
|
8
|
+
:null => true,
|
9
|
+
:limit => 3,
|
10
|
+
:scale => 1,
|
11
|
+
:precision => 2)
|
12
|
+
|
13
|
+
b = Fields::Sys::DbColumn.new('field', 'integer',
|
14
|
+
:default => 3,
|
15
|
+
:null => true,
|
16
|
+
:limit => 3,
|
17
|
+
:scale => 1,
|
18
|
+
:precision => 2)
|
19
|
+
|
20
|
+
assert a.the_same?(b)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Automigration
|
4
|
+
module Fields
|
5
|
+
class AccessbileTest < ActiveSupport::TestCase
|
6
|
+
test "mass assignment deny" do
|
7
|
+
obj = AccessibleModel.create(:first => 123, :second => 345)
|
8
|
+
assert_equal 123, obj.first
|
9
|
+
assert_equal 0, obj.second
|
10
|
+
end
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
data/test/fields_test.rb
ADDED
@@ -0,0 +1,34 @@
|
|
1
|
+
require 'test_helper'
|
2
|
+
|
3
|
+
module Automigration
|
4
|
+
class FieldsTest < ActiveSupport::TestCase
|
5
|
+
def test_kind_of_field
|
6
|
+
assert_equal :boolean, Fields::Boolean.kind
|
7
|
+
end
|
8
|
+
|
9
|
+
def test_automigrable_model
|
10
|
+
assert Simple.fields_keeper.auto_migrable?
|
11
|
+
assert !NotAutomigrable.fields_keeper.auto_migrable?
|
12
|
+
end
|
13
|
+
|
14
|
+
def test_migrations_attrs
|
15
|
+
assert_equal [], AutoMigration1.fields_keeper.migration_attrs
|
16
|
+
|
17
|
+
assert_equal ['some_attr1', 'some_attr2' , 'some_attr3'],
|
18
|
+
AutoMigration2.fields_keeper.migration_attrs
|
19
|
+
end
|
20
|
+
|
21
|
+
def test_boolean_column_false_by_default
|
22
|
+
assert_equal false, AutoMigration1.new.boolean_field
|
23
|
+
end
|
24
|
+
|
25
|
+
def test_from_meta
|
26
|
+
assert_equal Fields::Boolean, Fields::Sys::Base.from_meta(:as => :boolean, :name => 'some').class
|
27
|
+
end
|
28
|
+
|
29
|
+
def test_attributes_accessible
|
30
|
+
obj = AutoMigration1.create(:integer_field => 123)
|
31
|
+
assert_equal 123, obj.integer_field
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
class AutoMigration1 < ActiveRecord::Base
|
2
|
+
has_fields do |f|
|
3
|
+
f.integer :integer_field
|
4
|
+
f.float :float_field
|
5
|
+
f.boolean :boolean_field
|
6
|
+
f.string :string_field
|
7
|
+
f.text :text_field
|
8
|
+
f.datetime :datetime_field
|
9
|
+
f.date :date_field
|
10
|
+
f.time :time_field
|
11
|
+
end
|
12
|
+
|
13
|
+
add_field :integer, :additional_field
|
14
|
+
end
|