Sha256: 1cfcee910920eeb03fb619b82a2797bfcb3b120e615d234ba1305fae352b9432

Contents?: true

Size: 2 KB

Versions: 1

Compression:

Stored size: 2 KB

Contents

require 'active_support/core_ext/module/delegation'
require 'active_support/core_ext/array/extract_options'
require 'active_support/core_ext/object/duplicable'

class Collection
  include Enumerable

  attr_reader :klass, :options

  delegate :empty?, :size, :each, :last, to: :@collection, allow_nil: true

  class << self
    alias_method :of, :new
    alias_method :[], :new
  end

  def initialize(klass, *args)
    @options = args.extract_options!
    @klass = klass.is_a?(Class) ? klass : klass.class
    @collection = [args.first].compact.flatten
  end

  def initialize_clone(*)
    super

    # Clone each item in the collection
    @collection = @collection.inject([]) do |ary, item|
      ary << (item.duplicable? ? item.clone : item)
      ary
    end
  end

  def [](item)
    return nil if empty?

    if item.is_a?(Fixnum)
      @collection[item]
    else
      item = item.to_sym
      detect{ |i| i.name.to_sym == item }
    end
  end

  def new(*args, &block)
    @klass.new(*args, &block).tap{ |obj| @collection << obj }
  end

  def <<(obj)
    checker = @options.fetch(:allow_subclasses, true) ? :is_a? : :instance_of?
    raise ArgumentError, "can only add #{@klass.name} objects" unless obj.send(checker, @klass)
    @collection << obj
  end

  def keys
    @collection.map{ |i| i.name.to_sym }
  end

  def key?(key)
    keys.include?(key.to_sym)
  end
  alias_method :has_key?, :key?

  def include?(item)
    return true if @collection.include?(item)
    return keys.include?(item.to_sym) if item.respond_to?(:to_sym)
    return false
  end

  def except(*items)
    items.map!(&:to_sym)
    self.class.new(klass, reject{ |i| items.include?(i.name.to_sym) })
  end

  def slice(*items)
    items.map!(&:to_sym)
    self.class.new(klass, select{ |i| items.include?(i.name.to_sym) })
  end

  def delete(*items)
    @collection = reject{ |i| items.include?(i.name) }
  end

  def ==(other)
    return other == @collection if other.is_a?(self.class)
    return @collection == other if other.is_a?(Array)
    super
  end
end

Version data entries

1 entries across 1 versions & 1 rubygems

Version Path
collection_of-1.0.5 lib/collection_of/collection.rb