localtower 0.5.0 → 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.
- 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
|