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.
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