Continuation of #1217: Support creating polymorphic has-many relationships#1231
Continuation of #1217: Support creating polymorphic has-many relationships#1231st0012 wants to merge 9 commits intoJSONAPI-Resources:release-0-9from
Conversation
If we create/modify/delete records (via requests) in integration tests, it might affect other tests' test result. The ideal way is to keep integration test data isolated. And by adding database_cleaner, we can make sure database is reset between each test cases.
There was a problem hiding this comment.
Thanks @saravanak and @st0012 This is a good start, but it's not thoroughly tested and further work is needed downstream in the Resource for creating the relationship links.
|
|
||
| assert_jsonapi_response 400, msg: "Submitting a thing as a vehicle should raise a type mismatch error" | ||
| end | ||
|
|
There was a problem hiding this comment.
Let's test cases where multiple vehicles are provided. Tests should include mismatches of types, such as
'relationships' => {
'vehicles' => {'data' => [{'type' => 'car', 'id' => '1'}, {'type' => 'car', 'id' => '2'}]}, #vehicle 2 is actually a boat
}
Test should probably be repeated for updates, though as of now they should go through the same path.
We do this in following steps 1) Get the sub-resource's model class with `Resource.model_hint`'s info 2) Query the records with subclass instead of polymorphic class 3) Return 404 if we get any record not found error The reason to raise RecordNotFound instead of TypeMismatch is that type mismatch means requires 2 conditions: - the id can't be used to find any record in current subclass (Car) - but in the meantime, it does exists for the superclass (Vehicle) And this means we need to perform additional query to prove the second condition, which is kind of a waste.
| begin | ||
| related_records = relationship_klass.find(relationship_key_values[:ids]) | ||
| rescue ActiveRecord::RecordNotFound | ||
| fail JSONAPI::Exceptions::RecordNotFound.new(relationship_key_values[:ids]) |
There was a problem hiding this comment.
The reason to raise RecordNotFound instead of TypeMismatch is that type mismatch requires 2 conditions:
- the id can't be used to find any record in current subclass (Car)
- but in the meantime, it does exists for the superclass (Vehicle)
And this means we need to perform additional query to prove the second condition, which is kind of a waste.
There was a problem hiding this comment.
I tend to agree it's kind of a waste, but from a JSON API perspective it's not known that the backing table is sharing a common set of IDs. So there really isn't a Car with id 2 so the system should raise an error.
There was a problem hiding this comment.
Let's use find_by_keys, like https://github.com/cerebris/jsonapi-resources/blob/master/lib/jsonapi/resource.rb#L251. That way any overrides will get applied. This might be the case if people are doing permission checking for these related resources.
We need to use Resource.records as our query base to invoke user customizations. And because the ivar inheritance, we need to manually call model_name on subclasses to make this work.
| ids = relationship_key_values[:ids] | ||
|
|
||
| related_records = relationship_resource_klass | ||
| .records |
There was a problem hiding this comment.
@lgebhardt for supporting customizations, I think using records is enough. Use find_by_keys will also run includes for this query, which is unncessary.
There was a problem hiding this comment.
I missed this earlier: records needs to be called as records(options)
|
@lgebhardt added tests for update, is there anything missing for merging? |
| ids = relationship_key_values[:ids] | ||
|
|
||
| related_records = relationship_resource_klass | ||
| .records |
There was a problem hiding this comment.
I missed this earlier: records needs to be called as records(options)
| .records | ||
| .where({relationship_resource_klass._primary_key => ids}) | ||
|
|
||
| missed_ids = ids - related_records.map(&:id) |
There was a problem hiding this comment.
We need to account for alternate primary keys, and I think we can skip creating the models so pluck will save a few cycles.
missed_ids = ids - related_records.pluck(relationship_resource_klass._primary_key)| person = Person.find(body.dig("data", "id")) | ||
|
|
||
| assert "Reo", person.name | ||
| assert 2, person.vehicles.count |
There was a problem hiding this comment.
These asserts should be assert_equal. Once fixed this test is failing with only the last vehicle type being created.
a0ec607 to
2081af6
Compare
|
@lgebhardt all updated! |
|
@st0012 Thanks for working on this. I squashed your changes and pushed them to release-0-9 |
This is a continuation of #1217, which fixes its failing tests (thanks for @saravanak's hard work!).
The cause of #1217's failure is data mutation between test cases: the integration test's post request creates a new record, and it fails other tests (under certain execution order). So my additional commit is to keep the database clean (with database_cleaner before/after each integration test suite.
All Submissions:
New Feature Submissions:
Bug fixes and Changes to Core Features:
Test Plan:
Reviewer Checklist: