automigration 0.2.1

Sign up to get free protection for your applications and to get access to all the features.
Files changed (48) hide show
  1. data/.gitignore +6 -0
  2. data/Gemfile +4 -0
  3. data/LICENSE +22 -0
  4. data/README.md +50 -0
  5. data/Rakefile +18 -0
  6. data/automigration.gemspec +24 -0
  7. data/lib/automigration/base_extention.rb +15 -0
  8. data/lib/automigration/fields/belongs_to.rb +29 -0
  9. data/lib/automigration/fields/boolean.rb +9 -0
  10. data/lib/automigration/fields/date.rb +9 -0
  11. data/lib/automigration/fields/datetime.rb +9 -0
  12. data/lib/automigration/fields/float.rb +9 -0
  13. data/lib/automigration/fields/integer.rb +9 -0
  14. data/lib/automigration/fields/password.rb +9 -0
  15. data/lib/automigration/fields/string.rb +9 -0
  16. data/lib/automigration/fields/sys/base.rb +95 -0
  17. data/lib/automigration/fields/sys/db_column.rb +36 -0
  18. data/lib/automigration/fields/sys/keeper.rb +113 -0
  19. data/lib/automigration/fields/sys/slice_creater.rb +32 -0
  20. data/lib/automigration/fields/text.rb +9 -0
  21. data/lib/automigration/fields/time.rb +9 -0
  22. data/lib/automigration/migrator.rb +189 -0
  23. data/lib/automigration/version.rb +3 -0
  24. data/lib/automigration.rb +42 -0
  25. data/lib/tasks/automigration.rake +8 -0
  26. data/log/.gitkeep +0 -0
  27. data/test/auto_migration_test.rb +186 -0
  28. data/test/belongs_to_test.rb +51 -0
  29. data/test/db_column_test.rb +23 -0
  30. data/test/fields/accessible_test.rb +13 -0
  31. data/test/fields_test.rb +34 -0
  32. data/test/models/accessible_model.rb +6 -0
  33. data/test/models/auto_migration1.rb +14 -0
  34. data/test/models/auto_migration1a.rb +7 -0
  35. data/test/models/auto_migration2.rb +8 -0
  36. data/test/models/auto_migration3.rb +5 -0
  37. data/test/models/belongs_to_model.rb +9 -0
  38. data/test/models/boolean_model.rb +5 -0
  39. data/test/models/form_field.rb +6 -0
  40. data/test/models/form_field2.rb +6 -0
  41. data/test/models/local_name.rb +5 -0
  42. data/test/models/local_name2.rb +5 -0
  43. data/test/models/not_automigrable.rb +2 -0
  44. data/test/models/searchable.rb +6 -0
  45. data/test/models/simple.rb +5 -0
  46. data/test/models/user1.rb +7 -0
  47. data/test/test_helper.rb +34 -0
  48. 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,3 @@
1
+ module Automigration
2
+ VERSION = "0.2.1"
3
+ 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
@@ -0,0 +1,8 @@
1
+ namespace :db do
2
+ desc "Auto migration"
3
+ task :auto => :environment do
4
+ Rake::Task['db:create'].invoke
5
+ Automigration::Migrator.new.update_schema!
6
+ Rake::Task['db:migrate'].invoke
7
+ end
8
+ 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
@@ -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,6 @@
1
+ class AccessibleModel < ActiveRecord::Base
2
+ has_fields do |f|
3
+ f.integer :first, :default => 0
4
+ f.integer :second, :default => 0, :accessible => false
5
+ end
6
+ 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
@@ -0,0 +1,7 @@
1
+ class AutoMigration1a < ActiveRecord::Base
2
+ add_field :integer, :additional_field
3
+
4
+ has_fields do |f|
5
+ f.integer :integer_field
6
+ end
7
+ end
@@ -0,0 +1,8 @@
1
+ class AutoMigration2 < ActiveRecord::Base
2
+ migration_attr :some_attr1, :some_attr2
3
+ migration_attr :some_attr3
4
+
5
+ has_fields do |f|
6
+ f.integer :integer_field
7
+ end
8
+ end
@@ -0,0 +1,5 @@
1
+ class AutoMigration3 < ActiveRecord::Base
2
+ has_fields :timestamps => false do |f|
3
+ f.integer :integer_field
4
+ end
5
+ end
@@ -0,0 +1,9 @@
1
+ class BelongsToModel < ActiveRecord::Base
2
+ has_fields do |f|
3
+ f.string :name
4
+
5
+ f.belongs_to :simple
6
+ f.belongs_to :some, :class_name => 'Simple'
7
+ f.belongs_to :parent, :class_name => 'BelongsToModel'
8
+ end
9
+ end
@@ -0,0 +1,5 @@
1
+ class BooleanModel < ActiveRecord::Base
2
+ has_fields do |f|
3
+ f.boolean :value
4
+ end
5
+ end
@@ -0,0 +1,6 @@
1
+ class FormField < ActiveRecord::Base
2
+ has_fields do |f|
3
+ f.string :string
4
+ f.integer :integer
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ # encoding: utf-8
2
+ class FormField2 < ActiveRecord::Base
3
+ has_fields do |f|
4
+ f.string :string, :ru => 'Атрибут', :en => 'Attribute'
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class LocalName < ActiveRecord::Base
2
+ has_fields do |f|
3
+ f.integer :value
4
+ end
5
+ end
@@ -0,0 +1,5 @@
1
+ class LocalName2 < ActiveRecord::Base
2
+ has_fields do |f|
3
+ f.integer :value
4
+ end
5
+ end
@@ -0,0 +1,2 @@
1
+ class NotAutomigrable < ActiveRecord::Base
2
+ end
@@ -0,0 +1,6 @@
1
+ class Searchable < ActiveRecord::Base
2
+ has_fields do |t|
3
+ t.string :title
4
+ t.text :body
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ class Simple < ActiveRecord::Base
2
+ has_fields do |f|
3
+ f.boolean :boolean
4
+ end
5
+ end
@@ -0,0 +1,7 @@
1
+ class User1 < ActiveRecord::Base
2
+ validates :login, :presence => true
3
+
4
+ has_fields do |f|
5
+ f.string :login
6
+ end
7
+ end