diff --git a/lib/mysql-binuuid/type.rb b/lib/mysql-binuuid/type.rb index 8273fa6..15e2130 100644 --- a/lib/mysql-binuuid/type.rb +++ b/lib/mysql-binuuid/type.rb @@ -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 diff --git a/lib/mysql-binuuid/version.rb b/lib/mysql-binuuid/version.rb index 36b21fb..82d6a9a 100644 --- a/lib/mysql-binuuid/version.rb +++ b/lib/mysql-binuuid/version.rb @@ -1,3 +1,3 @@ module MySQLBinUUID - VERSION = "1.3.0" + VERSION = "2.0.0" end diff --git a/test/integration/mysql_integration_test.rb b/test/integration/mysql_integration_test.rb index de1ce75..23ef1e3 100644 --- a/test/integration/mysql_integration_test.rb +++ b/test/integration/mysql_integration_test.rb @@ -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 @@ -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) @@ -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