automigration 0.2.2 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- data/.rspec +1 -0
- data/.travis.yml +1 -3
- data/CHANGELOG.md +13 -0
- data/README.md +44 -23
- data/Rakefile +10 -12
- data/automigration.gemspec +4 -0
- data/lib/automigration.rb +5 -38
- data/lib/automigration/active_record_ext.rb +17 -0
- data/lib/automigration/db_column.rb +32 -0
- data/lib/automigration/dsl.rb +29 -0
- data/lib/automigration/engine.rb +23 -0
- data/lib/automigration/field.rb +75 -0
- data/lib/automigration/fields_keeper.rb +85 -0
- data/lib/automigration/migrator.rb +38 -77
- data/lib/automigration/version.rb +1 -1
- data/spec/dummy/.gitignore +2 -0
- data/spec/dummy/README.rdoc +261 -0
- data/spec/dummy/Rakefile +7 -0
- data/spec/dummy/app/assets/javascripts/application.js +15 -0
- data/spec/dummy/app/assets/stylesheets/application.css +13 -0
- data/spec/dummy/app/controllers/application_controller.rb +3 -0
- data/spec/dummy/app/helpers/application_helper.rb +2 -0
- data/{log → spec/dummy/app/mailers}/.gitkeep +0 -0
- data/spec/dummy/app/models/.gitkeep +0 -0
- data/spec/dummy/app/models/accessible_model.rb +6 -0
- data/spec/dummy/app/models/auto_migration1.rb +14 -0
- data/{test → spec/dummy/app}/models/auto_migration1a.rb +2 -2
- data/{test → spec/dummy/app}/models/auto_migration2.rb +2 -2
- data/spec/dummy/app/models/auto_migration3.rb +5 -0
- data/{test → spec/dummy/app}/models/belongs_to_model.rb +0 -0
- data/{test → spec/dummy/app}/models/boolean_model.rb +0 -0
- data/{test → spec/dummy/app}/models/form_field.rb +0 -0
- data/{test → spec/dummy/app}/models/form_field2.rb +1 -1
- data/{test → spec/dummy/app}/models/local_name.rb +0 -0
- data/{test → spec/dummy/app}/models/local_name2.rb +0 -0
- data/{test → spec/dummy/app}/models/not_automigrable.rb +0 -0
- data/{test → spec/dummy/app}/models/searchable.rb +0 -0
- data/{test → spec/dummy/app}/models/simple.rb +0 -0
- data/{test → spec/dummy/app}/models/user1.rb +0 -0
- data/spec/dummy/app/views/layouts/application.html.erb +14 -0
- data/spec/dummy/config.ru +4 -0
- data/spec/dummy/config/application.rb +56 -0
- data/spec/dummy/config/boot.rb +10 -0
- data/spec/dummy/config/database.yml +14 -0
- data/spec/dummy/config/environment.rb +5 -0
- data/spec/dummy/config/environments/development.rb +37 -0
- data/spec/dummy/config/environments/production.rb +67 -0
- data/spec/dummy/config/environments/test.rb +37 -0
- data/spec/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/spec/dummy/config/initializers/inflections.rb +15 -0
- data/spec/dummy/config/initializers/mime_types.rb +5 -0
- data/spec/dummy/config/initializers/secret_token.rb +7 -0
- data/spec/dummy/config/initializers/session_store.rb +8 -0
- data/spec/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/spec/dummy/config/locales/en.yml +5 -0
- data/spec/dummy/config/routes.rb +58 -0
- data/spec/dummy/db/.gitkeep +0 -0
- data/spec/dummy/lib/assets/.gitkeep +0 -0
- data/spec/dummy/log/.gitkeep +0 -0
- data/spec/dummy/public/404.html +26 -0
- data/spec/dummy/public/422.html +26 -0
- data/spec/dummy/public/500.html +25 -0
- data/spec/dummy/public/favicon.ico +0 -0
- data/spec/dummy/script/rails +6 -0
- data/spec/lib/accessible_spec.rb +13 -0
- data/spec/lib/auto_migration_spec.rb +155 -0
- data/spec/lib/belongs_to_spec.rb +38 -0
- data/spec/lib/db_column_spec.rb +21 -0
- data/spec/lib/fields_spec.rb +22 -0
- data/spec/spec_helper.rb +24 -0
- metadata +106 -47
- data/lib/automigration/base_extention.rb +0 -15
- data/lib/automigration/fields/belongs_to.rb +0 -29
- data/lib/automigration/fields/boolean.rb +0 -9
- data/lib/automigration/fields/date.rb +0 -9
- data/lib/automigration/fields/datetime.rb +0 -9
- data/lib/automigration/fields/float.rb +0 -9
- data/lib/automigration/fields/integer.rb +0 -9
- data/lib/automigration/fields/password.rb +0 -9
- data/lib/automigration/fields/string.rb +0 -9
- data/lib/automigration/fields/sys/base.rb +0 -95
- data/lib/automigration/fields/sys/db_column.rb +0 -36
- data/lib/automigration/fields/sys/keeper.rb +0 -113
- data/lib/automigration/fields/sys/slice_creater.rb +0 -32
- data/lib/automigration/fields/text.rb +0 -9
- data/lib/automigration/fields/time.rb +0 -9
- data/test/auto_migration_test.rb +0 -186
- data/test/belongs_to_test.rb +0 -51
- data/test/db_column_test.rb +0 -23
- data/test/fields/accessible_test.rb +0 -13
- data/test/fields_test.rb +0 -34
- data/test/models/accessible_model.rb +0 -6
- data/test/models/auto_migration1.rb +0 -14
- data/test/models/auto_migration3.rb +0 -5
- data/test/test_helper.rb +0 -35
data/.rspec
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
--color
|
data/.travis.yml
CHANGED
data/CHANGELOG.md
ADDED
data/README.md
CHANGED
@@ -1,24 +1,50 @@
|
|
1
1
|
# ActiveRecord automigrations
|
2
2
|
|
3
|
-
|
4
|
-
|
3
|
+
Create/modify/delete Active Record columns without migrations. It works only with PostgreSQL.
|
4
|
+
|
5
|
+
## Installation
|
6
|
+
|
7
|
+
```
|
8
|
+
gem 'automigration'
|
9
|
+
```
|
5
10
|
|
11
|
+
## Usage
|
6
12
|
|
7
|
-
|
13
|
+
Add <tt>has_fields</tt> into your models:
|
8
14
|
|
9
15
|
``` ruby
|
10
16
|
class User < ActiveRecord::Base
|
11
|
-
|
12
|
-
|
13
|
-
|
14
|
-
|
15
|
-
has_fields do |f|
|
16
|
-
f.string :name
|
17
|
-
f.integer :login_count
|
17
|
+
has_fields do
|
18
|
+
string :name
|
19
|
+
integer :login_count
|
18
20
|
end
|
19
21
|
end
|
20
22
|
```
|
21
23
|
|
24
|
+
Fire in console:
|
25
|
+
|
26
|
+
``
|
27
|
+
rake db:migrate
|
28
|
+
```
|
29
|
+
|
30
|
+
To keep some system tables add to <tt>config/application.rb</tt>
|
31
|
+
|
32
|
+
```
|
33
|
+
config.automigration.system_tables << %w[hits very_system_table]
|
34
|
+
```
|
35
|
+
|
36
|
+
Supported fields:
|
37
|
+
|
38
|
+
* belongs_to
|
39
|
+
* boolean
|
40
|
+
* date
|
41
|
+
* datetime
|
42
|
+
* float
|
43
|
+
* integer
|
44
|
+
* string
|
45
|
+
* text
|
46
|
+
* time
|
47
|
+
|
22
48
|
## Devise support
|
23
49
|
|
24
50
|
ActiveRecord::Base supports all types of devise fields with prefix devise\_
|
@@ -27,11 +53,11 @@ ActiveRecord::Base supports all types of devise fields with prefix devise\_
|
|
27
53
|
class User < ActiveRecord::Base
|
28
54
|
devise :database_authenticatable, :rememberable, :trackable, :validatable, :recoverable
|
29
55
|
|
30
|
-
has_fields do
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
56
|
+
has_fields do
|
57
|
+
devise_database_authenticatable :null => false
|
58
|
+
devise_rememberable
|
59
|
+
devise_trackable
|
60
|
+
devise_recoverable
|
35
61
|
end
|
36
62
|
end
|
37
63
|
```
|
@@ -41,12 +67,7 @@ end
|
|
41
67
|
By default in models with has_fields always columns updated_at and created_at created. To ignore
|
42
68
|
use has_fields(:timestamps => false)
|
43
69
|
|
44
|
-
##
|
70
|
+
## Status
|
45
71
|
|
46
|
-
|
47
|
-
|
48
|
-
* Remove db:auto rake task, enhance db:migrate instead
|
49
|
-
|
50
|
-
### Automigration 0.2.1 (March 18, 2012)
|
51
|
-
|
52
|
-
* First public release
|
72
|
+
[<img src="https://secure.travis-ci.org/boshie/automigration.png"/>](http://travis-ci.org/boshie/automigration)
|
73
|
+
[<img src="https://gemnasium.com/boshie/automigration.png"/>](http://gemnasium.com/boshie/automigration)
|
data/Rakefile
CHANGED
@@ -1,18 +1,16 @@
|
|
1
|
-
|
2
|
-
require
|
1
|
+
#!/usr/bin/env rake
|
2
|
+
require "bundler/gem_tasks"
|
3
3
|
|
4
|
-
|
5
|
-
|
6
|
-
|
7
|
-
t.test_files = FileList['test/**/*_test.rb']
|
8
|
-
t.verbose = true
|
9
|
-
end
|
4
|
+
require "rubygems"
|
5
|
+
require "bundler/setup"
|
6
|
+
require 'rspec/core/rake_task'
|
10
7
|
|
11
8
|
namespace :db do
|
12
|
-
desc
|
13
|
-
task
|
14
|
-
|
15
|
-
|
9
|
+
desc "prepare db for specs"
|
10
|
+
task "prepare" do
|
11
|
+
system "cd spec/dummy && bundle exec rake db:drop"
|
12
|
+
system "cd spec/dummy && bundle exec rake db:create db:migrate db:test:prepare"
|
16
13
|
end
|
17
14
|
end
|
18
15
|
|
16
|
+
RSpec::Core::RakeTask.new(:spec)
|
data/automigration.gemspec
CHANGED
@@ -20,5 +20,9 @@ Gem::Specification.new do |s|
|
|
20
20
|
|
21
21
|
s.add_dependency 'rails', '~> 3.1'
|
22
22
|
s.add_dependency 'ansi'
|
23
|
+
|
23
24
|
s.add_development_dependency 'pg'
|
25
|
+
s.add_development_dependency 'rspec-rails'
|
26
|
+
s.add_development_dependency 'database_cleaner'
|
27
|
+
s.add_development_dependency 'factory_girl_rails'
|
24
28
|
end
|
data/lib/automigration.rb
CHANGED
@@ -1,42 +1,9 @@
|
|
1
|
-
require 'rails/engine'
|
2
1
|
require 'ansi'
|
3
2
|
require 'automigration/version'
|
3
|
+
require 'automigration/engine'
|
4
4
|
require 'automigration/migrator'
|
5
|
-
require 'automigration/
|
6
|
-
require 'automigration/
|
7
|
-
require 'automigration/
|
8
|
-
require 'automigration/
|
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'
|
5
|
+
require 'automigration/field'
|
6
|
+
require 'automigration/db_column'
|
7
|
+
require 'automigration/fields_keeper'
|
8
|
+
require 'automigration/dsl'
|
19
9
|
|
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,17 @@
|
|
1
|
+
module ActiveRecord
|
2
|
+
class Base
|
3
|
+
class_attribute :__fields_keeper
|
4
|
+
self.__fields_keeper = nil
|
5
|
+
|
6
|
+
def self.__fields_keeper_instance
|
7
|
+
self.__fields_keeper ||= ::Automigration::FieldsKeeper.new(self)
|
8
|
+
end
|
9
|
+
|
10
|
+
class << self
|
11
|
+
delegate :has_fields, :add_field, :migration_attr, :to => :__fields_keeper_instance
|
12
|
+
delegate :auto_migrable?, :migration_attrs, :to => :__fields_keeper_instance
|
13
|
+
delegate :field_db_columns, :to => :__fields_keeper_instance
|
14
|
+
delegate :fields, :field_names, :to => :__fields_keeper_instance
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,32 @@
|
|
1
|
+
module Automigration
|
2
|
+
class DbColumn < Struct.new(:name, :type, :options)
|
3
|
+
def initialize(name_, type_, options_)
|
4
|
+
super
|
5
|
+
options_.assert_valid_keys(:default, :null, :limit, :scale, :precision)
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.from_activerecord_column(column)
|
9
|
+
out = DbColumn.new(column.name.to_sym, column.type.to_sym, {
|
10
|
+
:default => column.default,
|
11
|
+
:null => column.null,
|
12
|
+
:limit => column.limit,
|
13
|
+
:scale => column.scale,
|
14
|
+
:precision => column.precision
|
15
|
+
})
|
16
|
+
end
|
17
|
+
|
18
|
+
def the_same?(other)
|
19
|
+
(__to_array <=> other.send(:__to_array)) == 0
|
20
|
+
end
|
21
|
+
|
22
|
+
def to_options
|
23
|
+
options.reject{|k, v| v.nil?}
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
# compare only by 3 values
|
28
|
+
def __to_array
|
29
|
+
[name.to_s, type.to_s, options[:default].to_s]
|
30
|
+
end
|
31
|
+
end
|
32
|
+
end
|
@@ -0,0 +1,29 @@
|
|
1
|
+
module Automigration
|
2
|
+
class Dsl
|
3
|
+
attr_reader :fields
|
4
|
+
attr_reader :devise_fields
|
5
|
+
|
6
|
+
def initialize
|
7
|
+
@fields = []
|
8
|
+
@devise_fields = []
|
9
|
+
end
|
10
|
+
|
11
|
+
Field::KIND.each do |field|
|
12
|
+
define_method field do |*args|
|
13
|
+
options = args.extract_options!
|
14
|
+
raise "wrong amount of args" unless args.size == 1
|
15
|
+
name = args[0]
|
16
|
+
@fields << {:name => name, :as => field.to_sym}.merge(options)
|
17
|
+
Field.valid_options_keys(@fields.last)
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def method_missing(meth, *args, &block)
|
22
|
+
if meth.to_s =~ /^devise_(.*)/
|
23
|
+
@devise_fields << {:as => meth, :args => args}
|
24
|
+
else
|
25
|
+
super
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
require 'rails/engine'
|
2
|
+
|
3
|
+
module Automigration
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
config.automigration = ActiveSupport::OrderedOptions.new
|
6
|
+
config.automigration.system_tables = []
|
7
|
+
config.automigration.migration_paths = []
|
8
|
+
config.automigration.model_paths = []
|
9
|
+
|
10
|
+
initializer 'automigration' do |app|
|
11
|
+
app.config.automigration.migration_paths << Rails.root + 'db/migrate'
|
12
|
+
app.config.automigration.model_paths << Rails.root + 'app/models'
|
13
|
+
|
14
|
+
ActiveSupport.on_load(:active_record) do
|
15
|
+
require 'automigration/active_record_ext'
|
16
|
+
end
|
17
|
+
|
18
|
+
Migrator.set_system_tables(app.config.automigration.system_tables)
|
19
|
+
Migrator.set_migration_paths(app.config.automigration.migration_paths)
|
20
|
+
Migrator.set_model_paths(app.config.automigration.model_paths)
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,75 @@
|
|
1
|
+
module Automigration
|
2
|
+
module Field
|
3
|
+
KIND = %w[
|
4
|
+
belongs_to
|
5
|
+
boolean
|
6
|
+
date
|
7
|
+
datetime
|
8
|
+
float
|
9
|
+
integer
|
10
|
+
string
|
11
|
+
text
|
12
|
+
time
|
13
|
+
]
|
14
|
+
|
15
|
+
def self.to_db_columns(field)
|
16
|
+
type = field[:as]
|
17
|
+
|
18
|
+
if type == :belongs_to
|
19
|
+
name = "#{field[:name]}_id"
|
20
|
+
column_type = :integer
|
21
|
+
else
|
22
|
+
name = field[:name]
|
23
|
+
column_type = type
|
24
|
+
end
|
25
|
+
|
26
|
+
if type == :boolean
|
27
|
+
default = !!field[:default]
|
28
|
+
else
|
29
|
+
default = field[:default]
|
30
|
+
end
|
31
|
+
|
32
|
+
Automigration::DbColumn.new(name, column_type, {
|
33
|
+
:default => default,
|
34
|
+
:null => field[:null],
|
35
|
+
:limit => field[:limit],
|
36
|
+
:scale => field[:scale],
|
37
|
+
:precision => field[:precision]
|
38
|
+
})
|
39
|
+
end
|
40
|
+
|
41
|
+
def self.valid_options_keys(field)
|
42
|
+
valid_keys = [
|
43
|
+
:name, :as, # system attributes
|
44
|
+
:default, :null, :limit, :scale, :precision, # db columns keys
|
45
|
+
:accessible # mark attribute as accessible
|
46
|
+
]
|
47
|
+
|
48
|
+
type = field[:as]
|
49
|
+
|
50
|
+
if type == :belongs_to
|
51
|
+
valid_keys += [:class_name, :inverse_of]
|
52
|
+
end
|
53
|
+
|
54
|
+
field.assert_valid_keys(*valid_keys)
|
55
|
+
end
|
56
|
+
|
57
|
+
def self.extend_model!(model, field)
|
58
|
+
type = field[:as]
|
59
|
+
name = field[:name]
|
60
|
+
accessible = (field[:accessible] == nil) || field[:accessible]
|
61
|
+
|
62
|
+
if type == :belongs_to
|
63
|
+
model.belongs_to name, :class_name => field[:class_name], :inverse_of => field[:inverse_of]
|
64
|
+
|
65
|
+
if accessible
|
66
|
+
model.attr_accessible "#{name}_id"
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
if accessible
|
71
|
+
model.attr_accessible name
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
@@ -0,0 +1,85 @@
|
|
1
|
+
module Automigration
|
2
|
+
class FieldsKeeper
|
3
|
+
attr_reader :fields
|
4
|
+
attr_reader :migration_attrs
|
5
|
+
|
6
|
+
def initialize(model)
|
7
|
+
@model = model
|
8
|
+
@fields = nil
|
9
|
+
@devise_fields = []
|
10
|
+
@migration_attrs = []
|
11
|
+
@timestamps_added = false
|
12
|
+
|
13
|
+
@fields_lookup = {}
|
14
|
+
end
|
15
|
+
|
16
|
+
def has_fields(options = {}, &block)
|
17
|
+
options.assert_valid_keys(:timestamps)
|
18
|
+
options.reverse_merge!(:timestamps => true)
|
19
|
+
|
20
|
+
dsl = Automigration::Dsl.new
|
21
|
+
block.arity == 1 ? block.call(dsl) : dsl.instance_exec(&block)
|
22
|
+
|
23
|
+
dsl.fields.each do |field|
|
24
|
+
Field.extend_model!(@model, field)
|
25
|
+
end
|
26
|
+
|
27
|
+
@fields ||= []
|
28
|
+
@fields += dsl.fields
|
29
|
+
@devise_fields = dsl.devise_fields
|
30
|
+
|
31
|
+
if !@timestamps_added && options[:timestamps]
|
32
|
+
@timestamps_added = true
|
33
|
+
@fields << {:as => :datetime, :name => :created_at, :accessible => false}
|
34
|
+
@fields << {:as => :datetime, :name => :updated_at, :accessible => false}
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def add_field(type, name, options = {})
|
39
|
+
has_fields(:timestamps => false) do |f|
|
40
|
+
f.send type, name, options
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def migration_attr(*args)
|
45
|
+
@migration_attrs += args.flatten.map(&:to_s)
|
46
|
+
end
|
47
|
+
|
48
|
+
def auto_migrable?
|
49
|
+
@fields.present?
|
50
|
+
end
|
51
|
+
|
52
|
+
def field_names
|
53
|
+
@field_names ||= fields.map{|f| f[:name]}
|
54
|
+
end
|
55
|
+
|
56
|
+
def field_db_columns
|
57
|
+
out = []
|
58
|
+
|
59
|
+
out += @fields.map do |field|
|
60
|
+
Field.to_db_columns(field)
|
61
|
+
end.flatten
|
62
|
+
|
63
|
+
if defined?(Devise::Schema)
|
64
|
+
devise_schema = Class.new do
|
65
|
+
include Devise::Schema
|
66
|
+
|
67
|
+
define_method :apply_devise_schema do |*args|
|
68
|
+
opts = args.extract_options!
|
69
|
+
raise "wrong arguments" unless args.size == 2
|
70
|
+
name = args[0]
|
71
|
+
as = args[1].to_s.underscore.to_sym
|
72
|
+
as = :datetime if as == :date_time
|
73
|
+
out << Automigration::DbColumn.new(name, as, opts)
|
74
|
+
end
|
75
|
+
end.new
|
76
|
+
|
77
|
+
@devise_fields.each do |meta|
|
78
|
+
devise_schema.send(meta[:as].to_s.sub(/^devise_/, ''), *meta[:args])
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
out
|
83
|
+
end
|
84
|
+
end
|
85
|
+
end
|