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

More array functions for models / collections #51

Open
NonPolynomial opened this issue Feb 1, 2020 · 8 comments
Open

More array functions for models / collections #51

NonPolynomial opened this issue Feb 1, 2020 · 8 comments

Comments

@NonPolynomial
Copy link

The collection already has filter, slice and sort.
But it would be nice to also have map, forEach (could also be each) and reduce.

@samselikoff
Copy link
Contributor

Yes – we actually used to do this but what makes it hard is that those methods don't necessarily return Collections (because you can return anything from them). A Collection needs a modelName property on it so it can be properly serialized.

It was also causing issues because folks thought collections were real JS arrays and they were trying to use Lodash methods on them and they were breaking in unexpected ways.

I'm not sure what I would do today + whether there's now a way to truly actually subclass arrays in JS.

Today the escape hatch is to do collection.models to access the underlying JavaScript Array of models and go to town on it.

@NonPolynomial
Copy link
Author

Today the escape hatch is to do collection.models to access the underlying JavaScript Array of models and go to town on it.

thats what I currently use at the moment

It was also causing issues because folks thought collections were real JS arrays and they were trying to use Lodash methods on them and they were breaking in unexpected ways.

and using alternative function names?
e.g. forEach -> each

@samselikoff
Copy link
Contributor

Yeah we could I'm just hesitant because it feels like extra APIs to support, it's something new to learn, and folks could still get confused and try to use libs like lodash on them. .models or toArray() feels like a decent middleground.

Could you share with me your use case (the last time you used one of those methods)?

@NonPolynomial
Copy link
Author

I did a prototype for an App-Store, just to refresh some Angular basics.
So i had the models App and Rating
and the relation App --|1:n|-> Rating
I read in the documentation that association just works with belongTo but not with hasMany and I wanted to create random ratings for my apps when I call server.createList('app', 4) and to add a calculated field of the total rating, that the "frontend" doesn't have to calculate it itself.

If I had such array function it would be a little easier to achieve.

Or I totally missed something about calculated fields in the docs 😁

@samselikoff
Copy link
Contributor

I would use the afterCreate factory hook along with a trait for this:

import { Server, Model, Factory, trait } from 'miragejs';

new Server({
  models: {
    app: Model.extend({
      ratings: hasMany()
    }),
    rating: Model
  },

  factories: {
    app: {
      withRatings: trait({
        afterCreate(app, server) {
          app.update({
            ratings: server.createList('rating', 3, { app })
          })
        }
      })
    }
  },

  seeds(server) {
    server.createList('app', 4, 'withRatings') // boom, 4 apps with ratings
  }
})

Of course that afterCreate hook can do anything, make a random number of ratings, use other traits on the rating factory and so on.

@NonPolynomial
Copy link
Author

NonPolynomial commented Feb 5, 2020

I know, but the problem wasn't to create the related ratings but to add a calculated field in each app for the total rating

e.g.

App
- ratings:
  - rating: 5 stars
  - rating: 4 stars
  - rating 3 stars
- totalRating: 4 stars

those array functions would make it more easy to iterate over the ratings of an app to calculate such a field

@samselikoff
Copy link
Contributor

Ahh I see. Yes, unfortunately we don't have good support for this right now, it's definitely a gap in Mirage that will be closed (sooner rather than later because people keep running into it).

Does it have to be on the model or just the response? If response, I would use the Serializer layer to add computed/derived fields. Most likely in the serialize() hook https://miragejs.com/api/classes/serializer/#serialize

@samselikoff
Copy link
Contributor

Related #45

@samselikoff samselikoff transferred this issue from miragejs/miragejs Mar 22, 2020
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants