#1095 ✓resolved
phatmann

STI issue when loading Resources via base Model

Reported by phatmann | October 14th, 2009 @ 03:25 PM | in 1.1

The following code shows the problem:

  require 'rubygems'
  gem 'dm-core', '0.10.1'
  require 'dm-core'

  DataMapper::Logger.new(STDOUT, :debug)
  DataMapper.setup(:default, "mysql://localhost/ts_test")
 
  class Base
    include DataMapper::Resource
    property :id, Serial
    property :type, Discriminator
  end

  class Derived1 < Base
  end

  class Derived2 < Base
    property :extra, Integer
  end

  DataMapper.auto_migrate!
  Derived2.create(:extra => 1)
  Derived2.all.first.extra           # SUCCEEDS
  Base.all.first.extra               # FAILS

Here is the backtrace:

  `+options[:field]+ entry :extra does not map to a property in Base (ArgumentError)`
  dm-core/query.rb:689:in `assert_valid_fields'    
  dm-core/query.rb:680:in `each'
  dm-core/query.rb:680:in `assert_valid_fields'
  dm-core/query.rb:656:in `assert_valid_options'
  dm-core/query.rb:654:in `each'
  dm-core/query.rb:654:in `assert_valid_options'
  dm-core/query.rb:598:in `initialize'
  dm-core/query.rb:343:in `update'
  dm-core/query.rb:359:in `merge'
  dm-core/collection.rb:69:in `reload'
  dm-core/resource.rb:724:in `eager_load'
  dm-core/resource.rb:710:in `lazy_load'
  dm-core/property.rb:596:in `send'
  dm-core/property.rb:596:in `lazy_load'
  dm-core/property.rb:487:in `get'
  dm-core/model/property.rb:200:in `extra'
  from dm-test.rb:24

The problem starts with an STI issue: the first resource returned from Base.all does not have the :extra field loaded. Attempting to access the :extra field triggers a lazy load, which then triggers an eager load. The eager loading code loads the resource as type Base rather than Derived2, and the call to the #extra accessor fails.

So there are at least problems here:

  1. All the fields of Derived2 are not properly loaded when accessing via Base.all.first

  2. Eager loading via Base.all does not honor the STI type

Comments and changes to this ticket

  • David Kelso
  • Martin Gamsjaeger (snusnu)

    Martin Gamsjaeger (snusnu) January 14th, 2011 @ 08:47 PM

    • State changed from “new” to “resolved”
    • Milestone set to 1.1
    • Milestone order changed from “0” to “0”

    It's not exactly a dupe, in fact I believe this is resolved. Have a look at my comment over at #911 tho.

    ree-1.8.7-2010.02@datamapper mungo:dm-core snusnu$ ruby 1095.rb
     ~ (0.000107) SELECT sqlite_version(*)
     ~ (0.000135) DROP TABLE IF EXISTS "bases"
     ~ (0.000013) PRAGMA table_info("bases")
     ~ (0.000314) CREATE TABLE "bases" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "type" VARCHAR NOT NULL, "extra" INTEGER)
     ~ (0.000075) DROP TABLE IF EXISTS "bases"
     ~ (0.000007) PRAGMA table_info("bases")
     ~ (0.000102) CREATE TABLE "bases" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "type" VARCHAR NOT NULL, "extra" INTEGER)
     ~ (0.000071) DROP TABLE IF EXISTS "bases"
     ~ (0.000006) PRAGMA table_info("bases")
     ~ (0.000108) CREATE TABLE "bases" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "type" VARCHAR NOT NULL, "extra" INTEGER)
     ~ (0.000041) INSERT INTO "bases" ("type", "extra") VALUES ('Derived2', 1)
     ~ (0.000039) SELECT "id", "type", "extra" FROM "bases" WHERE "type" IN ('Derived2') ORDER BY "id" LIMIT 1
     ~ (0.000041) SELECT "id", "type" FROM "bases" WHERE "type" IN ('Base', 'Derived1', 'Derived2') ORDER BY "id" LIMIT 1
     ~ (0.000034) SELECT "id", "type", "extra" FROM "bases" WHERE "id" = 1 ORDER BY "id"
    

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 »

Pages