lib/neo4j/active_node/property.rb in neo4j-3.0.0.alpha.6 vs lib/neo4j/active_node/property.rb in neo4j-3.0.0.alpha.7
- old
+ new
@@ -4,24 +4,60 @@
include ActiveAttr::Attributes
include ActiveAttr::MassAssignment
include ActiveAttr::TypecastedAttributes
include ActiveAttr::AttributeDefaults
+ include ActiveAttr::QueryAttributes
include ActiveModel::Dirty
+ class UndefinedPropertyError < RuntimeError
+ end
def initialize(attributes={}, options={})
+ relationship_props = self.class.extract_relationship_attributes!(attributes)
+ writer_method_props = extract_writer_methods!(attributes)
+
+ validate_attributes!(attributes)
+
+ writer_method_props.each do |key, value|
+ self.send("#{key}=", value)
+ end
+
super(attributes, options)
- (@changed_attributes || {}).clear
end
def save_properties
@previously_changed = changes
- @changed_attributes.clear
+ changed_attributes.clear
end
+ # Returning nil when we get ActiveAttr::UnknownAttributeError from ActiveAttr
+ def read_attribute(name)
+ super(name)
+ rescue ActiveAttr::UnknownAttributeError
+ nil
+ end
+ alias_method :[], :read_attribute
+
+ private
+
+ # Changes attributes hash to remove relationship keys
+ # Raises an error if there are any keys left which haven't been defined as properties on the model
+ def validate_attributes!(attributes)
+ invalid_properties = attributes.keys.map(&:to_s) - self.attributes.keys
+ raise UndefinedPropertyError, "Undefined properties: #{invalid_properties.join(',')}" if invalid_properties.size > 0
+ end
+
+ def extract_writer_methods!(attributes)
+ attributes.keys.inject({}) do |writer_method_props, key|
+ writer_method_props[key] = attributes.delete(key) if self.respond_to?("#{key}=")
+
+ writer_method_props
+ end
+ end
+
module ClassMethods
def property(name, options={})
# Magic properties
options[:type] = DateTime if name.to_sym == :created_at || name.to_sym == :updated_at
@@ -32,9 +68,19 @@
super(name, options)
define_method("#{name}=") do |value|
typecast_value = typecast_attribute(typecaster_for(self.class._attribute_type(name)), value)
send("#{name}_will_change!") unless typecast_value == read_attribute(name)
super(value)
+ end
+ end
+
+ # Extracts keys from attributes hash which are relationships of the model
+ # TODO: Validate separately that relationships are getting the right values? Perhaps also store the values and persist relationships on save?
+ def extract_relationship_attributes!(attributes)
+ attributes.keys.inject({}) do |relationship_props, key|
+ relationship_props[key] = attributes.delete(key) if self.has_relationship?(key)
+
+ relationship_props
end
end
end
end