automigration 0.2.2 → 1.0.0
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.
- 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
|