diff --git a/CHANGELOG.md b/CHANGELOG.md index 262c82d64..d6a556455 100644 --- a/CHANGELOG.md +++ b/CHANGELOG.md @@ -6,6 +6,16 @@ This project adheres to [Semantic Versioning](http://semver.org/). ## [Unreleased][unreleased] - Nothing yet, placeholder +### Fixed +- Longstanding bug that would prevent association changes (`<<` and ActiveRel.create) in Rails after `reload!` had been called, see https://github.com/neo4jrb/neo4j/pull/839 + +### Changed +- In the absense of a `model_class` key, associations defined in ActiveNode models will use `from_/to_class` defined in `rel_class` to find destination. (Huge thanks to @olance, #838) +- ActiveRel's DSL was made a bit friendlier by making the `type`, `from_class` and `to_class` methods return their set values when called without arguments. + +### Added +- ActiveRel was given `find_or_create_by`, usable across single associations. + ## [5.0.0] - 2015-06-18 ### Fixed diff --git a/lib/neo4j/active_node/query/query_proxy.rb b/lib/neo4j/active_node/query/query_proxy.rb index 3f7b39e7c..2ea741ca8 100644 --- a/lib/neo4j/active_node/query/query_proxy.rb +++ b/lib/neo4j/active_node/query/query_proxy.rb @@ -192,7 +192,7 @@ def _nodeify!(*args) (arg.is_a?(Integer) || arg.is_a?(String)) ? @model.find_by(@model.id_property_name => arg) : arg end.compact - if @model && other_nodes.any? { |other_node| !other_node.is_a?(@model) } + if @model && other_nodes.any? { |other_node| !other_node.class.mapped_label_names.include?(@model.mapped_label_name) } fail ArgumentError, "Node must be of the association's class when model is specified" end diff --git a/lib/neo4j/active_rel/persistence.rb b/lib/neo4j/active_rel/persistence.rb index e69a7e683..62a886892 100644 --- a/lib/neo4j/active_rel/persistence.rb +++ b/lib/neo4j/active_rel/persistence.rb @@ -60,10 +60,16 @@ def validate_node_classes! next if [:any, false].include?(type_class) - fail ModelClassInvalidError, "Node class was #{node.class}, expected #{type_class}" unless node.is_a?(type_class.to_s.constantize) + unless node.class.mapped_label_names.include?(type_class.to_s.constantize.mapped_label_name) + fail ModelClassInvalidError, type_validation_error_message(node, type_class) + end end end + def type_validation_error_message(node, type_class) + "Node class was #{node.class} (#{node.class.object_id}), expected #{type_class} (#{type_class.object_id})" + end + def _create_rel(from_node, to_node, *args) props = self.class.default_property_values(self) props.merge!(args[0]) if args[0].is_a?(Hash) @@ -75,8 +81,6 @@ def _create_rel(from_node, to_node, *args) _rel_creation_query(from_node, to_node, props) end - private - N1_N2_STRING = 'n1, n2' ACTIVEREL_NODE_MATCH_STRING = 'ID(n1) = {n1_neo_id} AND ID(n2) = {n2_neo_id}' def _rel_creation_query(from_node, to_node, props)