Skip to content

Instantly share code, notes, and snippets.

@mbj
Created June 6, 2011 13:50
Show Gist options
  • Save mbj/1010298 to your computer and use it in GitHub Desktop.
Save mbj/1010298 to your computer and use it in GitHub Desktop.
Using veritas as a pseudo EV replacement in datamapper
# this is full of bad metaprogramming
class EmbeddedItems < DataMapper::Mongo::Property::Array
def load(value)
if value.nil?
nil
elsif value.is_a? ::Array
value.map { |item| embedded_item_class.load item }.extend collection
else
raise ArgumentError.new "+value+ of a property of #{self.class} type must be ::Array was: #{value.class}"
end
end
def embedded_item_class
self.class::EMBEDDED_ITEM
end
def collection
self.class::Collection
end
def dump(value)
if value.nil?
nil
elsif value.is_a? ::Array
value.map do |item|
if item.is_a? embedded_item_class
item.attributes
else
raise ArgumentError.new "each item of a property of #{self.class} type must be ::#{embedded_item_class} was: #{value.class}"
end
end
else
raise ArgumentError.new "+value+ of a property of #{self.class} type must be ::Array was: #{value.class}"
end
end
def typecast(value)
if value.nil?
nil
elsif value.is_a? ::Array
value.map do |item|
if item.kind_of? embedded_item_class
item
else
embedded_item_class.load item
end
end.extend collection
else
raise ArgumentError.new "+value+ of a property of #{self.class} type must be ::Array was: #{value.class}"
end
end
class << self
def for(klass)
unless klass.is_a? ::Class
raise ArgumentError.new "+klass+ msut be of type ::Class was: #{value.class}"
end
return registry[klass] if registry[klass]
embedded = Class.new(Stocktrade::Property::EmbeddedItems)
embedded.const_set('EMBEDDED_ITEM',klass)
embedded.const_set('Collection',Module.new)
registry[klass]=embedded
end
def registry
@registry ||= {}
end
end
end
require 'virtus'
class LineItem
include Virtus
include Virtus::DirtyTracking
include ActiveModel::Validations
attribute :product_id, String
attribute :quantity, Integer
validates_presence_of :product_id
validates_presence_of :quantity
def product=(value)
@product_id = if value.nil?
nil
elsif value.is_a? Product
raise ArgumentError, 'product must have an id' unless value.id
value.id
else
raise ArgumentError, '+value+ must be nil or an instance of Product'
end
end
def product
Product.get(product_id) if product_id
end
def self.load(value)
if value.kind_of? ::Hash
self.new(value)
else
raise ArgumentError, "+value+ must be an Hash was: #{value.class}"
end
end
def ==(other)
return false unless other.kind_of?(self.class)
other.product_id == self.product_id && other.quantity == self.quantity
end
end
class Order
include DataMapper::Mongo::Resource
property :id,ObjectId
property :line_items, ::EmbeddedItems.for(LineItem)
end
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment