Enforce column limits via concern

SQLite columns lengths are purely informational, so we'll enforce the
limits via a concern that checks the lengths from the schema.
This commit is contained in:
Donal McBreen
2025-11-25 15:29:42 +00:00
parent 67f648f356
commit 97bcdf1853
5 changed files with 134 additions and 15 deletions
@@ -1,4 +1,4 @@
# Apply MySQL-compatible column limits when using SQLite.
# Apply MySQL-compatible column limits when defining tables.
#
# For string columns: defaults to 255 (MySQL's VARCHAR default)
#
@@ -7,17 +7,19 @@
# - size: :tiny: 255 (TINYTEXT)
# - size: :medium: 16,777,215 (MEDIUMTEXT)
# - size: :long: 4,294,967,295 (LONGTEXT)
#
# This ensures the SQLite schema records the same limits as MySQL,
# which the ColumnLimits validation concern uses to enforce limits.
module TableDefinitionColumnLimits
# Map MySQL size options to limits
TEXT_SIZE_TO_LIMIT = {
tiny: 255, # TINYTEXT
medium: 16_777_215, # MEDIUMTEXT
long: 4_294_967_295 # LONGTEXT
tiny: 255,
medium: 16_777_215,
long: 4_294_967_295
}.freeze
TEXT_DEFAULT_LIMIT = 65_535 # TEXT
STRING_DEFAULT_LIMIT = 255 # VARCHAR
TEXT_DEFAULT_LIMIT = 65_535
STRING_DEFAULT_LIMIT = 255
def column(name, type, **options)
if type == :string
@@ -27,16 +29,11 @@ module TableDefinitionColumnLimits
if type == :text
if options.key?(:size)
size = options.delete(:size)
options[:limit] = TEXT_SIZE_TO_LIMIT.fetch(size) do
options[:limit] ||= TEXT_SIZE_TO_LIMIT.fetch(size) do
raise ArgumentError, "Unknown text size: #{size.inspect}. Use :tiny, :medium, or :long"
end
elsif options.key?(:limit)
valid_limits = [TEXT_DEFAULT_LIMIT] + TEXT_SIZE_TO_LIMIT.values
unless valid_limits.include?(options[:limit])
raise ArgumentError, "Invalid limit #{options[:limit]} for text column. Use `size:` (:tiny, :medium, :long) or omit for default TEXT."
end
else
options[:limit] = TEXT_DEFAULT_LIMIT
options[:limit] ||= TEXT_DEFAULT_LIMIT
end
end
@@ -47,3 +44,15 @@ end
ActiveSupport.on_load(:active_record) do
ActiveRecord::ConnectionAdapters::TableDefinition.prepend(TableDefinitionColumnLimits)
end
ActiveSupport.on_load(:action_text_rich_text) do
include ColumnLimits
end
ActiveSupport.on_load(:active_storage_blob) do
include ColumnLimits
end
ActiveSupport.on_load(:active_storage_attachment) do
include ColumnLimits
end