Skip to content

Commit

Permalink
Merge pull request #2461 from marmelab/export-one-to-many
Browse files Browse the repository at this point in the history
[RFR] Add support for arrays of references in fetchRelatedRecords
  • Loading branch information
Gildas Garcia authored Oct 23, 2018
2 parents b8b3a26 + 4aed575 commit e0c37c0
Show file tree
Hide file tree
Showing 2 changed files with 63 additions and 8 deletions.
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]);
});
});
});

0 comments on commit e0c37c0

Please sign in to comment.