module ActiveGraph::Shared # Contains methods related to the management class DeclaredProperty include Comparable class IllegalPropertyError < ActiveGraph::Error; end include ActiveGraph::Shared::DeclaredProperty::Index ILLEGAL_PROPS = %w(from_node to_node start_node end_node) attr_reader :name, :name_string, :name_sym, :options, :magic_typecaster, :type, :typecaster, :default_value alias default default_value def initialize(name, options = {}) fail IllegalPropertyError, "#{name} is an illegal property" if ILLEGAL_PROPS.include?(name.to_s) fail TypeError, "can't convert #{name.class} into Symbol" unless name.respond_to?(:to_sym) @name = @name_sym = name.to_sym @name_string = name.to_s @type = options[:type] @typecaster = options[:typecaster] @default_value = options[:default] @options = options fail_invalid_options! end # Compare attribute definitions # # @example # attribute_definition <=> other # # @param [ActiveGraph::Shared::DeclaredProperty, Object] other The other # attribute definition to compare with. # # @return [-1, 0, 1, nil] def <=>(other) return nil unless other.instance_of? self.class return nil if name == other.name && options != other.options self.to_s <=> other.to_s end def inspect options_description = options.map { |key, value| "#{key.inspect} => #{value.inspect}" }.sort.join(', ') inspected_options = ", #{options_description}" unless options_description.empty? "attribute :#{name}#{inspected_options}" end def to_s name.to_s end def to_sym name end def [](key) respond_to?(key) ? public_send(key) : nil end def register register_magic_properties end def fail_invalid_options! case when index?(:exact) && constraint?(:unique) fail ActiveGraph::InvalidPropertyOptionsError, "#Uniqueness constraints also provide exact indexes, cannot set both options on property #{name}" end end private def option_with_value!(key, value) options[key] = value fail_invalid_options! end def option_with_value?(key, value) options[key] == value end # Tweaks properties def register_magic_properties @type ||= ActiveGraph::Config.timestamp_type if timestamp_prop? register_magic_typecaster register_type_converter end def timestamp_prop? name.to_sym == :created_at || name.to_sym == :updated_at end def register_magic_typecaster found_typecaster = ActiveGraph::Shared::TypeConverters.typecaster_for(type) return unless found_typecaster && found_typecaster.respond_to?(:primitive_type) @typecaster = found_typecaster @magic_typecaster = type @type = found_typecaster.primitive_type end def register_type_converter converter = options[:serializer] return unless converter @type = converter.convert_type @typecaster = ActiveGraph::Shared::TypeConverters::ObjectConverter ActiveGraph::Shared::TypeConverters.register_converter(converter) end end end