Class: SlashMigrate::MigrationBuilder
- Inherits:
-
Object
- Object
- SlashMigrate::MigrationBuilder
- Defined in:
- app/services/slash_migrate/migration_builder.rb
Overview
Builds the migration (and model) for a brand-new table from a column plan. Unlike the old generator-backed path, this emits the Ruby itself, so it can express options the ‘rails g` grammar can’t (null:, default:). A create_table migration is always reversible, so the output is a plain ‘def change`.
Fidelity with Rails’ own output is guarded by a spec that diffs this against ‘rails g model` for the subset both can express.
Constant Summary collapse
- SELF_TABLE =
The “references table” picker uses this sentinel for a self-reference, since the table being created doesn’t exist to list yet. We resolve it to the new table’s name here, where it’s known.
"__self__".freeze
Instance Attribute Summary collapse
-
#name ⇒ Object
readonly
Returns the value of attribute name.
Class Method Summary collapse
Instance Method Summary collapse
-
#initialize(name:, columns: []) ⇒ MigrationBuilder
constructor
A new instance of MigrationBuilder.
- #migration_basename ⇒ Object
- #migration_class_name ⇒ Object
- #migration_source ⇒ Object
- #model_class_name ⇒ Object
- #model_filename ⇒ Object
- #model_source ⇒ Object
- #name_present? ⇒ Boolean
-
#pluralized_input? ⇒ Boolean
True when the input was plural and we singularized it, so the UI can warn.
-
#table_name ⇒ Object
A model is singular and its table plural, whatever the student typed.
-
#write! ⇒ Object
Writes the migration and model into the host app.
Constructor Details
#initialize(name:, columns: []) ⇒ MigrationBuilder
Returns a new instance of MigrationBuilder.
30 31 32 33 |
# File 'app/services/slash_migrate/migration_builder.rb', line 30 def initialize(name:, columns: []) @name = name.to_s.strip @columns = columns.reject(&:blank?) end |
Instance Attribute Details
#name ⇒ Object (readonly)
Returns the value of attribute name.
28 29 30 |
# File 'app/services/slash_migrate/migration_builder.rb', line 28 def name @name end |
Class Method Details
.from_params(name:, rows:) ⇒ Object
15 16 17 18 19 |
# File 'app/services/slash_migrate/migration_builder.rb', line 15 def self.from_params(name:, rows:) table = name.to_s.strip.underscore.pluralize columns = Array(rows).map { |row| Column.from_params(resolve_self_reference(row, table)) } new(name: name, columns: columns) end |
.resolve_self_reference(row, table) ⇒ Object
21 22 23 24 25 26 |
# File 'app/services/slash_migrate/migration_builder.rb', line 21 def self.resolve_self_reference(row, table) return row unless row[:to_table].to_s == SELF_TABLE hash = row.respond_to?(:to_unsafe_h) ? row.to_unsafe_h : row.to_h hash.symbolize_keys.merge(to_table: table) end |
Instance Method Details
#migration_basename ⇒ Object
60 61 62 |
# File 'app/services/slash_migrate/migration_builder.rb', line 60 def migration_basename "create_#{table_name}" end |
#migration_class_name ⇒ Object
56 57 58 |
# File 'app/services/slash_migrate/migration_builder.rb', line 56 def migration_class_name "Create#{table_name.camelize}" end |
#migration_source ⇒ Object
68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'app/services/slash_migrate/migration_builder.rb', line 68 def migration_source lines = [] lines << "class #{migration_class_name} < ActiveRecord::Migration[#{ActiveRecord::Migration.current_version}]" lines << " def change" lines << " create_table :#{table_name} do |t|" @columns.each { |column| lines << " #{column.to_ruby}" } lines << "" lines << " t.timestamps" lines << " end" index_columns.each { |column| lines << " #{column.index_statement(table_name)}" } lines << " end" lines << "end" lines.join("\n") + "\n" end |
#model_class_name ⇒ Object
47 48 49 |
# File 'app/services/slash_migrate/migration_builder.rb', line 47 def model_class_name name.classify end |
#model_filename ⇒ Object
64 65 66 |
# File 'app/services/slash_migrate/migration_builder.rb', line 64 def model_filename "#{name.classify.underscore}.rb" end |
#model_source ⇒ Object
83 84 85 86 87 88 |
# File 'app/services/slash_migrate/migration_builder.rb', line 83 def model_source lines = ["class #{model_class_name} < ApplicationRecord"] reference_columns.each { |column| lines << " #{column.belongs_to_line}" } lines << "end" lines.join("\n") + "\n" end |
#name_present? ⇒ Boolean
35 36 37 |
# File 'app/services/slash_migrate/migration_builder.rb', line 35 def name_present? !name.empty? end |
#pluralized_input? ⇒ Boolean
True when the input was plural and we singularized it, so the UI can warn.
52 53 54 |
# File 'app/services/slash_migrate/migration_builder.rb', line 52 def pluralized_input? name.present? && name != name.singularize end |
#table_name ⇒ Object
A model is singular and its table plural, whatever the student typed. classify and tableize are the same inflections Active Record uses to map between a model and its table, so “Articles”, “articles”, and “Article” all yield the Article model on the articles table.
43 44 45 |
# File 'app/services/slash_migrate/migration_builder.rb', line 43 def table_name name.tableize end |
#write! ⇒ Object
Writes the migration and model into the host app. Skips an existing model file rather than clobbering it. Returns the paths written, relative to root.
92 93 94 95 96 97 98 99 100 101 102 103 |
# File 'app/services/slash_migrate/migration_builder.rb', line 92 def write! written = [MigrationFileWriter.write(basename: migration_basename, source: migration_source)] model_path = Rails.root.join("app/models", model_filename) unless model_path.exist? model_path.dirname.mkpath # a namespaced model (app/models/admin/…) may need its dir File.write(model_path, model_source) written << model_path.relative_path_from(Rails.root).to_s end written end |