activegraph
activegraph copied to clipboard
idea: polymorphic association handling improvement
Note: what follows isn't something I have time to implement at the moment, but I wanted to record the idea for possible future use.
Idea to improve polymorphic association handling:
- Update the
has_many
andhas_one
methods to return a simpleActiveRel
class that can be assigned to a constant (e.g.class Person; FriendRel = has_many :out, :friends, type: :FRIEND, model_class: :Person; end
) - Add an
active_node_model.path()
method (andassociation_proxy.path()
method) that accepts an array ofActiveRel
models as input and uses theActiveRel
models to construct a query / association chain.
person.path(
Person::EmployerRel,
Organization::EquipmentRel,
Saw::UserRel
)
# MATCH (person)-[:EMPLOYER]->(node342:`Organization`)
# MATCH (node342)-[:EQUIPMENT]->(equip) #<-- polymorphic
# WHERE equip:`Saw` OR equip:`Hammer` OR equip:`Nail`
# MATCH (equip)-[:USER]->(node523:`Person`)
OR use path()
alongside traditional association chaining
person.employer.equipment.path(Saw::UserRel).employer
# MATCH (person)-[:EMPLOYER]->(node342:`Organization`)
# MATCH (node342)-[:EQUIPMENT]->(equip) #<-- polymorphic
# WHERE equip:`Saw` OR equip:`Hammer` OR equip:`Nail`
# MATCH (equip)-[:USER]->(node523:`Person`)
# MATCH (node523)-[:EMPLOYER]->(node353:`Organization`)
- This would be an improvement over the current
query_as()
+proxy_as()
way of doing polymorphic association chaining.
- when performing deep eager loading, a developer could supply an
ActiveRel
class instead of an association method name. This would allow deep eager loading of polymorphic associations.
person.employer.with_associations(equipment: {Saw::UserRel => :employer}, :employees)
Implications of this change
-
Currently, if you load a relation and an ActiveRel class exists for that relation, neo4jrb uses the
ActiveRel
class as a wrapper. Otherwise, neo4jrb uses a generic class to wrap the relation. This change would greatly increase the number of non-genericActiveRel
wrappers. In many apps, I could see every relation being associated with an ActiveRel class. -
It would be pretty easy for a developer to end up with what are essentially duplicate
ActiveRel
classes. i.e.
class Person
EmployerRel = has_one :out, :employer, type: :EMPLOYER, model_class: :Organization
end
class Organization
EmployeeRel = has_one :in, :employee, type: :EMPLOYER, model_class: :Person
end
I'm not sure what, if any, steps ActiveRel
currently takes to avoid duplicate relations or how ActiveRel
figures out which class to wrap a loaded relation in, but the EmployeeRel
/EmployerRel
scenario needs some consideration.