public
Description: Model ancestry and property management
Homepage: https://github.com/coryodaniel/dm-property-manager
Clone URL: git://github.com/coryodaniel/dm-property-manager.git
Cory ODaniel (author)
Thu Oct 01 18:37:42 -0700 2009
commit  27f15ae223c3afa95438e04088baf159920b7fa3
tree    83065ed54f743685ae9376641d71d794df1271ba
parent  2f9acb69b4bf843f6dedcfa9646991f7968e5186
name age message
file README.markdown Loading commit data...
file Rakefile
file dm-property-manager.gemspec
directory lib/
directory spec/
directory tasks/
README.markdown

Compatible w/ DM >= 0.9.11

DM PropertyManager is useful when you have similar models with identical properties/relationships between the two.

Whenever a model manages another model it also gets a few factory methods: new_model_name : creates an unsaved instance createmodel_name : creates a saved instance * createmodel_name_and_destroy : creates a saved instance and destroy the object you are working with

The factory methods will populate the created instance with all the values of the property of the managing instance.

Example: Rsvp.manage(:seat){...do_something...} Rsvp.new.respond_to? :new_seat #=> true

TODOS

  • has relationships should auto populate, see hack below

  • belongs_to relationships should auto populate, see hack below

Simple Example

class Rsvp
  include DataMapper::Resource
  include DataMapper::PropertyManager

  property :id, Serial

  manage(:seat) do
    belongs_to :room #some other model

    property :confirmation, String
    property :section, String
    property :number, String
  end
end

class Seat
  include DataMapper::Resource

  property :id, Serial
  property :arrived_at, DateTime
end

@rsvp = Rsvp.new
@rsvp.confirmation = "209fa9bj9jaa"
@rsvp.section = "Orchestra"
@rsvp.number  = "10A"
@rsvp.save

@seat = @rsvp.new_seat(:arrived_at=>Time.now)
@seat.section #=> "Orchestra"
@seat.arrived_at = "Fri May 01 21:18:24 -0700 2009"

Delegation

Delegation is useful when you have similar models, and you'd like to declare the like properties/relationships in one place and delegate the control of the 'managed models' to another model.

For the example we have a ticket system with three types of tickets (yeah its a stupid example): Unsold Tickets Sold Tickets * Stubs

class UnsoldTicket
  include DataMapper::Resource
  include DataMapper::PropertyManager

  property :id,     Serial

  manage(:sold_tickets => :stub) do
    belongs_to :concert
    property :seat,     String
    property :section,  Enum[:pit, :dance_floor, :really_far_back]
    property :price,    Float
  end
end

class SoldTicket
  include DataMapper::Resource
  include DataMapper::PropertyManager

  property :id,     Serial
end

class Stub
  include DataMapper::Resource
  include DataMapper::PropertyManager

  property :id,     Serial
end

@unsold_ticket = UnsoldTicket.new
@unsold_ticket.concert = Concert.get("Britney Spears, Live from your butthole")
@unsold_ticket.seat     = "33A"
@unsold_ticket.section  = :pit
@unsold_ticket.price    = 1.30
@unsold_ticket.save

@unsold_ticket.new_sold_ticket #=> an unsaved new ticket with the same properties
@unsold_ticket.create_sold_ticket #=> a saved ticket with the same properties
@unsold_ticket.create_sold_ticket(:price=>2.50) #=> a saved ticket overriding the price
@unsold_ticket.create_sold_ticket_and_destroy #=> a saved ticket and destroy the unsold one

@sold_ticket = @unsold_ticket.create_sold_ticket_and_destroy(:price => 25.30)

# the concert comes and goes...
@stub = @sold_ticket.create_stub_and_destroy #=> destroyes the sold ticket and makes it a ticket stub.

Auto Archiver

PropertyManager can be used to manage properties between a model and some archived version of the model

class User
  include DataMapper::Resource
  include DataMapper::PropertyManager

  property :id,     Serial  

  manage(:archived_user) do
    property :name,   String
    property :email,  String
    property :password,  String
    property :created_at, DateTime
  end

  def archive!
    @au = new_archived_user
    @au.deleted_at = Time.now
    @au.save
    self.destroy

    @au
  end

end

class ArchivedUser
  include DataMapper::Resource

  def self.default_repository_name
    :my_archive_repository
  end
  property :id, Serial
  property :deleted_at, DateTime
end

user = User.new
user.name = "Cory Odaniel"
user.email = "propmanager@coryodaniel.com"
user.password = "secretz"
user.save

# Move the user to the archive_users repo
user.archive!                         

Hack for auto populating relationships

class Dad
  include DataMapper::Resource
  property :id, Serial
  property :first_name, String

  manage(:kid) do
    belongs_to :dad   
    property :dad_id,     Integer
    property :last_name,  String
  end
end

class Kid
  include DataMapper::Resource
  property :id, Serial
  property :first_name, String
end