ember-model icon indicating copy to clipboard operation
ember-model copied to clipboard

Allow models to be loaded from outside of adapter

Open bguiz opened this issue 11 years ago • 6 comments

I would like to be able to load models from outside of the adapter, for example within the model hook of Ember.Route. Currently this is only possible through the interface defined by the adapter.

This is fine at a particular level of abstraction. However, let's say we wish to do make the AJAX request within the Ember.Router's model hook, instead of within Ember.Foo.adapater's findAll hook, because we require access to context available to the route, but not within the adapter. There is currently no way to accomplish this.

Thus I propose that we add a means to allow models to be loaded directly using Ember.Model instead of Ember.Model.adapter.

bguiz avatar Mar 05 '14 02:03 bguiz

Submitted a pull request:

https://github.com/ebryn/ember-model/pull/318

This is how I would do loadAll - as a counterpart to findAll. Of course, more work needs to be done for counterparts to the other find* functions. I'll be happy to work on those and add them to this PR if I am going down the right track with this.

bguiz avatar Mar 05 '14 02:03 bguiz

Correct me if I'm wrong but doesn't Em.Model.load() already do this?

narkeeso avatar Mar 05 '14 05:03 narkeeso

This is Ember.Model.load(), and I have marked the code path that it goes through when you call it with that. Hence I'm suggesting an alternative path.

load: function(hashes) {
if (Ember.typeOf(hashes) !== 'array') { hashes = [hashes]; }

if (!this.sideloadedData) { this.sideloadedData = {}; }

for (var i = 0, l = hashes.length; i < l; i++) {
  var hash = hashes[i],
      primaryKey = hash[get(this, 'primaryKey')],
      record = this.getCachedReferenceRecord(primaryKey); //returns undefined

  if (record) {
    record.load(primaryKey, hash); // <-- instead of going here
  } else {
    this.sideloadedData[primaryKey] = hash; // <-- goes here instead
  }
}
},

@narkeeso I'd like to know if you are able to make Ember.Model.load() work this way. Perhaps there is a means for me to prime the cached reference records which I am missing?

bguiz avatar Mar 05 '14 05:03 bguiz

@ebryn

Can you please further describe your use case?

The specifics of my use case are that I want to be able to, from outside of the Adapter. I would like to be able to makes my AJAX request and populate the Model from within the model hook of a Route.

The reason why I want to do it from outside the Adapter is because I need access to the instance of the current route, and access to a specific controller - an instance of subclass of AuthenticatedRoute and this.controllerFor('auth') (both contain state and utility methods related to current authentication). I cannot gain access to these from within the Adapter methods. Furthermore, this issue I raised on EmberJs - https://github.com/emberjs/ember.js/issues/4461 - compounds this issue for me.

Alternatively, I could do it from within the Adapter, and I think that this would be more aligned with the purpose of the Adapter. However, a means to pass in a reference, or otherwise obtain, the current Route is needed.

At first glance this doesn't seem like it belongs on the Model class, but instead on RecordArray since it's basically just a convenience method for instantiating a RecordArray.

Actually, the state of the Model mutates, thanks to this line: this._findAllRecordArray = Ember.RecordArray.create(...

So it is more than instantiating a RecordArray - it is about adding that to the Model's internal cache too.

Also, please write a test.

I'm not sure if I am going down the right track with this at the moment, and hen I am I'll be happy to do write tests for this.

For example, you might think it is a better idea to add a means to obtain the current Route from within the Adapter methods.

bguiz avatar Mar 05 '14 22:03 bguiz

@bguiz Why do you need to access the route from the adapter? Can you put together a simple JSBin example of what you're trying to accomplish?

ebryn avatar Mar 17 '14 02:03 ebryn

Why do you need to access the route from the adapter? Can you put together a simple JSBin example of what you're trying to accomplish?

@ebryn Ideally would like to be able to access any named controller from methods within adapters. My use case is that a model needs to determine the API URL based on the currently logged in user.

//HACK created a singleton because there is no way to access within adapter methods
var authController = App.getAuthController(); 
var apiUrl = App.apiUrl+'/user/'+authController.get('userSlug')+'/foos';
//perform AJAX request

That is what I am doing at the moment as a workaround within most of my model adapters. It is rather hacky, because I had to store a reference to the controller that I need against the global App object - not ideal.

bguiz avatar Jun 12 '14 01:06 bguiz