Please help shape my mental model around Ember Resources

Hi folks,

I’m exploring using Resources in an app to get a better understanding of the idea behind them. I’m using @NullVoxPopuli 's NullVoxPopuli/ember-resources.

I have 2 questions that I’d love some insight on as I’m not sure I’ve quite got my mental model straight around this concept.

  1. What is the fundamental concept of a “Resource” intended to represent? Is it a network request? Is it a particular piece of data? I’ve seen an example of a generic data fetching Resource but likewise seen an example of a checkbox Resource. Help me crystalize my mental model around this please.

  2. Is a Resource intended to be passed around or just interacted with in its invoking component? The Resource is tied to the lifecycle of the component that creates it which makes me wonder whether it’d be a good practice to pass it around to other components. I suppose it’s pretty common practice to pass around ember-concurrency tasks, so maybe the same applies to Resources too. Can someone clarify this for me please?

Thanks in advance for any insight and clarification you can provide me on this :smiley_cat:

2 Likes

Hello!

If you haven’t already, I think this blog post is a good introduction to the concept, and general problem space: pzuraq | blog | Introducing @use

What is the fundamental concept of a “Resource” intended to represent?

Different people may interpret the purpose / responsibility / etc differently, but to me a “Resource” is a Re-usable collection of state. That state could contain async data information, such as the examples you’ve seen. Or, they could contain, for example, “selection data”:

@tracked initiallySelected = [ ... ];

mySelection = selection(this, () => [initiallySelected]);
// provides:
//   selection.select(item)
//   selection.isSelected(item)
//   selected.isAllSelected
//   selected.isExcluded(item)
//   selected.state // ALL, NONE, SOME, ALL_EXCLUDING 
// etc

(useful for tables, multi-checkbox UIs, etc)

When looking at that, if you squint hard enough, it might look like this pattern:

@tracked initiallySelected = [ ... ];

@cached
get mySelection() {
  let instance = new Selection(this.initialSelected); 
  setOwner(instance, getOwner(this));
  return instance;
}

and that’s it. in a nutshell… for JS use.

But the underlying implementation of all the Resource implementations out there uses invokeHelper as well as Helper Managers. This for extra flexibility in choosing where/how you want to use a Resource.

For example, the selection above, as a resource (if exported at app/helpers/selection, could be used in a template like this:

{{#let (selection @initialSelected) as |mySelection|}}
  {{mySelection.state}}
{{/let}}

This is useful for template-only UIs – which have a huge advantage of using data/state in a backing class: template-only UIs scope responsibility via hierarchy. :tada:

Some example implementations of Resources out in open-source atm:

Is a Resource intended to be passed around or just interacted with in its invoking component?

Resources and concurrency tasks are equivalently tied to the lifecycle of the object they are created on. So if passing concurrency tasks around is your JAM, than passing resources around can be as well. I think this makes a lot of sense for utility-style resources (like the selection example) – as the resources could help prevent / abstract away prop drilling.


Hope this helps!

1 Like

Thanks for the prompt reply Preston.

I have indeed read Chris’ blog post, a few times, and those two questions were sort of what I was left with unanswered.

Thanks for taking the time to respond. It all makes sense and starts to clarify my mental model. I’ll take a look at those linked repos for some extra context.

Thanks again!

1 Like

For me the big thing when I switched some of my data handling to ember-data-resources was that it immediatelly fixed the weird lifecycle problem of loading data in components / services. Data is eventually there when you try to access it, without a need for an explicit kick in constructor or modifier or some other weird method.

So so far for me a resource is a piece of state that provides nice API that fills the gaps where the framework would force you to write quite a lot of quite ugly and possibly buggy code.

All my resources so far live in services. They basically supply ember-data store peekAll method (ish), but without me constantly bumping into problems with lifecycle and unintentionally changing data.

So for me resources are sort-of passed around. If you think that accessing a service resource from many places is “passing around”.

1 Like