miragejs / discuss

Ask questions, get help, and share what you've built with Mirage
MIT License
2 stars 0 forks source link

Merging real data with Mirage data. #19

Open alexabreu opened 5 years ago

alexabreu commented 5 years ago

Feature request

Is it currently or could it be possible to use fake/seeded data in combination with real data being requested via Mirage's passthrough feature? In my case, I'd like to create records via Mirage which are tied to a real user in our system. I can't, however, figure out how to delay Mirage initialization until after the user has been loaded. My hope would be able to use the afterCreate hook to tie a newly created record back to that existing user. Seems like this feature might be related to: miragejs/ember-cli-mirage#1416.

samselikoff commented 5 years ago

Hm can you list out the actual steps in the flow? Will your app be hitting the actual network for one set of endpoints and Mirage for another? I think if I see the steps and where and what you want Mirage to do I could help.

alexabreu commented 4 years ago

Thanks for getting back to me Sam. Yes, the idea would be to mix actual network requests with Mirage requests. Right now the main network request is to retrieve the current user/session.

The steps are as follows:

  1. Seed Mirage with project data. These projects belong to a user. When I seed Mirage, I don't yet have a real user.

In my default scenario:

import { Server } from 'ember-cli-mirage'

export default function(server: Server) {
  /*
    Seed your development database using your factories.
    This data will not be loaded in your tests.
  */
  server.createList('project', 3)
}
  1. In app/routes/application.ts, authenticate the user. Right now I'm adding this user to a dev only window.mirage object so I can access it when retrieving projects.
if (this.sessionService.isAuthenticated) {
      const currentUser = await this.store.findRecord('arcgis/user', this.sessionService.credential.userId)
      if (window.mirage) window.mirage.currentUser = currentUser
      return currentUser
    }

I'm using window here because I couldn't figure out a way to get a handle on the store or `services from within the mirage config.

  1. In mirage/config.js project route handler update the fake Mirage projects with the real user.
this.get('/ArcGIS/rest/services/collector/projects', schema => {
    const projects = schema.projects.all()
    projects.update('ownerId', window.mirage.currentUser.portalId)
    return projects
  })

My thought is it would nice to have control over when seeding Mirage takes place. That way, I could use my authenticated user during data creation rather than having to modify the data as it's being retrieved. Is there a better/more miragey way to accomplish my goal? Thanks so much for your help! Also, please let me know if I can provide you with more code/context around my setup.

samselikoff commented 4 years ago

Very interesting.

I haven't hit this situation before but I wonder... Mirage route handlers can be promises so what if you did something like this:

this.get('/auth', (schema, projects) => {
  return fetch('http://localhost:3000/real-auth-endpoint', { some: data })
    .then(res => res.json())
    .then(json => {
      schema.projects.all().update({ ownerId: json.portalId })

      return json;
    })
})

Then at least you could update your Mirage seeds once, on auth.

Another question: why not mock out the auth route too, and keep all data in Mirage?

Another idea: seeds could become async. (Then you could fetch data before initializing). This would be interesting for many possibilities.

Another idea: you could use an initializer that defers application readiness, fetches the user, updates Mirage and then proceeds with the application boot.

samselikoff commented 4 years ago

FYI: Transferred this to our Discuss repo, our new home for more open-ended conversations about Mirage!

If things become more concrete + actionable we can create a tracking issue in the main repo.