Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

[RFR] Add support for arrays of references in fetchRelatedRecords #2461

Merged
merged 1 commit into from
Oct 23, 2018
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
41 changes: 33 additions & 8 deletions packages/ra-ui-materialui/src/button/ExportButton.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,38 @@ const sanitizeRestProps = ({
...rest
}) => rest;

/**
* Extracts, aggregates and deduplicates the ids of related records
*
* @example
* const books = [
* { id: 1, author_id: 123, title: 'Pride and Prejudice' },
* { id: 2, author_id: 123, title: 'Sense and Sensibility' },
* { id: 3, author_id: 456, title: 'War and Peace' },
* ];
* getRelatedIds(books, 'author_id'); => [123, 456]
*
* @example
* const books = [
* { id: 1, tag_ids: [1, 2], title: 'Pride and Prejudice' },
* { id: 2, tag_ids: [2, 3], title: 'Sense and Sensibility' },
* { id: 3, tag_ids: [4], title: 'War and Peace' },
* ];
* getRelatedIds(records, 'tag_ids'); => [1, 2, 3, 4]
*
* @param {Object[]} records An array of records
* @param {string} field the identifier of the record field to use
*/
export const getRelatedIds = (records, field) =>
Array.from(
new Set(
records
.filter(record => record[field] != null)
.map(record => record[field])
.reduce((ids, value) => ids.concat(value), [])
)
);

/**
* Helper function for calling the data provider with GET_MANY
* via redux and saga, and getting a Promise in return
Expand All @@ -32,16 +64,9 @@ const sanitizeRestProps = ({
*/
const fetchRelatedRecords = dispatch => (data, field, resource) =>
new Promise((resolve, reject) => {
const sanitizedData = data
.filter(record => record[field])
.map(record => record[field]);

// find unique keys
const ids = Array.from(new Set(sanitizedData));

dispatch({
type: CRUD_GET_MANY,
payload: { ids },
payload: { ids: getRelatedIds(data, field) },
meta: {
resource,
fetch: GET_MANY,
Expand Down
30 changes: 30 additions & 0 deletions packages/ra-ui-materialui/src/button/ExportButton.spec.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,30 @@
import { getRelatedIds } from './ExportButton';

describe('ExportButton', () => {
describe('getRelatedIds', () => {
it('should ignore null or undefined values', () => {
const books = [
{ id: 1, author_id: 123, title: 'Pride and Prejudice' },
{ id: 2, author_id: null },
{ id: 3 },
];
expect(getRelatedIds(books, 'author_id')).toEqual([123]);
});
it('should aggregate scalar related ids', () => {
const books = [
{ id: 1, author_id: 123, title: 'Pride and Prejudice' },
{ id: 2, author_id: 123, title: 'Sense and Sensibility' },
{ id: 3, author_id: 456, title: 'War and Peace' },
];
expect(getRelatedIds(books, 'author_id')).toEqual([123, 456]);
});
it('should aggregate arrays of related ids', () => {
const books = [
{ id: 1, tag_ids: [1, 2], title: 'Pride and Prejudice' },
{ id: 2, tag_ids: [2, 3], title: 'Sense and Sensibility' },
{ id: 3, tag_ids: [4], title: 'War and Peace' },
];
expect(getRelatedIds(books, 'tag_ids')).toEqual([1, 2, 3, 4]);
});
});
});