module Cistern::Attributes def self.parsers @parsers ||= { :string => lambda { |v,opts| v.to_s }, :time => lambda { |v,opts| v.is_a?(Time) ? v : v && Time.parse(v.to_s) }, :integer => lambda { |v,opts| v && v.to_i }, :float => lambda { |v,opts| v && v.to_f }, :array => lambda { |v,opts| [*v] }, :boolean => lambda { |v,opts| ['true', '1'].include?(v.to_s.downcase) } } end def self.transforms @transforms ||= { :squash => Proc.new do |k, _v, options| v = Cistern::Hash.stringify_keys(_v) squash = options[:squash] if v.is_a?(::Hash) && squash.is_a?(Array) travel = lambda do |tree, path| if tree.is_a?(::Hash) travel.call(tree[path.shift], path) else tree end end travel.call(v, squash.dup) elsif v.is_a?(::Hash) if v.key?(squash.to_s.to_sym) v[squash.to_s.to_sym] elsif v.has_key?(squash.to_s) v[squash.to_s] else v end else v end end, :none => lambda { |k, v, opts| v }, } end def self.default_parser @default_parser ||= lambda { |v, opts| v } end module ClassMethods def _load(marshalled) new(Marshal.load(marshalled)) end def aliases @aliases ||= Hash.new { |h,k| h[k] = [] } end def attributes @attributes ||= {} end def attribute(_name, options = {}) if defined? Cistern::Coverage attribute_call = Cistern::Coverage.find_caller_before("cistern/attributes.rb") # Only use DSL attribute calls from within a model if attribute_call and attribute_call.label.start_with? " v) } end def changed @changes ||= {} end protected def missing_attributes(args) ([:service] | args).select{|arg| send("#{arg}").nil?} end def changed!(attribute, from, to) changed[attribute] = if existing = changed[attribute] [existing.first, to] else [from, to] end end end end