deep-jade
deep-jadeβ€’2y ago

Composite Primary Keys recommendations

Hey Refine-Team, hello Discord! Thank you for refine, it's a really good solution and has provided a lot of "wow" effects for the people I work with over the last couple of weeks. We are building a CRUD-UI using Refine for some pretty large databases, spanning 9 dbs over multiple hundred tables. We have a specification that is asking for composite-primary-key (CPK) access. Meaning I have an API that is offering access to a resource like this /post/:id/:locale_id/:provider_id. All keys must be provided for the CPK to access the correct resource. I found the BaseRecord and BaseKey interface I'd probably override?
export type BaseKey = string | number;
export type BaseRecord = {
id?: BaseKey;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
};
export type BaseKey = string | number;
export type BaseRecord = {
id?: BaseKey;
// eslint-disable-next-line @typescript-eslint/no-explicit-any
[key: string]: any;
};
I guess I will have to write another dataProvider with extended functionality for this. Maybe someone has done something similar already, any help or hint is appreciated!
30 Replies
kapa.ai
kapa.aiβ€’2y ago
Hi @bastianwegge. I'm kapa.ai, your friendly support bot. I will try to answer your question by searching through the knowledge base. :wave:
kapa.ai
kapa.aiβ€’2y ago
---------------------- Hello! I'm glad to hear that refine has been helpful for your projects. Regarding your question about composite-primary-key (CPK) access, you're on the right track with the idea of creating a custom dataProvider to handle this specific use case. Unfortunately, the information extracts I have don't provide a direct example of implementing a dataProvider for composite-primary-keys. However, you can refer to the documentation on dataProvider (https://refine.dev/docs/api-reference/core/providers/data-provider/) to understand how to create a custom dataProvider and adapt it to your specific needs. When creating your custom dataProvider, you'll need to implement the necessary methods (e.g., getList, getOne, create, update, deleteOne, etc.) to handle the composite-primary-keys in the API requests. You can use the BaseRecord and BaseKey interfaces as a starting point and extend them as needed. I hope this helps you get started on implementing the custom dataProvider for your project. Good luck! ---------------------- Note: you can ask me a follow up question by @ mentioning me again :speech_balloon: ----------------------
Data Provider | refine
TheΒ data providerΒ acts as a data layer for your app that makes the HTTP requests and encapsulates how the data is retrieved. refine consumes these methods via data hooks.
kapa.ai
kapa.aiβ€’2y ago
<@317433576721219584> kapa.ai is still learning and improving, please let us how it did by reacting below
Omer
Omerβ€’2y ago
Hey @bastianwegge πŸ‘‹ , Wow, greetings to the team that brings beauty to our day! My suggestion would have been similar, I believe that you can access what you want by using a custom dataProvider and meta (https://refine.dev/docs/tutorial/understanding-dataprovider/create-dataprovider/#meta-usage). If you encounter any issues during implementation, please don't hesitate to ask questions. Helping you would make us happy.
deep-jade
deep-jadeβ€’2y ago
@Omer so you would use :locale_id and :provider_id in meta ... πŸ€” These aren't (unfortunately) things I could provide through something like a HOC or Context. It's rather a Composite-Primary-Key for the list that comes back from the server. That's why I thought I'd adjust the BaseKey property, which I will try now. I haven't gotten into the details yet and I'm not very deep in refine's implementation. So I get a list with: - id: 5, locale_id: 1, provider_id: 2 - id: 5, locale_id: 2, provider_id: 3 - id: 5, locale_id: 3, provider_id: 4 When I click on "view" on the first element I want to have a route like: - /post/:id/:locale_id/:provider_id - so /post/5/1/2 If that makes sense at all πŸ˜… Before anybody's answering, Γ–mer you were completely right ! πŸš€
Omer
Omerβ€’2y ago
We support the use of 'meta' within the routes, but it has not yet been documented. @aliemirs can provide us with some information
deep-jade
deep-jadeβ€’2y ago
There's a hint that resources can take meta here: https://refine.dev/docs/tutorial/understanding-resources/index/#defining-actions-for-a-resource)
{
name: "blog_posts",
edit: "/blog-posts/edit/:id/:version",
}
{
name: "blog_posts",
edit: "/blog-posts/edit/:id/:version",
}
But how am I supposed to give meta to this object?
{
name: "blog_posts",
edit: "/blog-posts/edit/:id/:version",
meta: {
locale_id: 'locale_id',
provider_id: 'provider_id',
}
}
{
name: "blog_posts",
edit: "/blog-posts/edit/:id/:version",
meta: {
locale_id: 'locale_id',
provider_id: 'provider_id',
}
}
The solution above does not seem to work. I found out though that I can pass meta indirectly to the buttons (I'm using antd) like this:
<ShowButton
hideText
size="small"
recordItemId={record.id}
meta={{ provider_id: record.provider_id, locale_id: record.locale_id }}
/>
<ShowButton
hideText
size="small"
recordItemId={record.id}
meta={{ provider_id: record.provider_id, locale_id: record.locale_id }}
/>
Yeah @Omer that's what I'm stumbling across right now I guess πŸ˜„
Omer
Omerβ€’2y ago
Wow, you have already discovered the 'meta' usage that I was referring to, haha I am really impressed 🍻
deep-jade
deep-jadeβ€’2y ago
By accident I guess :D. The button shows the correct link and the router resolves the correct route. But when I'm accessing that link, the dataProvider does not get the meta information I referenced.
Omer
Omerβ€’2y ago
I think we are not passing the resource 'meta' to the data providers. For now, you should do this manually, but if you create a GitHub Feat issue, we can prioritize the automatic transfer of the 'meta' information.
deep-jade
deep-jadeβ€’2y ago
Do you mean passing the same meta to useTable? Or to useOne ? useOne Meta usage is mentioned in the docs, I tried to get to the Show page using the inferencer (because I'm lazy), but that didn't work unfortunately πŸ˜„
Omer
Omerβ€’2y ago
Yes, definitely. It makes sense to transfer everything that comes from useParsed or exists in the resource meta
deep-jade
deep-jadeβ€’2y ago
Alright, I'm gonna try that. Thanks a lot!
Omer
Omerβ€’2y ago
Ah, yes, you cannot do this with the inferencer 😦 Creating pages seems like the most logical option.
deep-jade
deep-jadeβ€’2y ago
If only I wasn't lazy πŸ™ˆ