Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Cast UUIDs to downcase #59

Open
wants to merge 4 commits into
base: main
Choose a base branch
from
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
18 changes: 11 additions & 7 deletions lib/mysql-binuuid/type.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,13 +12,17 @@ def cast(value)
if value.is_a?(MySQLBinUUID::Type::Data)
# It could be a Data object, in which case we should add dashes to the
# string value from there.
add_dashes(value.to_s)
elsif value.is_a?(String) && value.encoding == Encoding::ASCII_8BIT && strip_dashes(value).length != 32
# We cannot unpack something that looks like a UUID, with or without
# dashes. Not entirely sure why ActiveRecord does a weird combination of
# cast and serialize before anything needs to be saved..
undashed_uuid = value.unpack1('H*')
add_dashes(undashed_uuid.to_s)
add_dashes(value.to_s.downcase)
elsif value.is_a?(String)
if value.encoding == Encoding::ASCII_8BIT && strip_dashes(value).length != 32
# We cannot unpack something that looks like a UUID, with or without
# dashes. Not entirely sure why ActiveRecord does a weird combination of
# cast and serialize before anything needs to be saved..
undashed_uuid = value.unpack1('H*')
add_dashes(undashed_uuid.to_s.downcase)
else
value.downcase
end
else
super
end
Expand Down
2 changes: 1 addition & 1 deletion lib/mysql-binuuid/version.rb
Original file line number Diff line number Diff line change
@@ -1,3 +1,3 @@
module MySQLBinUUID
VERSION = "1.3.0"
VERSION = "2.0.0"
end
55 changes: 55 additions & 0 deletions test/integration/mysql_integration_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,33 @@ class MyUuidModel < ActiveRecord::Base
attribute :the_uuid, MySQLBinUUID::Type.new
end

class UuidPkeyModel < ActiveRecord::Base
self.abstract_class = true

attribute :id, MySQLBinUUID::Type.new

after_initialize :set_id

private

def set_id
self.id ||= SecureRandom.uuid
end
end

class MyUuidModelWithValidations < MyUuidModel
validates :the_uuid, uniqueness: true
end

class UuidParent < UuidPkeyModel
has_many :uuid_children
end

class UuidChild < UuidPkeyModel
belongs_to :uuid_parent
attribute :uuid_parent_id, MySQLBinUUID::Type.new
end

class MySQLIntegrationTest < ActiveSupport::TestCase
def connection
ActiveRecord::Base.connection
Expand Down Expand Up @@ -35,6 +58,9 @@ def db_config
ActiveRecord::Base.establish_connection(db_config)
connection.create_table("my_uuid_models")
connection.add_column("my_uuid_models", "the_uuid", :binary, limit: 16)
connection.create_table('uuid_parents', id: 'binary(16)')
connection.create_table('uuid_children', id: 'binary(16)')
connection.add_columns('uuid_children', 'uuid_parent_id', type: 'binary(16)')

# Uncomment this line to get logging on stdout
# ActiveRecord::Base.logger = Logger.new(STDOUT)
Expand Down Expand Up @@ -122,5 +148,34 @@ class AfterPersistedTest < MySQLIntegrationTest
MyUuidModel.create!(the_uuid: "40' + x'40")
end
end

test "always downcases the user-supplied value" do
@my_model.the_uuid = @sample_uuid.upcase
assert_equal @sample_uuid, @my_model.the_uuid
end

test "treats case-only changes as non-dirtying" do
@my_model.the_uuid = @sample_uuid.upcase
assert_equal false, @my_model.will_save_change_to_the_uuid?
end
end

class ComplexRelationTest < MySQLIntegrationTest
setup do
@parent = UuidParent.new(id: SecureRandom.uuid.upcase)
end

teardown do
UuidParent.delete_all
UuidChild.delete_all
end

test "does not dirty data on association reloads" do
@parent.uuid_children.build
@parent.save!
@parent.uuid_children.reload

refute @parent.uuid_children.first.uuid_parent_id_changed?
end
end
end