Module: BetterAuth::Hanami::Migration
- Defined in:
- lib/better_auth/hanami/migration.rb
Class Method Summary collapse
- .add_column_line(logical_field, attributes, tables) ⇒ Object
- .alter_table_index_lines(change) ⇒ Object
- .alter_table_lines(change, tables) ⇒ Object
- .auth_tables_for(options_or_tables) ⇒ Object
- .column_line(logical_field, attributes, options) ⇒ Object
- .create_table_lines(table, options) ⇒ Object
- .current_schema(connection) ⇒ Object
- .default_hanami_database?(database) ⇒ Boolean
- .default_value(attributes) ⇒ Object
- .foreign_key_line(command, logical_field, attributes, options_or_tables) ⇒ Object
- .foreign_key_target(reference, options_or_tables) ⇒ Object
- .foreign_key_target_field(reference, table) ⇒ Object
- .hanami_type(attributes) ⇒ Object
- .index_line(logical_field, attributes) ⇒ Object
- .physical_name(value) ⇒ Object
- .plan_pending(options) ⇒ Object
- .render(options) ⇒ Object
- .render_pending(plan) ⇒ Object
- .sequel_dialect(connection) ⇒ Object
Class Method Details
.add_column_line(logical_field, attributes, tables) ⇒ Object
151 152 153 154 155 156 157 158 159 160 |
# File 'lib/better_auth/hanami/migration.rb', line 151 def add_column_line(logical_field, attributes, tables) return foreign_key_line("add_foreign_key", logical_field, attributes, tables) if attributes[:references] column = attributes[:field_name] || physical_name(logical_field) parts = ["add_column :#{column}", hanami_type(attributes)] parts << "null: false" if attributes[:required] default = default_value(attributes) parts << "default: #{default}" unless default.nil? " #{parts.join(", ")}" end |
.alter_table_index_lines(change) ⇒ Object
162 163 164 165 166 167 168 169 170 |
# File 'lib/better_auth/hanami/migration.rb', line 162 def alter_table_index_lines(change) unique = change.unique ? ", unique: true" : "" [ "", " alter_table :#{change.table_name} do", " add_index :#{change.field_name}#{unique}", " end" ] end |
.alter_table_lines(change, tables) ⇒ Object
142 143 144 145 146 147 148 149 |
# File 'lib/better_auth/hanami/migration.rb', line 142 def alter_table_lines(change, tables) lines = ["", " alter_table :#{change.table_name} do"] change.fields.each do |logical_field, attributes| lines << add_column_line(logical_field, attributes, tables) end lines << " end" lines end |
.auth_tables_for(options_or_tables) ⇒ Object
224 225 226 227 228 229 230 |
# File 'lib/better_auth/hanami/migration.rb', line 224 def auth_tables_for() if .is_a?(Hash) && .values.all? { |value| value.is_a?(Hash) && value.key?(:fields) && value.key?(:model_name) } else BetterAuth::Schema.auth_tables() end end |
.column_line(logical_field, attributes, options) ⇒ Object
123 124 125 126 127 128 129 130 131 132 |
# File 'lib/better_auth/hanami/migration.rb', line 123 def column_line(logical_field, attributes, ) return foreign_key_line("foreign_key", logical_field, attributes, ) if attributes[:references] column = attributes[:field_name] || physical_name(logical_field) parts = ["column :#{column}", hanami_type(attributes)] parts << "null: false" if attributes[:required] default = default_value(attributes) parts << "default: #{default}" unless default.nil? " #{parts.join(", ")}" end |
.create_table_lines(table, options) ⇒ Object
108 109 110 111 112 113 114 115 116 117 118 119 120 121 |
# File 'lib/better_auth/hanami/migration.rb', line 108 def create_table_lines(table, ) table_name = table.fetch(:model_name) lines = ["", " create_table :#{table_name} do"] table.fetch(:fields).each do |logical_field, attributes| lines << column_line(logical_field, attributes, ) end lines << " primary_key [:id]" if table.fetch(:fields).key?("id") table.fetch(:fields).each do |logical_field, attributes| index = index_line(logical_field, attributes) lines << index if index end lines << " end" lines end |
.current_schema(connection) ⇒ Object
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 |
# File 'lib/better_auth/hanami/migration.rb', line 82 def current_schema(connection) connection.tables.each_with_object({}) do |table_name, schema| columns = connection.schema(table_name).each_with_object({}) do |entry, result| column, = entry result[column.to_s] = ([:db_type] || [:type]).to_s end indexes = {names: Set.new, columns: Set.new, unique_columns: Set.new} connection.indexes(table_name).each do |name, | indexes[:names] << name.to_s Array([:columns]).each do |column| column = column.to_s indexes[:columns] << column indexes[:unique_columns] << column if [:unique] end end schema[table_name.to_s] = {name: table_name.to_s, columns: columns, indexes: indexes} end end |
.default_hanami_database?(database) ⇒ Boolean
101 102 103 104 105 106 |
# File 'lib/better_auth/hanami/migration.rb', line 101 def default_hanami_database?(database) return false unless database.respond_to?(:source_location) path, = database.source_location path.to_s.end_with?("better_auth/hanami/configuration.rb") end |
.default_value(attributes) ⇒ Object
182 183 184 185 186 187 188 189 190 191 192 |
# File 'lib/better_auth/hanami/migration.rb', line 182 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_line(command, logical_field, attributes, options_or_tables) ⇒ Object
194 195 196 197 198 199 200 201 202 203 |
# File 'lib/better_auth/hanami/migration.rb', line 194 def foreign_key_line(command, logical_field, attributes, ) column = attributes[:field_name] || physical_name(logical_field) reference = attributes.fetch(:references) target, target_key = foreign_key_target(reference, ) parts = ["#{command} :#{column}, :#{target}", "type: #{hanami_type(attributes)}"] parts << "null: false" if attributes[:required] parts << "key: :#{target_key}" unless target_key == "id" parts << "on_delete: :#{reference[:on_delete]}" if reference[:on_delete] " #{parts.join(", ")}" end |
.foreign_key_target(reference, options_or_tables) ⇒ Object
205 206 207 208 209 210 211 |
# File 'lib/better_auth/hanami/migration.rb', line 205 def foreign_key_target(reference, ) tables = auth_tables_for() model = reference.fetch(:model).to_s table = tables.fetch(model, nil) || tables.each_value.find { |candidate| candidate.fetch(:model_name).to_s == model } target = table&.fetch(:model_name) || model [target, foreign_key_target_field(reference, table)] end |
.foreign_key_target_field(reference, table) ⇒ Object
213 214 215 216 217 218 219 220 221 222 |
# File 'lib/better_auth/hanami/migration.rb', line 213 def foreign_key_target_field(reference, table) field = reference.fetch(:field).to_s return physical_name(field) unless table attributes = table.fetch(:fields).fetch(field, nil) return attributes[:field_name] || physical_name(field) if attributes return field if table.fetch(:fields).each_value.any? { |data| data[:field_name].to_s == field } physical_name(field) end |
.hanami_type(attributes) ⇒ Object
172 173 174 175 176 177 178 179 180 |
# File 'lib/better_auth/hanami/migration.rb', line 172 def hanami_type(attributes) case attributes[:type] when "boolean" then "TrueClass" when "date" then "DateTime" when "number" then attributes[:bigint] ? ":Bignum" : "Integer" when "json", "string[]", "number[]" then "JSON" else "String" end end |
.index_line(logical_field, attributes) ⇒ Object
134 135 136 137 138 139 140 |
# File 'lib/better_auth/hanami/migration.rb', line 134 def index_line(logical_field, attributes) return unless attributes[:unique] || attributes[:index] column = attributes[:field_name] || physical_name(logical_field) unique = attributes[:unique] ? ", unique: true" : "" " index :#{column}#{unique}" end |
.physical_name(value) ⇒ Object
232 233 234 235 236 237 |
# File 'lib/better_auth/hanami/migration.rb', line 232 def physical_name(value) value.to_s .gsub(/([a-z\d])([A-Z])/, "\\1_\\2") .tr("-", "_") .downcase end |
.plan_pending(options) ⇒ Object
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 |
# File 'lib/better_auth/hanami/migration.rb', line 46 def plan_pending() config = BetterAuth::SQLMigration.configuration_for() if config.database == :memory raise BetterAuth::SQLMigration::UnsupportedAdapterError, "Better Auth Hanami incremental migrations require a Sequel connection" end if default_hanami_database?(config.database) && !(defined?(::Hanami) && ::Hanami.respond_to?(:app)) raise BetterAuth::SQLMigration::UnsupportedAdapterError, "Better Auth Hanami incremental migrations require a Sequel connection" end auth = BetterAuth.auth(config.to_h) adapter = auth.context.adapter connection = adapter.connection if adapter.respond_to?(:connection) raise BetterAuth::SQLMigration::UnsupportedAdapterError, "Better Auth Hanami incremental migrations require a Sequel connection" unless connection BetterAuth::SQLMigration.plan_from_existing( config, existing: current_schema(connection), dialect: sequel_dialect(connection) ) end |
.render(options) ⇒ Object
10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 |
# File 'lib/better_auth/hanami/migration.rb', line 10 def render() tables = BetterAuth::Schema.auth_tables() lines = [ "# frozen_string_literal: true", "", "require \"date\"", "require \"rom-sql\"", "", "ROM::SQL.migration do", " change do" ] tables.each_value { |table| lines.concat(create_table_lines(table, )) } lines.concat([" end", "end", ""]) lines.join("\n") end |
.render_pending(plan) ⇒ Object
26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 |
# File 'lib/better_auth/hanami/migration.rb', line 26 def render_pending(plan) created_tables = plan.to_create.map(&:table_name).to_set lines = [ "# frozen_string_literal: true", "", "require \"date\"", "require \"rom-sql\"", "", "ROM::SQL.migration do", " change do" ] plan.to_create.each { |change| lines.concat(create_table_lines(change.table, plan.tables)) } plan.to_add.each { |change| lines.concat(alter_table_lines(change, plan.tables)) } plan.to_index.reject { |change| created_tables.include?(change.table_name) }.each do |change| lines.concat(alter_table_index_lines(change)) end lines.concat([" end", "end", ""]) lines.join("\n") end |
.sequel_dialect(connection) ⇒ Object
66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 |
# File 'lib/better_auth/hanami/migration.rb', line 66 def sequel_dialect(connection) type = connection.respond_to?(:database_type) ? connection.database_type.to_s : "" case type when /postgres/ :postgres when /mysql/ :mysql when /sqlite/ :sqlite when /mssql|sqlserver|sql_server/ :mssql else :postgres end end |