-
Notifications
You must be signed in to change notification settings - Fork 23
Creating relationships between resources
- Create relationships between resources using member_ids.
- Create a relationship by including a full resource in another resource.
In this step we will make page resources members of the book resource. Normally, you would save the pages before making them a member of another resource. As a side effect of saving, an id will be assigned to the pages.
As a general good practice, DON'T assign ids. We assign ids in the example below only to demonstrate how member_ids works before we'd discussed persistence of resources which will generate IDs. |
For some persistence adapters, assigning an ID ok acceptable and they will use the assigned id. But for others, they have their own way of assigning IDs to address defined behaviors in the adapter's backing data source (e.g. Postgres) as in primary key constraints, and so it is appropriate to delegate this action to the adapter on save. |
You can assign alternate_ids
if an attribute for alternate_ids
is defined in the resource definition. As an example, Hyrax uses alternate ids to hold the GUIDs created separately by the Hyrax system and which are used as part of the URL for accessing items.
> page1 = Page.new
> page1.id = "page_1"
=> "page_1"
> page1.id
=> #<Valkyrie::ID:... @id="page_1">
> page2 = Page.new(id: "page_2")
> page3 = Page.new(id: "page_3")
Assigning member_ids
allow operators similar to those supported by Arrays.
> book = Book.new
> book.member_ids = page1.id
=> #<Valkyrie::ID:... @id="page_1">
> book.member_ids
=> [#<Valkyrie::ID:... @id="page_1">]
> book.member_ids << page2.id
=> [#<Valkyrie::ID:... @id="page_1">, #<Valkyrie::ID:... @id="page_2">]
> book.member_ids += [page3.id]
=> [#<Valkyrie::ID:... @id="page_1">, #<Valkyrie::ID:... @id="page_2">, #<Valkyrie::ID:... @id="page_3">]
Create a cover art resource for the book.
> cover_art = CoverArt.new(id: 'cover_art1', alternate_ids: 'ca1', artists: 'Mary GrandPré')
=> #<CoverArt id=nil internal_resource="CoverArt" created_at=nil updated_at=nil new_record=true alternate_ids=[#<Valkyrie::ID:... @id="ca1">] artists=["Mary GrandPré"] image_id=nil>
Let's try and assign the cover art the same way we did member_ids. Notice that it tries to coerce the cover art's id into an instance of CoverArt and raises an exception when it fails.
> book.cover_art = cover_art.id
=> Dry::Struct::Error ([CoverArt.new] can't convert Valkyrie::ID into Hash)
When correctly setting the cover art on the book resource, the entire object is copied into the book resource.
> book.cover_art = cover_art
> book.cover_art
=> [#<CoverArt id='cover_art1' internal_resource="CoverArt" created_at=nil updated_at=nil new_record=true alternate_ids=[#<Valkyrie::ID:... @id="ca1">] artists=["Mary GrandPré"] image_id=nil>]
One last thing to notice, updating the cover_art resource also updates cover_art in the book.
> book.cover_art.first.artists # BEFORE the update
=> ["Mary GrandPré"]
> cover_art.artists += ["Kazu Kibuishi", "Brian Selznick"]
# ["Mary GrandPré", "Kazu Kibuishi", "Brian Selznick"]
Reflected in the book...
> book.cover_art.first.artists # AFTER the update
=> ["Mary GrandPré", "Kazu Kibuishi", "Brian Selznick"]
Potential advanced exercise: How would you update a specific cover_art resource saved in the book's Array of cover_art resources?