#1380 ✓resolved
mbj

When using ActiveModel::Validations descendant tracking from activesupport-3.rc failes with dm-migrations

Reported by mbj | August 1st, 2010 @ 01:04 PM | in 1.1

When I'm using ActiveModel::Validations in my model, the model ends up with an descendant tracker from ActiveSupport.

It basically overrides dm-core's one. ActiveSupport and DataMapper had an different understanding of descendants.

Example:

class A
end

class B < A
end

Datamapper: A#descendants => DestendantSet with: [A,B]
ActiveSupport: A#descendants => [B]

related active support (rails) commit: http://github.com/rails/rails/commit/5dda97602f2188a13cbcab5c7e9a5b...

When dm-migration calls: Model#properties_with_subclasses on any model with included active support/validations the following code fails: (dm-core/model/properties.rb)

  def properties_with_subclasses(repository_name = default_repository_name)
    properties = PropertySet.new

    descendants.each do |model|
      model.properties(repository_name).each do |property|
        properties[property.name] ||= property
      end
    end

    properties
  end

It basically ends up with an empty property set for non STI models (and an incorrect for STI). If I'm including ActiveModels::Validations after DataMapper::Resource, datamappers descendant tracking is used (it overrides ActiveSupports one).

Here is some example code:

  gem 'dm-core', '1.0.0'
  gem 'dm-sqlite-adapter', '1.0.0'
  gem 'activemodel', '3.0.0.rc'

  require 'dm-core'
  require 'dm-sqlite-adapter'
  require 'dm-migrations'
  require 'active_model'

  class FailingPerson
    include DataMapper::Resource
    include ActiveModel::Validations
    property :id,Serial
    property :name,String
    validates_presence_of :name
  end

  class CorrectPerson
    include ActiveModel::Validations
    include DataMapper::Resource
    property :id,Serial
    property :name,String
    validates_presence_of :name
  end

  DataMapper::Logger.new(STDERR,:debug)

  DataMapper.setup(:default,"sqlite://:memory:")
  DataMapper.auto_migrate!

  p FailingPerson.method(:descendants)
  p CorrectPerson.method(:descendants)

  p CorrectPerson.first
  p FailingPerson.first

Resulting in:

   ~ (0.000088) SELECT sqlite_version(*)
   ~ (0.000150) DROP TABLE IF EXISTS "failing_people"
   ~ (0.000014) PRAGMA table_info("failing_people")
   ~ (0.000015) DROP TABLE IF EXISTS "correct_people"
   ~ (0.000009) PRAGMA table_info("correct_people")
   ~ (0.001066) CREATE TABLE "correct_people" ("id" INTEGER NOT NULL PRIMARY KEY AUTOINCREMENT, "name" VARCHAR(50))
   #<Method: Class(ActiveSupport::DescendantsTracker)#descendants>
   []
   #<Method: Class(DataMapper::Model)#descendants>
   #<DataMapper::Model::DescendantSet:0x000000012a65d8 @descendants=[CorrectPerson],  @ancestors=#<DataMapper::Model::DescendantSet:0x000000012e8aa0 @descendants=[FailingPerson, CorrectPerson], @ancestors=nil>>
   ~ (0.000048) SELECT "id", "name" FROM "correct_people" ORDER BY "id" LIMIT 1
   nil
   ~ (0.000027) SELECT "id", "name" FROM "failing_people" ORDER BY "id" LIMIT 1
   ~ no such table: failing_people (code: 1, sql state: , query: SELECT "id", "name" FROM "failing_people" ORDER BY "id" LIMIT 1, uri: sqlite3://:memory)

It would be trivial to fix this. But I'm sure someone of the datamapper devs can fix it better than me ;)

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 »

Pages