automigration 0.2.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.
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