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

Conditionally cached? #153

Closed
dustinfarris opened this issue Dec 27, 2016 · 2 comments
Closed

Conditionally cached? #153

dustinfarris opened this issue Dec 27, 2016 · 2 comments

Comments

@dustinfarris
Copy link
Contributor

Is it possible to do a @cached query but actually do the query if it turns out the model doesn't exist on the client?

My scenario (continuing from #141):

  • User visits /items/new and fills out a form, clicks "Create!"
  • cashay.mutate('createItem' ... is executed with a pre-made unique id
  • even though the server has not responded yet, user is immediately redirected to /items/123 where "123" is the client-generated unique id
  • the detail component executes cashay.query(getItemQuery ... which hits the server

In this scenario, the data for the detail route is already on the client, because the client filled out a form. But going forward, if the user visits this page, it will need to retrieve data from the server.

Is there a way to sometimes check cache, sometimes not?

@mattkrick
Copy link
Owner

mattkrick commented Dec 27, 2016 via email

@dustinfarris
Copy link
Contributor Author

dustinfarris commented Dec 28, 2016

This is what I had to do to make all of this work. The last piece of the puzzle was using ops in the mutation. I have to create a dummy "cached" query so that the createItem mutation knows to add subfields. That query has to match an actual query that will be used by the detail page. Both queries need the same op name and key. The mutation needs to specify the key in ops. (all this is necessary to prevent cashay from doing a second server request for data it already has)

@mattkrick am I on the right track here?

// controllers/new.js
...
// this just generates a new uuid to use
new_item_id: computed(function() { return uuid.v4() }).volatile()
...
<!-- new.hbs -->

{{new-item item_id=new_item_id create=(route-action "createItemAndRedirect")}}
// components/new-item.js

const newItemQuery = `
{
  item @cached(id: $item_id, type: "Item") {
    id
    name
  }
}
`;

const stateToComputed = (state, { item_id }) => {
  const { data: { item } } = cashay.query(newItemQuery, {
    op: 'item-detail',
    key: item_id,
    mutationHandlers: {
      createItem(optimistic, response, current) {
        if (optimistic) {
          Object.assign(current.item, optimistic.item_details);
          return current;
        }
      }
    },
    variables: { item_id }
  });
  return { item: Object.assign({}, item, { id: item_id }) };
};

const CreateItem = Component.extend({
  createItem: task(function *(changeset) {
    yield this.sendAction('create', Object.assign({}, this.get('item'), changeset.get('change')));
  }).drop(),

  layout: hbs`
  
  {{create-item-form
    changeset=(changeset item)
    submit=(perform createItem)
  }}
  
  `
});

export default connect(stateToComputed)(CreateItem);
// routes/application.js

...
actions: {
  createItemAndRedirect(item_details) {
    cashay.mutate('createItem', {
      variables: { item_details },
      ops: {
        'item-detail': item_details.id
      }
    });
    this.transitionTo('detail', item_details.id);
  }
}
// components/item-detail.js

// this is the same query used in new-item only without @cached
const itemQuery = `
{
  item (id: $item_id) {
    id
    name
  }
}
`;

const stateToComputed = (state, { item_id }) => {
  const { data: { item } } = cashay.query(itemQuery, {
    op: 'item-detail',
    key: item_id,
    variables: { item_id }
  });
  return { item };
};

...

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