= dm-is-remixable

DataMapper::Is::Remixable allows you to create re-usable chunks of relational data, its kind of like multiple
inheritance for models.

For example:

  # Comments are everywhere, why define them over and over?:
  module Comment
    include DataMapper::Resource
    is :remixable

    property :id,         Serial
    property :body,       String
    property :created_at, DateTime
  end

  # Lots of things can be addressable; people, buildings
  module Addressable
    include DataMapper::Resource

    is :remixable,
      :suffix => "address" #Default suffix is module name pluralized

    property :id,         Serial

    property :label,      String #home, work, etc...

    property :address1,   String, :length => 255
    property :address2,   String, :length => 255

    property :city,       String, :length => 128
    property :state,      String, :length => 2
    property :zip,        String, :length => 5..10
  end

  module Vote
    include DataMapper::Resource

    is :remixable

    property :id,         Serial
    property :opinion,    Enum["good","bad"]
  end

  class Location
    include DataMapper::Resource

    #Location can have 1 address
    remix 1, :addressables

    # This does the following:
    # - creates a class called LocationAddress
        (default name would be LocationAddressable, but Addressable#suffix was specified)
    # - duplicates the properties of Addressable within LocationAddress
    # - a table called location_addresses
    # - creates Location#location_addresses accessor

    #... methods, properties, etc ...#
  end

  class User
    include DataMapper::Resource

    #User can have many addresses
    remix n, :addressables, :as => "addresses"
    # - creates a class called UserAddress
        (default name would be UserAddressable, but Addressable#suffix was specified)
    # - duplicates the properties of Addressable within UserAddress
    # - a table called user_addresses
    # - creates User#user_addresses accessor
    # - creates an accessor alias User#addresses

    enhance :addressables do
      storage_names[:default] = "a_different_table_name"
      property :label, Enum["work","home"]

      #This adds a column to user_addresses to store an address label
    end

    #... methods, properties, etc ...#
  end

  class Article
    include DataMapper::Resource

    remix n, :comments, :for => "User"
    # - creates a class called ArticleComment
    # - duplicates the properties of Comment within ArticleComment
    # - a table called article_comments
    # - creates Article#article_comments
    # - creates User#article_comments

    #... methods, properties, etc ...#

  end

  class Video
    include DataMapper::Resource

    remix n, :comments, :for => "User", :as => "comments"
    # - creates a class called VideoComment
    # - duplicates the properties of Comment within VideoComment
    # - a table called video_comments
    # - creates Video#video_comments
    # - creates User#video_comments
    # - create Video#comments

    enhance :comments do
      # VideoComment now has the method #reverse
      def reverse
        return self.body.reverse
      end

      #I like YouTubes ability for users to vote comments up and down
      remix 1, :votes, :for => "User"
      # - creates a class called VideoCommentVote
      # - duplicates the properties of Vote within VideoCommentVote
      # - a table called video_comment_votes
      # - creates Video#video_comments#votes

    end

    #... methods, properties, etc ...#
  end

Further, remixables can namespace methods that should exist in the generated and remixing classes, if these
modules are present the are attached appropriately to the other classes.

  module ExampleRemixable
    include DataMapper::Resource
    is :remixable

    #... your properies ...

    # Class methods that will be attached to class doing the remixing...
    #
    # These methods would be attached to the User class given:
    #   User.remixes n, :images
    #
    module RemixerClassMethods
    end

    # Instances methods that will be attached to objects of the class doing the remixing...
    #
    # These methods would be attached to User objects given:
    #   User.remixes n, :images
    #
    module RemixerInstanceMethods
    end

    # Class methods that will be attached to genereated remixed class
    #
    # These methods would be attached to the UserImage class given:
    #   User.remixes n, :images
    #
    module RemixeeClassMethods
    end

    # Instances methods that will be attached to objects of the genereated remixed class
    #
    # These methods would be attached to UserImage objects given:
    #   User.remixes n, :images
    #
    module RemixeeInstanceMethods
    end
  end
