Ember CLI with PODS nested model


#1

I am using pods for development and the app is in very initial stage.

I have a links settings page which I have added in app/settings/page/link/ in my router.js it looks likes

Router.map(function() {
  this.route('login', {path: '/login'});

  this.route('settings', function() {
    this.route('page', function() {
      this.route('link');
      this.route('groups');
    });
  });
});

I also need to create a model for page links, which I have created in app/settings/page/links folder. When I fetch the page it give me error that WARNING: Encountered "links" in payload, but no model was found for model name "link" (resolved model name using lp@serializer:-rest:.modelNameFromPayloadKey("links"))

So on my rest client I have changed the out put from

{"links":[
       {
         "id":1,
         "display_name":"Page Links",
         "backend_name":"Page Links",
         "url":"settings.page.links",
         "created_by":null,
         "updated_by":null,
         "created_at":"0000-00-00 00:00:00",
         "updated_at":"0000-00-00 00:00:00"
       }
     ]
}

to

{"settings/page/links":[
       {
         "id":1,
         "display_name":"Page Links",
         "backend_name":"Page Links",
         "url":"settings.page.links",
         "created_by":null,
         "updated_by":null,
         "created_at":"0000-00-00 00:00:00",
         "updated_at":"0000-00-00 00:00:00"
       }
     ]
}

I can see that it loaded the data in Ember Inspector. But I dont like how I have to change the REST client to match my model.

Also when I save the page, Ember is sending whole 'settings/page/links/ in the payload

So on the PHP side I have to get it like below, which is not good

$data         = $input->get('settings/page/link');
$display_name = $data['display_name'];
$backend_name = $data['backend_name'];
$url          = $data['url'];

#2

Unfortunately, you have to create your model on root path. I faced similar problem when trying to associate singular-name model with plural-name resource using pods.

So it would be logical to look like this:

/users/controller.js
/users/route.js
/users/model.js // but the model would be plural in this case

If you use ember g model user then it generates user folder with model.js file which is annoying to have half-empty folder on root path.

So my advice for you is not to try structure models under paths even though it really breaks the structure, yes, it is convenient and logical but due to limitations of ember-cli, should be avoided for now.

You can opt for creating a distinct models folder on root path and having all models there or reconciling with having one-folder-with-one-file on top root for each model (which is worse in my opinion).


#3

@igorpreston: I would like to add that you can always use a singular route with a plural path. This is how I do it:

this.route('user', { path: '/users' }, function() {
});

#4

Hello @aamirrajpoot, try the following:

Move your link route outside settings:

 this.route('settings', function() {
  this.route('page', function() {
    this.route('groups');
  });
});
this.route('link', { path: '/settings/page/link' });

Create your model to be at a root level:

$ ember g model link

That way you would should have a file structure like this and you won’t have to prefix your json payload.

/app
  /pods
    /link
      model.js

#5

I will be having more than 200 models in my application, so bringing them on root is not a wise solution for me, that is the reason I am putting all in their groups i.e. settings in settings folder.


#6

In that case, it sounds to me like you would need to use seriailze and deserialize functions to change the root keyname to match your needs while using the heavily nested pods structure.

I can see why the pods structure isn’t considered stable enough to be recommeded at the moment. But it’s nice to have as an “as-is” workflow for now.

Let us know if using a custom serializer or adapter helps in your issue.


#7

Good Idea, as I am fairly new to Ember and it is still changing a lot I might take couple of days to reply.

Thank you for the suggestion


#8

I have to create adapter and serializer for ‘settings/page/links’ bellow are the codes

app/settings/page/link/adapter.js

import ApplicationAdapter from '../../../application/adapter';

export default ApplicationAdapter.extend({
  pathForType: function(modelName) {
    modelName = modelName.replace('settings/page/', '');
    var decamelized = Ember.String.decamelize(modelName);
    return Ember.String.pluralize(decamelized);
  }
});

app/settings/page/link/serializer.js

import DS from 'ember-data';

export default DS.RESTSerializer.extend({
  modelNameFromPayloadKey: function (payloadKey) {
    return this._super('settings/page/' + payloadKey);
  },
  payloadKeyFromModelName: function(modelName) {
    modelName = modelName.replace('settings/page/', '');
    modelName = Ember.String.dasherize(modelName);
    return modelName;
  }
});

#9

I am also using simple-auth plugin it was working fine before,

but now when I logout and try to access a secured route, it should take me to to login page instead it is giving me these errors, not sure if it is related to it or not

Error while processing route: settings.page.link.new Adapter operation failed Error: Adapter operation failed
at new Error (native)
at Error.EmberError (http://localhost:4200/assets/vendor.js:24481:21)
at Error.ember$data$lib$adapters$errors$$AdapterError (http://localhost:4200/assets/vendor.js:78334:50)
at ember$data$lib$system$adapter$$default.extend.handleResponse (http://localhost:4200/assets/vendor.js:79499:16)
at ember$data$lib$system$adapter$$default.extend.ajax.Ember.RSVP.Promise.hash.error (http://localhost:4200/assets/vendor.js:79589:33)
at jQuery.Callbacks.fire (http://localhost:4200/assets/vendor.js:3301:30)
at Object.jQuery.Callbacks.self.fireWith [as rejectWith] (http://localhost:4200/assets/vendor.js:3413:7)
                                                            at done (http://localhost:4200/assets/vendor.js:8468:14)
at XMLHttpRequest.jQuery.ajaxTransport.send.callback (http://localhost:4200/assets/vendor.js:8807:9)

I am not able to find any thing for Adapter operation failed


#10

That’s a bit vague, but double check your network tab in the development tools, see if your API request is actually happening when you extend the adapter.


#11

hmm it was bit strange. Previously I was sending an empty object with status 200 on successful delete. But now I have to send something in array ['success'=> 'it is done'] and it is working again.


#12

Hello I need to do resolve it .