activegraph icon indicating copy to clipboard operation
activegraph copied to clipboard

idea: polymorphic association handling improvement

Open jorroll opened this issue 6 years ago • 0 comments

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:

  1. Update the has_many and has_one methods to return a simple ActiveRel class that can be assigned to a constant (e.g. class Person; FriendRel = has_many :out, :friends, type: :FRIEND, model_class: :Person; end)
  2. Add an active_node_model.path() method (and association_proxy.path() method) that accepts an array of ActiveRel models as input and uses the ActiveRel 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.
  1. 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-generic ActiveRel 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.

jorroll avatar Mar 28 '18 08:03 jorroll