localtower 0.5.0 → 1.0.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +25 -17
- data/app/controllers/localtower/pages_controller.rb +27 -12
- data/app/views/layouts/localtower/application.html.erb +16 -33
- data/app/views/localtower/pages/_alert_no_models.html.erb +3 -0
- data/app/views/localtower/pages/migrations.html.erb +52 -83
- data/app/views/localtower/pages/models.html.erb +53 -70
- data/app/views/localtower/pages/new_migration.html.erb +103 -0
- data/app/views/localtower/pages/new_model.html.erb +87 -0
- data/config/routes.rb +4 -4
- data/lib/localtower/generators/migration.rb +51 -120
- data/lib/localtower/generators/model.rb +52 -28
- data/lib/localtower/generators/service_objects/insert_array.rb +23 -0
- data/lib/localtower/generators/service_objects/insert_defaults.rb +15 -43
- data/lib/localtower/generators/service_objects/insert_indexes.rb +80 -0
- data/lib/localtower/generators/service_objects/insert_nullable.rb +23 -0
- data/lib/localtower/status.rb +1 -1
- data/lib/localtower/tools.rb +13 -16
- data/lib/localtower/version.rb +1 -1
- data/public/css/app.css +0 -49
- data/public/js/app.js +215 -70
- data/public/screenshots/v1.0.0/migrations.png +0 -0
- data/public/screenshots/v1.0.0/models.png +0 -0
- data/public/screenshots/v1.0.0/new_migration.png +0 -0
- data/public/screenshots/v1.0.0/new_model.png +0 -0
- data/spec/dummy/Gemfile +0 -2
- data/spec/dummy/Gemfile.lock +1 -10
- data/spec/dummy/app/models/post.rb +3 -0
- data/spec/dummy/app/models/user.rb +1 -0
- data/spec/dummy/config/environments/development.rb +1 -0
- data/spec/dummy/config/puma.rb +1 -1
- data/spec/dummy/db/migrate/20230119221452_create_users.rb +14 -0
- data/spec/dummy/db/migrate/20230119221751_change_users_at1674166670.rb +7 -0
- data/spec/dummy/db/migrate/20230119222054_create_posts.rb +11 -0
- data/spec/dummy/db/migrate/20230119222106_change_posts_at1674166865.rb +5 -0
- data/spec/dummy/db/schema.rb +20 -8
- data/spec/dummy/log/development.log +15281 -3345
- data/spec/dummy/log/localtower.log +1897 -132
- data/spec/dummy/log/test.log +0 -0
- data/spec/dummy/test/index.html +38 -0
- data/spec/dummy/tmp/pids/server.pid +1 -0
- data/spec/factories/migration.rb +25 -41
- data/spec/factories/model.rb +39 -25
- data/spec/lib/localtower/generators/migration_spec.rb +36 -63
- data/spec/lib/localtower/generators/model_spec.rb +43 -34
- data/spec/lib/localtower/generators/service_objects/insert_array_spec.rb +47 -0
- data/spec/lib/localtower/generators/service_objects/insert_defaults_spec.rb +30 -35
- data/spec/lib/localtower/generators/service_objects/insert_indexes_spec.rb +90 -0
- data/spec/lib/localtower/generators/service_objects/insert_nullable_spec.rb +61 -0
- data/spec/lib/localtower/tools_spec.rb +1 -11
- data/spec/spec_helper.rb +8 -3
- metadata +34 -18
- data/app/views/localtower/pages/_migrations.html.erb +0 -57
- data/app/views/localtower/pages/schema.html.erb +0 -67
- data/spec/dummy/db/migrate/20221115190039_create_users.rb +0 -13
- data/spec/dummy/db/migrate/20221115193020_change_users.rb +0 -8
- data/spec/dummy/db/migrate/20221115193532_change_users_at1668540931.rb +0 -5
- data/spec/dummy/db/migrate/20221115193605_change_users_at1668540964.rb +0 -5
- data/spec/dummy/db/migrate/20221115193637_change_users_at1668540996.rb +0 -5
- data/spec/dummy/db/migrate/20221115193642_change_users_at1668541001.rb +0 -5
- data/spec/lib/localtower/generators/relation_spec.rb +0 -65
@@ -0,0 +1,103 @@
|
|
1
|
+
<% content_for :title do %>New Migration<% end %>
|
2
|
+
<div class="row">
|
3
|
+
<div class="col-md-12">
|
4
|
+
<div class="card">
|
5
|
+
<div class="header">
|
6
|
+
<% if @models.empty? %>
|
7
|
+
<%= render partial: 'alert_no_models' %>
|
8
|
+
<% end %>
|
9
|
+
<div class="alert alert-warning">
|
10
|
+
<span>Remember, you can always edit your migration files manually before running "rails db:migrate"</span>
|
11
|
+
</div>
|
12
|
+
</div>
|
13
|
+
<div class="content">
|
14
|
+
<%= form_tag migrations_path, class: "form" do %>
|
15
|
+
<div class="row">
|
16
|
+
<div class="container-table" data-selector="table">
|
17
|
+
<table class="table table-hover table-striped">
|
18
|
+
<thead>
|
19
|
+
<th> <span data-selector=''>On Model</span></th>
|
20
|
+
<th> <span data-selector=''>Action</span></th>
|
21
|
+
<th> <span data-selector='belongs_to_label'>Belongs To</span></th>
|
22
|
+
<th> <span data-selector='column_label'>Column</span></th>
|
23
|
+
<th> <span data-selector='default_label'>Default</span></th>
|
24
|
+
<th> <span data-selector='new_column_name_label'>New Column Name</span></th>
|
25
|
+
<th> <span data-selector='column_type_label'>Type</span></th>
|
26
|
+
<th> <span data-selector='index_options_label'>Index Options</span></th>
|
27
|
+
<th> <span data-selector='nullable_label'>Can be null?</span></th>
|
28
|
+
<th> <span data-selector=''></span></th>
|
29
|
+
</thead>
|
30
|
+
<tbody data-selector="tbody">
|
31
|
+
<tr data-selector="tr">
|
32
|
+
<td style='width: 300px;'>
|
33
|
+
<%= select_tag "migrations[][table_name]", options_for_select(Localtower::Tools.models.collect {|p| [ p, p.table_name ] }), class: "form-control" %>
|
34
|
+
</td>
|
35
|
+
<td style='width: 220px;'>
|
36
|
+
<%= select_tag "migrations[][action]", options_for_select(::Localtower::Generators::Migration::ACTIONS), class: "form-control", "data-selector" => "action" %>
|
37
|
+
</td>
|
38
|
+
<td>
|
39
|
+
<%= select_tag "migrations[][belongs_to]", options_for_select(Localtower::Tools.models.collect {|p| [ p, p.table_name ] }), class: "form-control", "data-selector" => "belongs_to" %>
|
40
|
+
</td>
|
41
|
+
<td class="text-center">
|
42
|
+
<input type="text" name="migrations[][column]" class="form-control" data-selector="column_text">
|
43
|
+
<%= select_tag "migrations[][column_list]", options_for_select(::Localtower::Tools.all_columns), class: "form-control", include_blank: true, "data-selector" => "column_list" %>
|
44
|
+
</td>
|
45
|
+
<td>
|
46
|
+
<%= select_tag "migrations[][default]", options_for_select(::Localtower::Generators::ServiceObjects::InsertDefaults::DEFAULTS), class: "form-control", include_blank: true, "data-selector" => "default_input" %>
|
47
|
+
</td>
|
48
|
+
<td>
|
49
|
+
<input type="text" name="migrations[][new_column_name]" class="form-control" data-selector="new_column_name">
|
50
|
+
</td>
|
51
|
+
<td>
|
52
|
+
<%= select_tag "migrations[][column_type]", options_for_select(::Localtower::Generators::Migration::TYPES), class: "form-control", "data-selector" => "column_type" %>
|
53
|
+
</td>
|
54
|
+
<td>
|
55
|
+
<div data-selector="index_options">
|
56
|
+
<div class="row">
|
57
|
+
<div class="col-md-4">
|
58
|
+
index: <br>
|
59
|
+
<%= select_tag "migrations[][index][using]", options_for_select(::Localtower::Generators::ServiceObjects::InsertIndexes::USING - ['none']), class: "form-control" %>
|
60
|
+
</div>
|
61
|
+
<div class="col-md-4">
|
62
|
+
unique:
|
63
|
+
<br>
|
64
|
+
<%= select_tag "migrations[][index][unique]", options_for_select(::Localtower::Generators::ServiceObjects::InsertIndexes::UNIQUE), class: "form-control" %>
|
65
|
+
</div>
|
66
|
+
<div class="col-md-4">
|
67
|
+
algorithm
|
68
|
+
<br>
|
69
|
+
<%= select_tag "migrations[][index][algorithm]", options_for_select(::Localtower::Generators::ServiceObjects::InsertIndexes::ALGO), class: "form-control" %>
|
70
|
+
</div>
|
71
|
+
</div>
|
72
|
+
</div>
|
73
|
+
</td>
|
74
|
+
<td>
|
75
|
+
<input data-selector="nullable_input" type="checkbox" value="true" name="migrations[][nullable]" class="form-control" checked>
|
76
|
+
</td>
|
77
|
+
<td>
|
78
|
+
<div class="pull-right">
|
79
|
+
<button class="btn btn-danger btn-xs pointer" data-selector="removeLineMigration">Remove line</button>
|
80
|
+
</div>
|
81
|
+
</td>
|
82
|
+
</tr>
|
83
|
+
</tbody>
|
84
|
+
</table>
|
85
|
+
</div>
|
86
|
+
</div>
|
87
|
+
<div class="row">
|
88
|
+
<div class="col-md-12 text-center">
|
89
|
+
<i class="pe-7s-plus pointer" data-selector="duplicateLineNewMigration" style="font-size: 3em;"></i>
|
90
|
+
</div>
|
91
|
+
</div>
|
92
|
+
<div class="row">
|
93
|
+
<div class="col-md-12 text-right">
|
94
|
+
<button type="submit" value="true" class="btn btn-success btn-fill" data-selector="submitNewMigration">
|
95
|
+
Generate the migration
|
96
|
+
</button>
|
97
|
+
</div>
|
98
|
+
</div>
|
99
|
+
<% end %>
|
100
|
+
</div>
|
101
|
+
</div>
|
102
|
+
</div>
|
103
|
+
</div>
|
@@ -0,0 +1,87 @@
|
|
1
|
+
<% content_for :title do %>New Model<% end %>
|
2
|
+
<div class="row">
|
3
|
+
<div class="col-md-12">
|
4
|
+
<div class="card">
|
5
|
+
<div class="header">
|
6
|
+
<div class="alert alert-warning">
|
7
|
+
<span>Remember, you can always edit your migration files manually before running "rails db:migrate"</span>
|
8
|
+
</div>
|
9
|
+
</div>
|
10
|
+
<div class="content">
|
11
|
+
<%= form_tag models_path, class: "form" do %>
|
12
|
+
<div class="row">
|
13
|
+
<div class="col-md-6">
|
14
|
+
<div class="form-group">
|
15
|
+
<label>Name of the Model</label>
|
16
|
+
<input type="text" data-selector="modelName" name="model[model_name]" class="form-control">
|
17
|
+
</div>
|
18
|
+
</div>
|
19
|
+
</div>
|
20
|
+
<div class="row">
|
21
|
+
<table class="table table-hover table-striped">
|
22
|
+
<thead>
|
23
|
+
<th>Type</th>
|
24
|
+
<th>Column Name</th>
|
25
|
+
<th>Default</th>
|
26
|
+
<th>Index Options</th>
|
27
|
+
<th>Can be null?</th>
|
28
|
+
<th></th>
|
29
|
+
</thead>
|
30
|
+
<tbody data-selector="tbody">
|
31
|
+
<tr data-selector="tr">
|
32
|
+
<td>
|
33
|
+
<%= select_tag "model[attributes][][attribute_type]", options_for_select(::Localtower::Generators::Migration::TYPES), class: "form-control" %>
|
34
|
+
</td>
|
35
|
+
<td>
|
36
|
+
<input type="text" data-selector="attributeName" name="model[attributes][][attribute_name]" class="form-control">
|
37
|
+
</td>
|
38
|
+
<td>
|
39
|
+
<%= select_tag "model[attributes][][default]", options_for_select(::Localtower::Generators::ServiceObjects::InsertDefaults::DEFAULTS), class: "form-control" %>
|
40
|
+
</td>
|
41
|
+
<td style='min-width: 240px'>
|
42
|
+
<div class="row">
|
43
|
+
<div class="col-md-4">
|
44
|
+
index: <br>
|
45
|
+
<%= select_tag "model[attributes][][index][using]", options_for_select(::Localtower::Generators::ServiceObjects::InsertIndexes::USING), class: "form-control" %>
|
46
|
+
</div>
|
47
|
+
<div class="col-md-4">
|
48
|
+
unique:
|
49
|
+
<br>
|
50
|
+
<%= select_tag "model[attributes][][index][unique]", options_for_select(::Localtower::Generators::ServiceObjects::InsertIndexes::UNIQUE), class: "form-control" %>
|
51
|
+
</div>
|
52
|
+
<div class="col-md-4">
|
53
|
+
algorithm
|
54
|
+
<br>
|
55
|
+
<%= select_tag "model[attributes][][index][algorithm]", options_for_select(::Localtower::Generators::ServiceObjects::InsertIndexes::ALGO), class: "form-control" %>
|
56
|
+
</div>
|
57
|
+
</div>
|
58
|
+
</td>
|
59
|
+
<td>
|
60
|
+
<input type="checkbox" value="true" name="model[attributes][][nullable]" class="form-control" checked>
|
61
|
+
</td>
|
62
|
+
<td>
|
63
|
+
<div class="pull-right">
|
64
|
+
<button class="btn btn-danger btn-xs pointer" data-selector="removeLineModel">Remove line</button>
|
65
|
+
</div>
|
66
|
+
</td>
|
67
|
+
</tr>
|
68
|
+
</tbody>
|
69
|
+
</table>
|
70
|
+
</div>
|
71
|
+
<div class="row">
|
72
|
+
<div class="col-md-12 text-center">
|
73
|
+
<i class="pe-7s-plus pointer" data-selector="duplicateLineNewModel" style="font-size: 3em;"></i>
|
74
|
+
</div>
|
75
|
+
</div>
|
76
|
+
<div class="row">
|
77
|
+
<div class="col-md-12 text-right">
|
78
|
+
<button type="submit" value="true" class="btn btn-success btn-fill" data-selector="submitNewModel">
|
79
|
+
Generate the migration (and the model)
|
80
|
+
</button>
|
81
|
+
</div>
|
82
|
+
</div>
|
83
|
+
<% end %>
|
84
|
+
</div>
|
85
|
+
</div>
|
86
|
+
</div>
|
87
|
+
</div>
|
data/config/routes.rb
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
Localtower::Engine.routes.draw do
|
2
|
+
get 'migrations/new', to: 'pages#new_migration', as: :new_migration
|
2
3
|
get 'migrations', to: 'pages#migrations', as: :migrations
|
3
4
|
post 'migrations', to: 'pages#post_migrations'
|
4
5
|
|
6
|
+
get 'models/new', to: 'pages#new_model', as: :new_model
|
5
7
|
get 'models', to: 'pages#models', as: :models
|
6
8
|
post 'models', to: 'pages#post_models'
|
7
9
|
|
8
|
-
|
9
|
-
get 'schema', to: 'pages#schema', as: 'schema'
|
10
|
-
post 'actions', to: 'pages#post_actions', as: 'actions'
|
10
|
+
post 'actions', to: 'pages#post_actions', as: :actions
|
11
11
|
|
12
|
-
root :to => redirect('models')
|
12
|
+
root :to => redirect('models/new')
|
13
13
|
end
|
@@ -5,24 +5,16 @@ module Localtower
|
|
5
5
|
include Thor::Actions
|
6
6
|
|
7
7
|
no_commands do
|
8
|
-
# data = {last_migration_file: "", column_type: "", table_name: "", column: "", nullable: true, index: true}
|
9
8
|
def migration_add_column(data)
|
10
|
-
file = data["last_migration_file"]
|
11
|
-
|
12
9
|
# Special case for array
|
13
|
-
if %w
|
14
|
-
line = " add_column :#{data['table_name']}, :#{data['column']}, :
|
10
|
+
if %w[array].include?(data["column_type"])
|
11
|
+
line = " add_column :#{data['table_name']}, :#{data['column']}, :string"
|
15
12
|
line << ", default: []"
|
16
13
|
line << ", array: true"
|
17
|
-
|
18
|
-
# Add an gin inde as well:
|
19
|
-
line << "\n"
|
20
|
-
line << " add_index :#{data['table_name']}, :#{data['column']}, using: :gin"
|
21
14
|
else
|
22
15
|
line = " add_column :#{data['table_name']}, :#{data['column']}, :#{data['column_type']}"
|
23
16
|
line << ", default: #{data['default']}" if data['default'].present?
|
24
|
-
line << ", null: false" if
|
25
|
-
line << ", index: true" if data['index'] == true
|
17
|
+
line << ", null: false" if data['nullable'] == false
|
26
18
|
end
|
27
19
|
|
28
20
|
line << "\n"
|
@@ -31,90 +23,68 @@ module Localtower
|
|
31
23
|
end
|
32
24
|
|
33
25
|
def migration_remove_column(data)
|
34
|
-
file = data['last_migration_file']
|
35
|
-
|
36
26
|
line = " remove_column :#{data['table_name']}, :#{data['column']}\n"
|
37
27
|
|
38
28
|
inject_in_migration(file, line)
|
39
29
|
end
|
40
30
|
|
41
31
|
def migration_rename_column(data)
|
42
|
-
file = data['last_migration_file']
|
43
|
-
|
44
32
|
line = " rename_column :#{data['table_name']}, :#{data['column']}, :#{data['new_column_name']}\n"
|
45
33
|
|
46
34
|
inject_in_migration(file, line)
|
47
35
|
end
|
48
36
|
|
49
37
|
def migration_change_column_type(data)
|
50
|
-
file = data['last_migration_file']
|
51
|
-
|
52
38
|
line = " change_column :#{data['table_name']}, :#{data['column']}, :#{data['new_column_type']}\n"
|
53
39
|
|
54
40
|
inject_in_migration(file, line)
|
55
41
|
end
|
56
42
|
|
57
43
|
def migration_add_index_to_column(data)
|
58
|
-
|
59
|
-
|
60
|
-
line = " add_index :#{data["table_name"]}, :#{data["column"]}\n"
|
44
|
+
line = " add_index :#{data['table_name']}, :#{data['column']}\n"
|
61
45
|
|
62
46
|
inject_in_migration(file, line)
|
63
|
-
end
|
64
|
-
|
65
|
-
# def migration_add_index_to_column_combined(data)
|
66
|
-
# file = data["last_migration_file"]
|
67
|
-
# attr_names = data["column"].split(",")
|
68
47
|
|
69
|
-
|
70
|
-
|
71
|
-
|
72
|
-
|
73
|
-
|
74
|
-
|
75
|
-
|
48
|
+
# Custom options:
|
49
|
+
params = [data]
|
50
|
+
.select { |attr| attr.dig('index', 'using').present? }
|
51
|
+
.reject { |attr| attr.dig('index', 'using') == 'none' }
|
52
|
+
.each_with_object([]) do |attr, arr|
|
53
|
+
arr << Hash[attr['column'], attr['index']]
|
54
|
+
end
|
55
|
+
::Localtower::Generators::ServiceObjects::InsertIndexes.new(params).call
|
56
|
+
end
|
76
57
|
|
77
58
|
def migration_remove_index_to_column(data)
|
78
|
-
|
79
|
-
|
80
|
-
line = " remove_index :#{data["table_name"]}, :#{data["column"]}\n"
|
59
|
+
line = " remove_index :#{data['table_name']}, :#{data['column']}\n"
|
81
60
|
|
82
61
|
inject_in_migration(file, line)
|
83
62
|
end
|
84
63
|
|
85
64
|
def migration_belongs_to(data)
|
86
|
-
|
87
|
-
|
88
|
-
line = " add_reference :#{data["table_name"]}, :#{data["column"]}, foreign_key: true, index: true\n"
|
65
|
+
line = " add_reference :#{data['table_name']}, :#{data['column']}, foreign_key: true, index: true\n"
|
89
66
|
|
90
67
|
inject_in_migration(file, line)
|
91
68
|
|
92
|
-
file = "#{Rails.root}/app/models/#{data[
|
69
|
+
file = "#{Rails.root}/app/models/#{data['table_name'].underscore.singularize}.rb"
|
93
70
|
after = /class #{data["table_name"].camelize.singularize} < ApplicationRecord\n/
|
94
|
-
line1 = " belongs_to :#{data[
|
95
|
-
|
96
|
-
::Localtower::Tools::ThorTools.new.insert_after_word(file, after, line1)
|
71
|
+
line1 = " # belongs_to :#{data['column'].singularize.underscore}\n"
|
97
72
|
|
73
|
+
if File.exist?(file)
|
74
|
+
::Localtower::Tools::ThorTools.new.insert_after_word(file, after, line1)
|
75
|
+
end
|
98
76
|
|
99
|
-
file = "#{Rails.root}/app/models/#{data[
|
77
|
+
file = "#{Rails.root}/app/models/#{data['column'].underscore.singularize}.rb"
|
100
78
|
after = /class #{data["column"].camelize.singularize} < ApplicationRecord\n/
|
101
|
-
line1 = " has_many :#{data[
|
102
|
-
|
103
|
-
::Localtower::Tools::ThorTools.new.insert_after_word(file, after, line1)
|
104
|
-
end
|
105
|
-
|
106
|
-
def migration_create_table(data)
|
107
|
-
file = data["last_migration_file"]
|
108
|
-
|
109
|
-
line = " create_table :#{data["table_name"]}\n"
|
79
|
+
line1 = " # has_many :#{data['table_name'].pluralize.underscore}\n"
|
110
80
|
|
111
|
-
|
81
|
+
if File.exist?(file)
|
82
|
+
::Localtower::Tools::ThorTools.new.insert_after_word(file, after, line1)
|
83
|
+
end
|
112
84
|
end
|
113
85
|
|
114
86
|
def migration_drop_table(data)
|
115
|
-
|
116
|
-
|
117
|
-
line = " drop_table :#{data["table_name"]}, force: :cascade\n"
|
87
|
+
line = " drop_table :#{data['table_name']}\n"
|
118
88
|
|
119
89
|
inject_in_migration(file, line)
|
120
90
|
end
|
@@ -122,55 +92,42 @@ module Localtower
|
|
122
92
|
private
|
123
93
|
|
124
94
|
def inject_in_migration(file, line)
|
125
|
-
inject_into_file(file, line,
|
95
|
+
inject_into_file(file, line, before: " end\nend")
|
96
|
+
end
|
97
|
+
|
98
|
+
def file
|
99
|
+
Localtower::Tools.last_migration
|
126
100
|
end
|
127
101
|
end
|
128
102
|
end
|
129
103
|
|
130
104
|
class Migration
|
131
|
-
TYPES = %w
|
132
|
-
ACTIONS = [
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
105
|
+
TYPES = %w[string datetime date text uuid integer float json jsonb decimal binary boolean array references].freeze
|
106
|
+
ACTIONS = %w[
|
107
|
+
add_column
|
108
|
+
add_index_to_column
|
109
|
+
remove_index_to_column
|
110
|
+
belongs_to
|
111
|
+
remove_column
|
112
|
+
change_column_type
|
113
|
+
rename_column
|
114
|
+
drop_table
|
141
115
|
].freeze
|
142
116
|
|
143
|
-
DEFAULTS = [
|
144
|
-
"true", "false", "nil", "0"
|
145
|
-
]
|
146
|
-
|
147
117
|
# @opts =
|
148
|
-
def initialize(
|
118
|
+
def initialize(migrations)
|
149
119
|
@thor = ThorGeneratorMigration.new
|
150
|
-
@
|
120
|
+
@migrations = JSON[migrations.to_json]
|
151
121
|
end
|
152
122
|
|
153
|
-
# @opts['migrations'] = []
|
154
|
-
# @opts['run_migrate'] = true
|
155
123
|
def run
|
156
|
-
model_names =
|
157
|
-
|
158
|
-
cmd = "Change#{model_names}#{@opts['migration_name']}At#{Time.now.to_i}"
|
159
|
-
::Localtower::Tools.perform_migration(cmd, true)
|
124
|
+
model_names = migrations.map { |line| line['table_name'].camelize }.uniq.join
|
160
125
|
|
161
|
-
|
162
|
-
|
126
|
+
cmd = "Change#{model_names}At#{Time.now.to_i}"
|
127
|
+
::Localtower::Tools.perform_migration(cmd)
|
163
128
|
|
164
|
-
|
165
|
-
|
166
|
-
# index = action_line['index']
|
167
|
-
# default = action_line['default']
|
168
|
-
# null = action_line['null']
|
169
|
-
# unique = action_line['unique']
|
170
|
-
# column_type = action_line['column_type']
|
171
|
-
# new_column_type = action_line['new_column_type']
|
172
|
-
# new_column_name = action_line['new_column_name']
|
173
|
-
action_line["last_migration_file"] = last_migration_file
|
129
|
+
migrations.each do |action_line|
|
130
|
+
next if action_line['action'].blank?
|
174
131
|
|
175
132
|
{
|
176
133
|
'add_column' => -> { add_column(action_line) },
|
@@ -180,24 +137,15 @@ module Localtower
|
|
180
137
|
'add_index_to_column' => -> { add_index_to_column(action_line) },
|
181
138
|
'belongs_to' => -> { belongs_to(action_line) },
|
182
139
|
'remove_index_to_column' => -> { remove_index_to_column(action_line) },
|
183
|
-
'create_table' => -> { create_table(action_line) },
|
184
140
|
'drop_table' => -> { drop_table(action_line) }
|
185
|
-
|
186
|
-
end
|
187
|
-
|
188
|
-
if @opts['run_migrate']
|
189
|
-
run_migration_or_nil
|
141
|
+
}[action_line['action']].call
|
190
142
|
end
|
191
143
|
end
|
192
144
|
|
193
|
-
#====================================
|
194
|
-
def last_migration_file
|
195
|
-
Dir["#{Rails.root}/db/migrate/*"].sort.last
|
196
|
-
end
|
197
|
-
|
198
|
-
# VALIDATION before continuing:
|
199
145
|
private
|
200
146
|
|
147
|
+
attr_reader :migrations
|
148
|
+
|
201
149
|
def add_column(data)
|
202
150
|
@thor.migration_add_column(data)
|
203
151
|
end
|
@@ -229,26 +177,9 @@ module Localtower
|
|
229
177
|
@thor.migration_remove_index_to_column(data)
|
230
178
|
end
|
231
179
|
|
232
|
-
def create_table(data)
|
233
|
-
@thor.migration_create_table(data)
|
234
|
-
end
|
235
|
-
|
236
180
|
def drop_table(data)
|
237
181
|
@thor.migration_drop_table(data)
|
238
182
|
end
|
239
|
-
|
240
|
-
def run_migration_or_nil
|
241
|
-
if last_migration_changed?
|
242
|
-
::Localtower::Tools.perform_cmd('rake db:migrate')
|
243
|
-
else
|
244
|
-
File.delete(last_migration_file)
|
245
|
-
nil
|
246
|
-
end
|
247
|
-
end
|
248
|
-
|
249
|
-
def last_migration_changed?
|
250
|
-
File.readlines(last_migration_file).join != ~ /def change\n end/
|
251
|
-
end
|
252
183
|
end
|
253
184
|
end
|
254
185
|
end
|
@@ -3,52 +3,76 @@ module Localtower
|
|
3
3
|
class Model
|
4
4
|
def initialize(opts)
|
5
5
|
@opts = JSON[opts.to_json] # stringify keys
|
6
|
+
@model_name = @opts['model_name']
|
7
|
+
@attributes = @opts['attributes']
|
8
|
+
|
9
|
+
raise "No model_name provided" if @model_name.blank?
|
10
|
+
raise "No attributes provided" if @attributes.blank?
|
6
11
|
end
|
7
12
|
|
8
|
-
# data = {attributes: "", model_name: ""}
|
9
13
|
def run
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
attributes_list = []
|
14
|
+
attributes_str = parse_attributes.join(" ")
|
15
|
+
cmd = "rails generate model #{model_name.camelize} #{attributes_str}"
|
14
16
|
|
15
|
-
|
16
|
-
str = "#{attribute_data["attribute_name"]}:#{attribute_data["attribute_type"]}"
|
17
|
-
str << ":index" if attribute_data["index"]
|
17
|
+
::Localtower::Tools.perform_cmd(cmd)
|
18
18
|
|
19
|
-
|
20
|
-
|
19
|
+
insert_non_nullable_values
|
20
|
+
insert_default_values
|
21
|
+
insert_array
|
22
|
+
insert_indexes
|
23
|
+
end
|
21
24
|
|
22
|
-
|
23
|
-
cmd = "rails g model #{@opts['model_name'].camelize} #{attributes_str}"
|
25
|
+
private
|
24
26
|
|
25
|
-
|
27
|
+
attr_reader :model_name
|
28
|
+
attr_reader :attributes
|
26
29
|
|
27
|
-
|
28
|
-
|
30
|
+
def parse_attributes
|
31
|
+
attributes.map do |attr_hash|
|
32
|
+
[
|
33
|
+
attr_hash['attribute_name'],
|
34
|
+
(attr_hash['attribute_type'] == 'array' ? 'string' : attr_hash['attribute_type']), # we need this transformation of "array"
|
35
|
+
(attr_hash.dig('index', 'using') != 'none') ? 'index' : nil
|
36
|
+
].compact.join(':')
|
29
37
|
end
|
38
|
+
end
|
30
39
|
|
31
|
-
|
32
|
-
|
33
|
-
|
40
|
+
def insert_array
|
41
|
+
params = attributes
|
42
|
+
.select { |attr| attr['attribute_type'] == 'array' }
|
43
|
+
.map { |attr| attr['attribute_name'] }
|
34
44
|
|
35
|
-
|
45
|
+
Localtower::Generators::ServiceObjects::InsertArray.new(params).call
|
36
46
|
end
|
37
47
|
|
38
|
-
|
48
|
+
def insert_default_values
|
49
|
+
params = attributes
|
50
|
+
.reject { |attr| attr['default'] == nil }
|
51
|
+
.reject { |attr| attr['default'] == '' }
|
52
|
+
.each_with_object([]) do |attr, arr|
|
53
|
+
arr << Hash[attr['attribute_name'], attr['default']]
|
54
|
+
end
|
39
55
|
|
40
|
-
|
41
|
-
@opts['attributes'].any? { |attr| attr["defaults"].present? }
|
56
|
+
Localtower::Generators::ServiceObjects::InsertDefaults.new(params).call
|
42
57
|
end
|
43
58
|
|
44
|
-
def
|
45
|
-
|
46
|
-
|
47
|
-
|
59
|
+
def insert_non_nullable_values
|
60
|
+
params = attributes
|
61
|
+
.select { |attr| attr['nullable'] == false }
|
62
|
+
.map{ |attr| attr['attribute_name'] }
|
63
|
+
|
64
|
+
::Localtower::Generators::ServiceObjects::InsertNullable.new(params).call
|
48
65
|
end
|
49
66
|
|
50
|
-
def
|
51
|
-
|
67
|
+
def insert_indexes
|
68
|
+
params = attributes
|
69
|
+
.select { |attr| attr.dig('index', 'using').present? }
|
70
|
+
.reject { |attr| attr.dig('index', 'using') == 'none' }
|
71
|
+
.each_with_object([]) do |attr, arr|
|
72
|
+
arr << Hash[attr['attribute_name'], attr['index']]
|
73
|
+
end
|
74
|
+
|
75
|
+
::Localtower::Generators::ServiceObjects::InsertIndexes.new(params).call
|
52
76
|
end
|
53
77
|
end
|
54
78
|
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
module Localtower
|
2
|
+
module Generators
|
3
|
+
module ServiceObjects
|
4
|
+
class InsertArray
|
5
|
+
def initialize(attributes)
|
6
|
+
@attributes = attributes
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
attributes.each do |attribute|
|
11
|
+
line_str = File.read(Localtower::Tools.last_migration).match(/((.*)t\.string :#{attribute})/)[0]
|
12
|
+
content = File.read(Localtower::Tools.last_migration).gsub(line_str, "#{line_str}, array: true")
|
13
|
+
File.write(Localtower::Tools.last_migration, content)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
private
|
18
|
+
|
19
|
+
attr_reader :attributes
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|