CloudHealth / ar-ondemand

Fast access to database results without the memory overhead of ActiveRecord objects
MIT License
39 stars 2 forks source link

Doesn't seem like this works with UUID primary keys (Postgres) #18

Open mepatterson opened 5 years ago

mepatterson commented 5 years ago

On postgres, we use UUIDs as our primary keys. When I try to use any of the ar-ondemand methods...

> Widget.limit(500).for_reading { |e| puts e.id }
    SQL (2.8ms)  SELECT  "widgets".* FROM "widgets" LIMIT 500
    ArgumentError: Unknown type :uuid
    from /Users/dev/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/activemodel-5.2.1/lib/active_model/type/registry.rb:22:in `lookup'

> Widget.limit(500).raw_results
    SQL (3.0ms)  SELECT  "widgets".* FROM "widgets" LIMIT 500
    ArgumentError: Unknown type :uuid
    from /Users/dev/.asdf/installs/ruby/2.5.1/lib/ruby/gems/2.5.0/gems/activemodel-5.2.1/lib/active_model/type/registry.rb:22:in `lookup'
tallclouds commented 3 years ago

Narrowed the source of the issue down to result.rb initialize call.

When building the map ActiveRecord::Type.registry.lookup(x.type) fails and returns ArgumentError: Unknown type :uuid.

def initialize(model, results, options = {})
        @model = model
        @results = results
        @column_types = Hash[@model.columns.map { |x| [x.name, x] }]

        # For AR 5.x capture the types from registry to use for conversion
        @ar_types = defined?(ActiveRecord::Type.registry.lookup) ? Hash[@model.columns.map { |x|
          [x.name, (x.type.is_a?(::Symbol) ?  ActiveRecord::Type.registry.lookup(x.type) : x.type)]
        }] : nil

It appears that the registry needs the adapter to find the type correctly. For postgres: Tried this directly in console and worked:

ActiveRecord::Type.registry.lookup(:uuid, adapter: :postgresql)

Possible Fix could be:

ActiveRecord::Type.registry.lookup(x.type, adapter: @model.connection_config[:adapter].to_sym)