localtower 0.5.0 → 1.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (61) hide show
  1. checksums.yaml +4 -4
  2. data/README.md +25 -17
  3. data/app/controllers/localtower/pages_controller.rb +27 -12
  4. data/app/views/layouts/localtower/application.html.erb +16 -33
  5. data/app/views/localtower/pages/_alert_no_models.html.erb +3 -0
  6. data/app/views/localtower/pages/migrations.html.erb +52 -83
  7. data/app/views/localtower/pages/models.html.erb +53 -70
  8. data/app/views/localtower/pages/new_migration.html.erb +103 -0
  9. data/app/views/localtower/pages/new_model.html.erb +87 -0
  10. data/config/routes.rb +4 -4
  11. data/lib/localtower/generators/migration.rb +51 -120
  12. data/lib/localtower/generators/model.rb +52 -28
  13. data/lib/localtower/generators/service_objects/insert_array.rb +23 -0
  14. data/lib/localtower/generators/service_objects/insert_defaults.rb +15 -43
  15. data/lib/localtower/generators/service_objects/insert_indexes.rb +80 -0
  16. data/lib/localtower/generators/service_objects/insert_nullable.rb +23 -0
  17. data/lib/localtower/status.rb +1 -1
  18. data/lib/localtower/tools.rb +13 -16
  19. data/lib/localtower/version.rb +1 -1
  20. data/public/css/app.css +0 -49
  21. data/public/js/app.js +215 -70
  22. data/public/screenshots/v1.0.0/migrations.png +0 -0
  23. data/public/screenshots/v1.0.0/models.png +0 -0
  24. data/public/screenshots/v1.0.0/new_migration.png +0 -0
  25. data/public/screenshots/v1.0.0/new_model.png +0 -0
  26. data/spec/dummy/Gemfile +0 -2
  27. data/spec/dummy/Gemfile.lock +1 -10
  28. data/spec/dummy/app/models/post.rb +3 -0
  29. data/spec/dummy/app/models/user.rb +1 -0
  30. data/spec/dummy/config/environments/development.rb +1 -0
  31. data/spec/dummy/config/puma.rb +1 -1
  32. data/spec/dummy/db/migrate/20230119221452_create_users.rb +14 -0
  33. data/spec/dummy/db/migrate/20230119221751_change_users_at1674166670.rb +7 -0
  34. data/spec/dummy/db/migrate/20230119222054_create_posts.rb +11 -0
  35. data/spec/dummy/db/migrate/20230119222106_change_posts_at1674166865.rb +5 -0
  36. data/spec/dummy/db/schema.rb +20 -8
  37. data/spec/dummy/log/development.log +15281 -3345
  38. data/spec/dummy/log/localtower.log +1897 -132
  39. data/spec/dummy/log/test.log +0 -0
  40. data/spec/dummy/test/index.html +38 -0
  41. data/spec/dummy/tmp/pids/server.pid +1 -0
  42. data/spec/factories/migration.rb +25 -41
  43. data/spec/factories/model.rb +39 -25
  44. data/spec/lib/localtower/generators/migration_spec.rb +36 -63
  45. data/spec/lib/localtower/generators/model_spec.rb +43 -34
  46. data/spec/lib/localtower/generators/service_objects/insert_array_spec.rb +47 -0
  47. data/spec/lib/localtower/generators/service_objects/insert_defaults_spec.rb +30 -35
  48. data/spec/lib/localtower/generators/service_objects/insert_indexes_spec.rb +90 -0
  49. data/spec/lib/localtower/generators/service_objects/insert_nullable_spec.rb +61 -0
  50. data/spec/lib/localtower/tools_spec.rb +1 -11
  51. data/spec/spec_helper.rb +8 -3
  52. metadata +34 -18
  53. data/app/views/localtower/pages/_migrations.html.erb +0 -57
  54. data/app/views/localtower/pages/schema.html.erb +0 -67
  55. data/spec/dummy/db/migrate/20221115190039_create_users.rb +0 -13
  56. data/spec/dummy/db/migrate/20221115193020_change_users.rb +0 -8
  57. data/spec/dummy/db/migrate/20221115193532_change_users_at1668540931.rb +0 -5
  58. data/spec/dummy/db/migrate/20221115193605_change_users_at1668540964.rb +0 -5
  59. data/spec/dummy/db/migrate/20221115193637_change_users_at1668540996.rb +0 -5
  60. data/spec/dummy/db/migrate/20221115193642_change_users_at1668541001.rb +0 -5
  61. 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
- # get ':v/:asset', to: 'pages#asset_render', as: 'asset_render', :constraints => { :v => /[^\/]*/, :asset => /[^\/]*/ }
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(array).include?(data["column_type"])
14
- line = " add_column :#{data['table_name']}, :#{data['column']}, :text"
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 not data['nullable']
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
- file = data['last_migration_file']
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
- # # add_index :relationships, [:follower_id, :followed_id], unique: true
70
- # line = " add_index :#{data["table_name"]}, [#{attr_names.map { |i| ":#{i}"}.join(', ')}]"
71
- # line << ", unique: true" if data["unique"]
72
- # line << "\n"
73
-
74
- # inject_in_migration(file, line)
75
- # end
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
- file = data["last_migration_file"]
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
- file = data["last_migration_file"]
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["table_name"].underscore.singularize}.rb"
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["column"].singularize.underscore}\n"
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["column"].underscore.singularize}.rb"
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["table_name"].pluralize.underscore}\n"
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
- inject_in_migration(file, line)
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
- file = data["last_migration_file"]
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, after: "def change\n")
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(string datetime text uuid integer float json jsonb decimal binary boolean array references).freeze
132
- ACTIONS = [
133
- 'add_column',
134
- 'remove_column',
135
- 'rename_column',
136
- 'change_column_type',
137
- 'add_index_to_column',
138
- 'belongs_to',
139
- 'remove_index_to_column',
140
- 'drop_table',
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(opts)
118
+ def initialize(migrations)
149
119
  @thor = ThorGeneratorMigration.new
150
- @opts = JSON[opts.to_json]
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 = @opts['migrations'].map { |line| line['table_name'].camelize }.join
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
- @opts['migrations'].each do |action_line|
162
- next unless action_line['action'].present?
126
+ cmd = "Change#{model_names}At#{Time.now.to_i}"
127
+ ::Localtower::Tools.perform_migration(cmd)
163
128
 
164
- # table_name = action_line['table_name']
165
- # column = action_line['column']
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
- }[action_line['action'].downcase].call
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
- return nil if @opts['attributes'].blank?
11
- return nil if @opts['model_name'].blank?
12
-
13
- attributes_list = []
14
+ attributes_str = parse_attributes.join(" ")
15
+ cmd = "rails generate model #{model_name.camelize} #{attributes_str}"
14
16
 
15
- @opts['attributes'].each do |attribute_data|
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
- attributes_list << str
20
- end
19
+ insert_non_nullable_values
20
+ insert_default_values
21
+ insert_array
22
+ insert_indexes
23
+ end
21
24
 
22
- attributes_str = attributes_list.join(" ")
23
- cmd = "rails g model #{@opts['model_name'].camelize} #{attributes_str}"
25
+ private
24
26
 
25
- ::Localtower::Tools.perform_cmd(cmd, false)
27
+ attr_reader :model_name
28
+ attr_reader :attributes
26
29
 
27
- if defaults_present?
28
- insert_default_values.call
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
- if @opts['run_migrate']
32
- ::Localtower::Tools.perform_cmd('rake db:migrate', false)
33
- end
40
+ def insert_array
41
+ params = attributes
42
+ .select { |attr| attr['attribute_type'] == 'array' }
43
+ .map { |attr| attr['attribute_name'] }
34
44
 
35
- self
45
+ Localtower::Generators::ServiceObjects::InsertArray.new(params).call
36
46
  end
37
47
 
38
- private
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
- def defaults_present?
41
- @opts['attributes'].any? { |attr| attr["defaults"].present? }
56
+ Localtower::Generators::ServiceObjects::InsertDefaults.new(params).call
42
57
  end
43
58
 
44
- def params_for_defaults
45
- @opts['attributes'].each_with_object([]) do |attr, arr|
46
- arr << Hash[ attr['attribute_name'], attr['defaults'] ] unless attr['defaults'].empty?
47
- end
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 insert_default_values
51
- ::Localtower::Generators::ServiceObjects::InsertDefaults.new(params_for_defaults)
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