Included Modules

DataMapper::Is::Remixable::RemixerClassMethods

Description

Methods available to all DataMapper::Resources

Public Class Methods

included(base) click to toggle source
# File lib/dm-is-remixable/is/remixable.rb, line 73
def self.included(base);end

Public Instance Methods

enhance(remixable,remixable_model=nil, &block) click to toggle source
  • enhance

Description

Enhance a remix; allows nesting remixables, adding columns & functions to a remixed resource

Parameters

remixable <Symbol> Name of remixable to enhance (plural or singular name of is :remixable module)
model_class <Class, symbol, String> Name of the remixable generated Model Class.
block     <Proc>    Enhancements to perform

Examples

 When you have one remixable:

 class Video
   include DataMapper::Resource
   remix Comment

   enhance :comments do
     remix n, :votes        #This would result in something like YouTubes Voting comments up/down

     property :updated_at, DateTime

     def backwards; self.test.reverse; end;
   end

When you remixe the same remixable modules twice:

 class Article
   include DataMapper::Resource
   remix n, :taggings, :for => User, :model => "UserArticleTagging"
   remix n, :taggings, :for => Bot,  :model => "BotArticleTagging"

   enhance :taggings, "UserArticleTagging" do
     property :updated_at, DateTime
     belongs_to :user
     belongs_to :tag
   end

   enhance :taggings, "BotArticleTagging" do
     belongs_to :bot
     belongs_to :tag
   end
# File lib/dm-is-remixable/is/remixable.rb, line 260
def enhance(remixable,remixable_model=nil, &block)
  inflector = DataMapper::Inflector

  # always use innermost singular underscored constant name
  remixable_name = inflector.singularize(remixable.to_s)
  remixable_name = inflector.underscore(remixable_name).to_sym
  class_name = if remixable_model.nil?
    @remixables[remixable_name].keys.first
  else
    name = inflector.demodulize(remixable_model.to_s)
    inflector.underscore(name).to_sym
  end

  model = @remixables[remixable_name][class_name][:model] unless @remixables[remixable_name][class_name].nil?

  unless model.nil?
    model.class_eval &block
  else
    raise Exception, "#{remixable} must be remixed with :model option as #{remixable_model} before it can be enhanced"
  end
end
is_remixable?() click to toggle source
# File lib/dm-is-remixable/is/remixable.rb, line 75
def is_remixable?
  @is_remixable ||= false
end
remix(cardinality, remixable, options={}) click to toggle source
  • remix

Description

Remixes a Remixable Module

Parameters

cardinality <~Fixnum> 1, n, x ...
remixable   <Symbol> plural of remixable; i.e. Comment => :comments
options     <Hash>   options hash
                    :model      <String> Remixed Model name (Also creates a storage_name as tableize(:model))
                                This is the class that will be created from the Remixable Module
                                The storage_name can be changed via 'enhance' in the class that is remixing
                                Default: self.name.downcase + "_" + remixable.suffix.pluralize
                    :as         <String> Alters the name that the remixable items will be available through, this WILL NOT
                                create the standard accessor
                                Default: tableize(:class_name)
                    :for|:on    <String> Class name to join to through Remixable
                                This will create a M:M relationship THROUGH the remixable, rather than
                                a 1:M with the remixable
                    :via        <String> changes the name of the second id in a unary relationship
                                see example below; only used when remixing a module between the same class twice
                                ie: self.class.to_s == options[:for||:on]
                    :unique     <Boolean> Only works with :for|:on; creates a unique composite key
                                over the two table id's

Examples

Given: User (Class), Addressable (Module)

One-To-Many; Class-To-Remixable

remix n, :addressables, :model => "UserAddress", :as => "addresses"

Tables: users, user_addresses
Classes: User, UserAddress
  User.user_addresses << UserAddress.new => Raise No Method Exception since it was alias with :as
  User.addresses << UserAddress.new
--------------------------------------------
--------------------------------------------

Given: User (Class), Video (Class), Commentable (Module)

Many-To-Many; Class-To-Class through RemixableIntermediate (Video allows Commentable for User)

Video.remix n, :commentables
  :for        => 'User'    #:for & :on have same effect, just a choice of wording...
--------------------------------------------
--------------------------------------------

Given: User (Class), User (Class), Commentable (Module)

Many-To-Many Unary relationship between User & User through comments
User.remix n, :commentables, :as => "comments", :for => 'User', :via => "commentor"
=> This would create user_id and commentor_id as the
# File lib/dm-is-remixable/is/remixable.rb, line 139
def remix(cardinality, remixable, options={})
  assert_kind_of 'remixable', Symbol, String, Module

  #A map for remixable names to Remixed Models
  @remixables = {} if @remixables.nil?

  # Allow nested modules to be remixable to better support using dm-is-remixable in gems
  # Example (from my upcoming dm-is-rateable gem)
  # remix n, "DataMapper::Is::Rateable::Rating", :as => :ratings
  remixable_module = case remixable
    when Symbol then DataMapper::Ext::Object.full_const_get(Object, DataMapper::Inflector.classify(remixable))
    when String then DataMapper::Ext::Object.full_const_get(Object, remixable)
    when Module then remixable
  end

  unless remixable_module.is_remixable?
    raise Exception, "#{remixable_module} is not remixable"
  end

  if options[:class_name]
    warn '+options[:class_name]+ is deprecated, use :model instead'
    options[:model] = options.delete(:class_name)
  end

  inflector = DataMapper::Inflector
  model = inflector.underscore(self.name)
  model = inflector.camelize(model + '_' + remixable_module.suffix)

  #Merge defaults/options
  options = {
    :as      => nil,
    :model   => model,
    :for     => nil,
    :on      => nil,
    :unique  => false,
    :via     => nil,
    :connect => false
  }.update(options)

  #Make sure the class hasn't been remixed already
  unless DataMapper::Ext::Object.full_const_defined?(inflector.classify(options[:model]))

    #Storage name of our remixed model
    options[:table_name] = DataMapper::Inflector.tableize(inflector.demodulize(options[:model]))

    #Other model to mix with in case of M:M through Remixable
    options[:other_model] = options[:for] || options[:on]

    DataMapper.logger.info "Generating Remixed Model: #{options[:model]}"
    model = generate_remixed_model(remixable_module, options)

    # map the remixable to the remixed model
    # since this will be used from 'enhance api' i think it makes perfect sense to
    # always refer to a remixable by its demodulized underscored constant name
    remixable_key = inflector.demodulize(remixable_module.name)
    remixable_key = inflector.underscore(remixable_key).to_sym
    populate_remixables_mapping(model, options.merge(:remixable_key => remixable_key))

    # attach RemixerClassMethods and RemixerInstanceMethods to remixer if defined by remixee
    if DataMapper::Ext::Object.full_const_defined? "#{remixable_module}::RemixerClassMethods"
      extend DataMapper::Ext::Object.full_const_get("#{remixable_module}::RemixerClassMethods")
    end

    if DataMapper::Ext::Object.full_const_defined? "#{remixable_module}::RemixerInstanceMethods"
      include DataMapper::Ext::Object.full_const_get("#{remixable_module}::RemixerInstanceMethods")
    end

    #Create relationships between Remixer and remixed class
    if options[:other_model]
      # M:M Class-To-Class w/ Remixable Module as intermediate table
      # has n and belongs_to (or One-To-Many)
      remix_many_to_many cardinality, model, options
    else
      # 1:M Class-To-Remixable
      # has n and belongs_to (or One-To-Many)
      remix_one_to_many cardinality, model, options
    end
  else
    DataMapper.logger.warn "#{__FILE__}:#{__LINE__} warning: already remixed constant #{options[:model]}"
  end
end
remixables() click to toggle source
  • remixables

Description

Returns a hash of the remixables used by this class

Returns

<Hash> Remixable Class Name => Remixed Class Name
# File lib/dm-is-remixable/is/remixable.rb, line 84
def remixables
  @remixables
end

[Validate]

Generated with the Darkfish Rdoc Generator 2.