Module: BetterAuth::Rails::Migration
- Defined in:
- lib/better_auth/rails/migration.rb
Constant Summary collapse
- BOUNDED_STRING_LIMIT =
191
Class Method Summary collapse
- .active_record_connection ⇒ Object
- .active_record_dialect(connection) ⇒ Object
- .add_column_lines(change, dialect: :rails) ⇒ Object
- .bounded_string?(logical_field, attributes) ⇒ Boolean
- .column_line(logical_field, attributes, dialect: :rails) ⇒ Object
- .column_options(logical_field, attributes) ⇒ Object
- .create_table_lines(table, dialect: :rails) ⇒ Object
- .current_schema(connection) ⇒ Object
- .default_value(attributes) ⇒ Object
- .foreign_key_lines(table, options) ⇒ Object
- .foreign_key_target_field(reference, target_table) ⇒ Object
- .foreign_key_target_table(reference, tables) ⇒ Object
- .index_line(table_name, column, unique: false) ⇒ Object
- .index_lines(table) ⇒ Object
- .limited_string?(logical_field, attributes) ⇒ Boolean
- .migration_version ⇒ Object
- .physical_name(value) ⇒ Object
- .plan_pending(options, connection: active_record_connection) ⇒ Object
- .primary_key_options(table, dialect: :rails) ⇒ Object
- .rails_type(logical_field, attributes, dialect = :rails) ⇒ Object
- .render(options, migration_version: nil, dialect: nil) ⇒ Object
- .render_pending(plan, class_name: "UpdateBetterAuthTables", migration_version: nil) ⇒ Object
- .table_map(options) ⇒ Object
Class Method Details
.active_record_connection ⇒ Object
61 62 63 64 65 |
# File 'lib/better_auth/rails/migration.rb', line 61 def active_record_connection ::ActiveRecord::Base.connection if defined?(::ActiveRecord::Base) rescue nil end |
.active_record_dialect(connection) ⇒ Object
67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 |
# File 'lib/better_auth/rails/migration.rb', line 67 def active_record_dialect(connection) adapter = connection.respond_to?(:adapter_name) ? connection.adapter_name.to_s.downcase : "" case adapter when /postgres/ :postgres when /mysql/ :mysql when /sqlite/ :sqlite when /sqlserver|sql_server|mssql/ :mssql else :postgres end end |
.add_column_lines(change, dialect: :rails) ⇒ Object
160 161 162 163 164 165 166 167 |
# File 'lib/better_auth/rails/migration.rb', line 160 def add_column_lines(change, dialect: :rails) change.fields.map do |logical_field, attributes| column = attributes[:field_name] || physical_name(logical_field) parts = [" add_column :#{change.table_name}, :#{column}, :#{rails_type(logical_field, attributes, dialect)}"] parts.concat((logical_field, attributes)) parts.join(", ") end end |
.bounded_string?(logical_field, attributes) ⇒ Boolean
202 203 204 205 206 207 208 209 210 |
# File 'lib/better_auth/rails/migration.rb', line 202 def bounded_string?(logical_field, attributes) logical_field.to_s == "id" || logical_field.to_s.end_with?("Id") || attributes[:unique] || attributes[:index] || attributes[:sortable] || attributes[:references] || attributes.key?(:default_value) end |
.column_line(logical_field, attributes, dialect: :rails) ⇒ Object
129 130 131 132 133 134 135 136 137 138 139 |
# File 'lib/better_auth/rails/migration.rb', line 129 def column_line(logical_field, attributes, dialect: :rails) column = attributes[:field_name] || physical_name(logical_field) type = rails_type(logical_field, attributes, dialect) parts = if type == "timestamptz" ["t.column :#{column}, :timestamptz"] else ["t.#{type} :#{column}"] end parts.concat((logical_field, attributes)) " #{parts.join(", ")}" end |
.column_options(logical_field, attributes) ⇒ Object
141 142 143 144 145 146 147 148 |
# File 'lib/better_auth/rails/migration.rb', line 141 def (logical_field, attributes) parts = [] parts << "limit: #{BOUNDED_STRING_LIMIT}" if limited_string?(logical_field, attributes) parts << "null: false" if attributes[:required] default = default_value(attributes) parts << "default: #{default}" unless default.nil? parts end |
.create_table_lines(table, dialect: :rails) ⇒ Object
107 108 109 110 111 112 113 114 115 116 |
# File 'lib/better_auth/rails/migration.rb', line 107 def create_table_lines(table, dialect: :rails) table_name = table.fetch(:model_name) lines = ["", " create_table :#{table_name}, #{(table, dialect: dialect)} do |t|"] table.fetch(:fields).each do |logical_field, attributes| next if logical_field == "id" lines << column_line(logical_field, attributes, dialect: dialect) end lines << " end" end |
.current_schema(connection) ⇒ Object
83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/better_auth/rails/migration.rb', line 83 def current_schema(connection) connection.tables.each_with_object({}) do |table_name, schema| columns = connection.columns(table_name).each_with_object({}) do |column, result| result[column.name.to_s] = column.respond_to?(:sql_type) ? column.sql_type.to_s : column.type.to_s end indexes = {names: Set.new, columns: Set.new, unique_columns: Set.new} connection.indexes(table_name).each do |index| indexes[:names] << index.name.to_s Array(index.columns).each do |column| column = column.to_s indexes[:columns] << column indexes[:unique_columns] << column if index.unique end end schema[table_name.to_s] = {name: table_name.to_s, columns: columns, indexes: indexes} end end |
.default_value(attributes) ⇒ Object
216 217 218 219 220 221 222 223 224 225 226 |
# File 'lib/better_auth/rails/migration.rb', line 216 def default_value(attributes) default = attributes[:default_value] return if default.respond_to?(:call) case default when true then "true" when false then "false" when Numeric then default.to_s when String then default.inspect end end |
.foreign_key_lines(table, options) ⇒ Object
174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 |
# File 'lib/better_auth/rails/migration.rb', line 174 def foreign_key_lines(table, ) table_name = table.fetch(:model_name) tables = table_map() table.fetch(:fields).filter_map do |logical_field, attributes| reference = attributes[:references] next unless reference column = attributes[:field_name] || physical_name(logical_field) target_table = foreign_key_target_table(reference, tables) target = target_table&.fetch(:model_name) || reference.fetch(:model) target_field = foreign_key_target_field(reference, target_table) primary_key = (target_field.to_s == "id") ? "" : ", primary_key: :#{target_field}" on_delete = reference[:on_delete] ? ", on_delete: :#{reference[:on_delete]}" : "" " add_foreign_key :#{table_name}, :#{target}, column: :#{column}#{primary_key}#{on_delete}" end end |
.foreign_key_target_field(reference, target_table) ⇒ Object
245 246 247 248 249 250 251 252 253 254 255 256 257 258 |
# File 'lib/better_auth/rails/migration.rb', line 245 def foreign_key_target_field(reference, target_table) field = reference.fetch(:field).to_s return field unless target_table fields = target_table.fetch(:fields) attributes = fields.fetch(field, nil) return attributes[:field_name] || physical_name(field) if attributes if fields.each_value.any? { |data| data[:field_name].to_s == field } field else physical_name(field) end end |
.foreign_key_target_table(reference, tables) ⇒ Object
240 241 242 243 |
# File 'lib/better_auth/rails/migration.rb', line 240 def foreign_key_target_table(reference, tables) model = reference.fetch(:model).to_s tables.fetch(model, nil) || tables.each_value.find { |table| table.fetch(:model_name).to_s == model } end |
.index_line(table_name, column, unique: false) ⇒ Object
169 170 171 172 |
# File 'lib/better_auth/rails/migration.rb', line 169 def index_line(table_name, column, unique: false) unique_option = unique ? ", unique: true" : "" " add_index :#{table_name}, :#{column}#{unique_option}" end |
.index_lines(table) ⇒ Object
150 151 152 153 154 155 156 157 158 |
# File 'lib/better_auth/rails/migration.rb', line 150 def index_lines(table) table_name = table.fetch(:model_name) table.fetch(:fields).filter_map do |logical_field, attributes| next unless attributes[:unique] || attributes[:index] column = attributes[:field_name] || physical_name(logical_field) index_line(table_name, column, unique: attributes[:unique]) end end |
.limited_string?(logical_field, attributes) ⇒ Boolean
212 213 214 |
# File 'lib/better_auth/rails/migration.rb', line 212 def limited_string?(logical_field, attributes) attributes[:type] == "string" && bounded_string?(logical_field, attributes) end |
.migration_version ⇒ Object
101 102 103 104 105 |
# File 'lib/better_auth/rails/migration.rb', line 101 def migration_version return ::ActiveRecord::Migration.current_version if defined?(::ActiveRecord::Migration) "7.0" end |
.physical_name(value) ⇒ Object
228 229 230 |
# File 'lib/better_auth/rails/migration.rb', line 228 def physical_name(value) BetterAuth::Schema.send(:physical_name, value) end |
.plan_pending(options, connection: active_record_connection) ⇒ Object
52 53 54 55 56 57 58 59 |
# File 'lib/better_auth/rails/migration.rb', line 52 def plan_pending(, connection: active_record_connection) dialect = active_record_dialect(connection) BetterAuth::SQLMigration.plan_from_existing( , existing: current_schema(connection), dialect: dialect ) end |
.primary_key_options(table, dialect: :rails) ⇒ Object
118 119 120 121 122 123 124 125 126 127 |
# File 'lib/better_auth/rails/migration.rb', line 118 def (table, dialect: :rails) attributes = table.fetch(:fields)["id"] return "id: false" unless attributes column = attributes[:field_name] || physical_name("id") parts = ["id: :#{rails_type("id", attributes, dialect)}"] parts << "limit: #{BOUNDED_STRING_LIMIT}" if limited_string?("id", attributes) parts << "primary_key: :#{column}" unless column == "id" parts.join(", ") end |
.rails_type(logical_field, attributes, dialect = :rails) ⇒ Object
191 192 193 194 195 196 197 198 199 200 |
# File 'lib/better_auth/rails/migration.rb', line 191 def rails_type(logical_field, attributes, dialect = :rails) case attributes[:type] when "boolean" then "boolean" when "date" then (dialect == :postgres) ? "timestamptz" : "datetime" when "number" then attributes[:bigint] ? "bigint" : "integer" when "json", "string[]", "number[]" then (dialect == :postgres) ? "jsonb" : "json" when "string" then bounded_string?(logical_field, attributes) ? "string" : "text" else "text" end end |
.render(options, migration_version: nil, dialect: nil) ⇒ Object
12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 |
# File 'lib/better_auth/rails/migration.rb', line 12 def render(, migration_version: nil, dialect: nil) migration_version ||= self.migration_version dialect ||= active_record_connection ? active_record_dialect(active_record_connection) : :rails tables = BetterAuth::Schema.auth_tables() lines = [ "# frozen_string_literal: true", "", "class CreateBetterAuthTables < ActiveRecord::Migration[#{migration_version}]", " def change" ] tables.each_value { |table| lines.concat(create_table_lines(table, dialect: dialect)) } tables.each_value { |table| lines.concat(index_lines(table)) } tables.each_value { |table| lines.concat(foreign_key_lines(table, )) } lines.concat([" end", "end", ""]) lines.join("\n") end |
.render_pending(plan, class_name: "UpdateBetterAuthTables", migration_version: nil) ⇒ Object
29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 |
# File 'lib/better_auth/rails/migration.rb', line 29 def render_pending(plan, class_name: "UpdateBetterAuthTables", migration_version: nil) migration_version ||= self.migration_version created_tables = plan.to_create.map(&:table_name).to_set lines = [ "# frozen_string_literal: true", "", "class #{class_name} < ActiveRecord::Migration[#{migration_version}]", " def change" ] plan.to_create.each { |change| lines.concat(create_table_lines(change.table, dialect: plan.dialect)) } plan.to_create.each { |change| lines.concat(index_lines(change.table)) } plan.to_create.each { |change| lines.concat(foreign_key_lines(change.table, plan.tables)) } plan.to_add.each { |change| lines.concat(add_column_lines(change, dialect: plan.dialect)) } plan.to_index.reject { |change| created_tables.include?(change.table_name) }.each do |change| lines << index_line(change.table_name, change.field_name, unique: change.unique) end plan.to_add.each do |change| lines.concat(foreign_key_lines({model_name: change.table_name, fields: change.fields}, plan.tables)) end lines.concat([" end", "end", ""]) lines.join("\n") end |
.table_map(options) ⇒ Object
232 233 234 235 236 237 238 |
# File 'lib/better_auth/rails/migration.rb', line 232 def table_map() if .respond_to?(:values) && .values.all? { |value| value.respond_to?(:fetch) && value.key?(:fields) } else BetterAuth::Schema.auth_tables() end end |