Add references parameter to relationships#1188
Conversation
| t.field "material", "Material" | ||
| t.relates_to_many "components", "Component", via: "part_ids", dir: :in, singular: "component" | ||
| t.relates_to_one "manufacturer", "Manufacturer", via: "manufacturer_id", dir: :out | ||
| t.relates_to_one "manufacturer_by_guid", "Manufacturer", via: "manufacturer_guid", references: "guid", dir: :out |
There was a problem hiding this comment.
Instead of adding a new relationship--which isn't exercised by any acceptance tests to demonstrate that references works end-to-end--can we update some existing relationships? In particular:
- Let's find relationships that are used by both GraphQL acceptance tests and indexing
source_fromrelationships in acceptance tests, and update them - Let's cover both a
_oneand_manyrelationship - Let's cover both a
dir: :inand adir: :outrelationship
...maybe even cover the combination those dimensions.
Here's what I'm concerned about: you've demonstrated via this test schema change that references: shows up in the runtime metadata as you expect, but you haven't demonstrated that it works for GraphQL relationships or for sourced_from indexing relationships.
I don't think we need to retain any relationships that rely on the default of "id"--as I see it, if a feature works end-to-end for references: "arbitrary_string" then we can trust it'll work for the default of "id", too. But the opposite is not true: there may be behavior that works for "id" that does not work for an alternate references: value due to us hardcoding "id" in some spots that you missed. Updating relationships to use a specific references option (with a different value than "id") is a forcing function to make sure we've updated all the spots that hardcoded "id" before.
So I guess one option is we could update every relationship to use an alternate reference field but that's probably overkill--just make sure we've covered examples of all the cases so we're sure that all code paths are covered.
There was a problem hiding this comment.
It's concerning that you updated this file without changing any unit, integration, or acceptance tests in elasticgraph-graphql. That means that someone could revert these to the hardcoded "id" in the future and our test suite wouldn't catch it!
With my suggestion on config/schema/widgets.rb to update the existing relationships, we should gain a bit of automatic acceptance test coverage of this. In addition, it would be good to update https://github.com/block/elasticgraph/blob/main/elasticgraph-graphql/spec/integration/elastic_graph/graphql/resolvers/nested_relationships_spec.rb to exercise this. Similar to my request above, it would be good to cover the various cases (in/out, many/one, etc) with a references: override to prove it works.
|
Here's the current state of this PR (which I know is failing CI, despite passing I ran into a bunch of issues trying to make this When you have a relationship between indexed types: Widget.relates_to_one "manufacturer", via: "manufacturer_id" ...ElasticGraph assumes this flow:
i.e. It would be a pretty big change I think to change this assumption everywhere it is relied upon. With that said, I messed around a little with embedded (i.e. not indexed) types, because embedded types don't have document I tried to show this working by adding some new types to the example Widgets schema and adding a graphql acceptance test for it. Obviously not ideal to add a bunch of models just to show this, but no existing relationships covered what I wanted to see for this. And I'm doubtful that this feature in this state would be acceptable anyway so I'm not exactly proposing adding those to the schema on main. Overall, it feels kind of hacky to me to add all this code to only support configurable |
At the end of the day, I'm in favor of removing this assumption, if we can do it safely and correctly. As I see it, But I think that to remove the assumption, this will have to be broken down into smaller sub-problems that we can tackle individually. It's too much to tackle in one PR.
Agree that would be hacky. If we're going to support For now I've converted this back to draft. |
Summary
Adds a
referencesparameter torelates_to_oneandrelates_to_manythat allows specifying which field the foreign key points to, instead of always assumingid. Defaults to"id"for backward compatibility.Changes
relates_to_oneandrelates_to_manyaccept an optionalreferences:keyword (default"id")Relationship, passed through runtime metadata, and used byRelationJoinat query timeregister_inferred_foreign_key_fieldsusesreferencesinstead of hardcoded"id"validate_referencesinRelationshipResolverto validate the field exists (for:out) and is anIDtypeManufacturer.guidand parallel relationships exercising both directions