#1191 ✓resolved
Jordan Ritter

custom dm-types don't properly deserialize when aggregated

Reported by Jordan Ritter | February 3rd, 2010 @ 09:46 AM | in 1.0.0

Custom DM types do not deserialize/re-map properly when dm-aggregates is used upon them. Observe:

require 'dm-core'
require 'dm-types'
require 'dm-aggregates'

DataMapper::Logger.new(STDOUT, :debug)
DataMapper.setup(:default, "mysql://root@localhost/foo")

class Foo
    include ::DataMapper::Resource

    property :id, Serial
    property :enum, Enum[:foo, :bar, :blort]
end

::DataMapper.auto_migrate!

2.times { Foo.create(:enum => :foo) }
          Foo.create(:enum => :bar)

require 'pp'
pp Foo.aggregate(:enum, :fields => [:enum, :enum.count])
___END___
 ~ (0.000005) SET sql_auto_is_null = 0
 ~ (0.000002) SET SESSION sql_mode = 'ANSI,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION,NO_UNSIGNED_SUBTRACTION,TRADITIONAL'
 ~ (0.000002) DROP TABLE IF EXISTS `foos`
 ~ (0.000003) SHOW TABLES LIKE 'foos'
 ~ (0.000002) SHOW VARIABLES LIKE 'character_set_connection'
 ~ (0.000002) SHOW VARIABLES LIKE 'collation_connection'
 ~ (0.000002) CREATE TABLE `foos` (`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `enum` INTEGER, PRIMARY KEY(`id`)) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci
 ~ (0.000003) INSERT INTO `foos` (`enum`) VALUES (1)
 ~ (0.000002) INSERT INTO `foos` (`enum`) VALUES (1)
 ~ (0.000003) INSERT INTO `foos` (`enum`) VALUES (2)
 ~ (0.000004) SELECT `enum`, COUNT(`enum`) FROM `foos` GROUP BY `enum` ORDER BY `enum`
[[nil, 2], [nil, 1]]

The fix is to call the field type's #load() method before #typecast()ing:

diff --git a/dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb b/dm-aggregates/lib/dm-aggregates/adapters/data
index ff877ee..9ace407 100644
--- a/dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb
+++ b/dm-aggregates/lib/dm-aggregates/adapters/data_objects_adapter.rb
@@ -27,6 +27,7 @@ module DataMapper
                 if field.respond_to?(:operator)
                   send(field.operator, field.target, value)
                 else
+                  value = field.type.load(value, field) if field.type.respond_to?(:load)
                   field.typecast(value)
                 end
               end

Which leads the above script to yield the correct result:

 ~ (0.000006) SET sql_auto_is_null = 0
 ~ (0.000002) SET SESSION sql_mode = 'ANSI,NO_BACKSLASH_ESCAPES,NO_DIR_IN_CREATE,NO_ENGINE_SUBSTITUTION,NO_UNSIGNED_SUBTRACTION,TRADITIONAL'
 ~ (0.000002) DROP TABLE IF EXISTS `foos`
 ~ (0.000002) SHOW TABLES LIKE 'foos'
 ~ (0.000003) SHOW VARIABLES LIKE 'character_set_connection'
 ~ (0.000001) SHOW VARIABLES LIKE 'collation_connection'
 ~ (0.000002) CREATE TABLE `foos` (`id` INT(10) UNSIGNED NOT NULL AUTO_INCREMENT, `enum` INTEGER, PRIMARY KEY(`id`)) ENGINE = InnoDB CHARACTER SET utf8 COLLATE utf8_general_ci
 ~ (0.000005) INSERT INTO `foos` (`enum`) VALUES (1)
 ~ (0.000003) INSERT INTO `foos` (`enum`) VALUES (1)
 ~ (0.000002) INSERT INTO `foos` (`enum`) VALUES (2)
 ~ (0.000004) SELECT `enum`, COUNT(`enum`) FROM `foos` GROUP BY `enum` ORDER BY `enum`
[[:foo, 2], [:bar, 1]]

Comments and changes to this ticket

Please Sign in or create a free account to add a new ticket.

With your very own profile, you can contribute to projects, track your activity, watch tickets, receive and update tickets through your email and much more.

New-ticket Create new ticket

Create your profile

Help contribute to this project by taking a few moments to create your personal profile. Create your profile »

People watching this ticket

Pages