#1001 ✓resolved
Ashley Moran

STI broken when subclassed parent to a child - possibly connected in some way to validation code

Reported by Ashley Moran | August 4th, 2009 @ 09:57 AM | in 0.10.2

This is much easier demonstrated with a ticket than explained. Because of DataMapper's next branch evolving quickly, I don't know how this will work against the latest code.

require 'rubygems'
  
USE_DM_0_9 = false # We didn't test it in 0.9 - gem has been uninstalled
 
if USE_DM_0_9
  DM_GEMS_VERSION   = "0.9.11"
  DO_GEMS_VERSION   = "0.9.12"
else
  DM_GEMS_VERSION   = "0.10.0"
  DO_GEMS_VERSION   = "0.10.0"
end
 
gem "data_objects",   DO_GEMS_VERSION
gem "do_sqlite3",     DO_GEMS_VERSION
gem "dm-core",        DM_GEMS_VERSION   
gem "dm-types",       DM_GEMS_VERSION        
gem "dm-validations", DM_GEMS_VERSION  

require "data_objects"
require "dm-core"
require "dm-types"
require "dm-validations"

require 'spec'
 
SQLITE_FILE = File.join(`pwd`.chomp, "test.db")
 
DataMapper.setup(:default, "sqlite3:#{SQLITE_FILE}")
DataMapper.setup(:reloaded, "sqlite3:#{SQLITE_FILE}")

# We have not investigated the false case
ENABLE_MONKEY_PATCH_WE_THINK_HIGHLIGHTS_ERROR_BUT_ACTUALLY_CHANGES_BEHAVIOUR = true

if ENABLE_MONKEY_PATCH_WE_THINK_HIGHLIGHTS_ERROR_BUT_ACTUALLY_CHANGES_BEHAVIOUR == true
  module DataMapper
    module Validate
      extend Chainable
      
      # NOTE: this is different to the current next branch, as of writing:
      # http://github.com/datamapper/dm-more/blob/0c58330f1ee3b27978fec1e3331c1b68417a738a/dm-validations/lib/dm-validations.rb
      def save(context = :default)
        return false unless save_parents && (context.nil? || valid?(context))
        save_self && save_children
      end
    end
  end
end

class Person
  include DataMapper::Resource

  property :id, Serial
  property :type, Discriminator
end
 
class Employee < Person  
  has 1, :job_role
end

class Manager < Person  
  has 1, :office
  
  def initialize(*)
    self.office = Office.new(:manager => self)
    super
  end
end

class JobRole
  include DataMapper::Resource
  
  property :id, Serial
  
  belongs_to :employee
  # belongs_to :person # Allows you to save
end
 
class Office
  include DataMapper::Resource
  
  property :id, Serial
  
  belongs_to :manager
end
 
Spec::Runner.configure do |config|
  config.before(:each) do
    Person.auto_migrate!
    JobRole.auto_migrate!
    Office.auto_migrate!
  end
end

describe "belongs_to targetting an STI subclass" do
  before(:each) do
    @employee = Employee.new    
  end
  
  # Pass
  it "should save when you assign the parent to the child" do
    @job_role = JobRole.new(:employee => @employee)
    @job_role.save.should be_true
  end
  
  # Fail
  it "should save when you assign the child to the parent" do
    # Produces: "table job_roles has no column named person_id"    
    @job_role = @employee.job_role = JobRole.new
    @job_role.save.should be_true
  end

  # Pass
  it "should save if you do both" do
    @job_role = @employee.job_role = JobRole.new(:employee => @employee)
    @job_role.save.should be_true
  end
end

describe "when the child is created in the parent's constructor" do
  before(:each) do
    @manager = Manager.new    
  end
  
  # Fail
  it "should save" do
    @manager.save.should be_true
  end
end

Comments and changes to this ticket

  • Dan Kubb (dkubb)

    Dan Kubb (dkubb) October 7th, 2009 @ 12:41 PM

    • Milestone set to 0.10.2
    • State changed from “new” to “resolved”
    • Assigned user set to “Dan Kubb (dkubb)”

    I can confirm these specs now pass with edge dm-core and dm-more.

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