Skip to content

Instantly share code, notes, and snippets.

@bgentry
Created November 18, 2009 20:53
Show Gist options
  • Save bgentry/238238 to your computer and use it in GitHub Desktop.
Save bgentry/238238 to your computer and use it in GitHub Desktop.
Provides a DataMapper Type for Tags (similar to Flags in dm-types). Tags are stored here in YAML form but made accessible to your app as symbols. Overrides the default 'Text' primitive of Yaml because, for my usage, 255chars is sufficient
require 'set'
module DataMapper
module Types
class Tags < Yaml
primitive String
length 255
lazy false
def self.inherited(target)
target.send :primitive, String
target.send :length, 255
target.send :lazy, false
end
def self.flag_list
@flag_list
end
def self.flag_list=(value)
@flag_list = value
end
def self.new(*flags)
type = Class.new(Tags)
type.flag_list = Set.new
flags.each {|flag| type.flag_list << flag }
type
end
def self.[](*flags)
new(*flags)
end
def self.load(value, property)
if value.nil?
nil
elsif value.is_a?(String)
matches = super
return if matches == nil
results = []
matches.each do |v|
results << v.to_sym
unless flag_list.include?(v.to_sym)
flag_symbols = flag_list.map {|i| ":#{i}"}
msg = "Tag :#{v} was loaded but not present in list: ["
msg << flag_symbols.join(", ") << ']'
warn msg
end
end
results.uniq
else
raise ArgumentError.new("+value+ of a property of Tags type must be nil or a String")
end
end
def self.dump(value, property)
array = if value.nil?
nil
elsif value.is_a?(Symbol)
flag_list.include?(value) ? [value.to_s] : nil
elsif value.is_a?(Array)
value.each {|v| value.delete(v) unless flag_list.include?(v) }
value.empty? ? nil : value.map {|v| v.to_s }
else
raise ArgumentError, "+value+ of Tags must be a an array or nil, but given #{value.inspect}"
end
super(array, property)
end
def self.typecast(value, property)
case value
when nil then nil
when Array then value.map {|v| v.to_sym}
when Symbol then [ value ]
else [ value.to_sym ]
end
end
end # class Yaml
end # module Types
end # module DataMapper
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment