Serving all routes from a specific folder (using PODS)


#1

Hello everyone,

With the arrival of 2.0 I am adapting my application to the new version as well as restructuring it. I am using PODS by default, but with no default pods folder so that everything lives in app folder. However, I would like all routes to be nested in one directory, for example “routes” so that I could have them all together. So the structure would be the following:

  • routes
    • home
      • route.js
      • template.js
    • users
      • route.js
      • template.js
    • settings
      • route.js
      • template.js

I have been trying to get this to work all day, but I cannot seem to get it working. Is this even possible? If so, how should I approach this problem?

Thanks!


#2

try this …

ember g route routes/home

ember g route routes/users

ember g route routes/settings

hopefully it wil help u …


#3

This did not work out of the box. This was added to my router when I ran the command for settings route:

this.route('routes', function () {
    this.route('settings', {path: '/settings'});
});

With that, I could access the settings route by going to /routes/settings. However, I would like it to be at /settings . I changed the router to the following:

this.route('routes.settings', {path: '/settings'});

Now I am able stop access settings route at /settings . Is this a good approach, or is it frowned upon? Is there a way how to tell Ember to always look for all routes in the routes folder so that I do not have to prepend the “routes.” to every route and specify path for every route?

Thanks!


#4

You just need to reset the namespace like so:

this.route('routes', function () {
    this.route('settings', {path: '/settings', resetNamespace: true});
});

#5

Sounds like you are trying to change the default pod folder. Take a look at the podModulePrefix for the config/environment.js file in the ember-cli user guide: http://www.ember-cli.com/user-guide/#pod-structure Basically, you’ll want to specify podModulePrefix: 'your-project-name/routes'


#6

Thanks for the ideas! Unfortunately neither of them seem to work.

Adding resetNamespace: true did have any effect. Changing the podModulePrefix seems to have possibly helped with the routes, but then ember started to try to fetch data from wrong paths and everything was kind of off. The problem is that I do not want to change the pod directory for everything, but just for routes.

This is what I have in my router right now:

Router.map(function () {
    this.route('routes.settings', {path: '/settings'});
    this.route('routes.devices', {path: '/devices'});
    this.route('routes.home', {path: '/'});
});

It is probably not ideal, but it seems to work for now. I wonder if there is a way to extend the default resolver to look for routes directly in the “routes” folder, but not sure if that is a good idea either.


#7

@mmiklo - This worked great for me. Thanks for blazing the trail. You can also nest your routes further and refer to them using 'main.sub/.his-route', allowing the source directory structure to mirror the application URL structure. It is a bit of a bummer to have to manually edit the paths, but only a slight one.


#8

@DanChadwick thanks for the reply, glad it helped and thanks for the suggestion. I actually came up with an ever better solution for my issue. I modified the Resolver in app.js:

Resolver: Resolver.extend({
        resolveRoute: function (parsedName) {
            var resolvedObject = this._super(parsedName);

            if (!resolvedObject && shouldAppendRoutesToResolvedObject.call(this, parsedName.name)) {
                parsedName.fullNameWithoutType = 'routes/' + parsedName.fullNameWithoutType;
                parsedName.fullName = 'route:' + parsedName.fullNameWithoutType;
                parsedName.name = 'routes/' + parsedName.name;

                resolvedObject = this._super(parsedName);
            }

            return resolvedObject;
        },
        resolveTemplate: function (parsedName) {
            var resolvedObject = this._super(parsedName);

            if (!resolvedObject && shouldAppendRoutesToResolvedObject.call(this, parsedName.name)) {
                parsedName.fullNameWithoutType = 'routes/' + parsedName.fullNameWithoutType;
                parsedName.fullName = 'template:' + parsedName.fullNameWithoutType;
                parsedName.name = 'routes/' + parsedName.name;

                resolvedObject = this._super(parsedName);
            }

            return resolvedObject;
        },
        resolveController: function (parsedName) {
            var resolvedObject = this._super(parsedName);

            if (!resolvedObject && shouldAppendRoutesToResolvedObject.call(this, parsedName.name)) {
                parsedName.fullNameWithoutType = 'routes/' + parsedName.fullNameWithoutType;
                parsedName.fullName = 'controller:' + parsedName.fullNameWithoutType;
                parsedName.name = 'routes/' + parsedName.name;

                resolvedObject = this._super(parsedName);
            }

            return resolvedObject;
        },
        resolveOther: function (parsedName) {
            var resolvedObject = this._super(parsedName);

            if (!resolvedObject && shouldAppendRoutesToResolvedObject.call(this, parsedName.name)) {
                var elementType = parsedName.fullName.substring(0, parsedName.fullName.indexOf(':'));

                if (elementType) {
                    parsedName.fullNameWithoutType = 'routes/' + parsedName.fullNameWithoutType;
                    parsedName.fullName = elementType + ':' + parsedName.fullNameWithoutType;
                    parsedName.name = 'routes/' + parsedName.name;

                    resolvedObject = this._super(parsedName);
                }
            }

            return resolvedObject;
        }}), 

This works great for us, I can have all the routes in the “routes” directory and I do not have to modify my router at all.


#9

@mmiklo - Oh, that’s much better. I’m not sure you need resolveOther since the only things in the routes folder are routes, controllers, and templates. I’m not sure if name should be updated. Here’s my variation of your code:

  Resolver: Resolver.extend({
    /**
     * Extend the resolver to allow routes to be within the routes directory.
     */
    adjustRoute(parsedName, type) {
      parsedName.fullNameWithoutType = 'routes/' + parsedName.fullNameWithoutType;
      parsedName.fullName = type + ':' + parsedName.fullNameWithoutType;
      return this;
    },
    resolveRoute(parsedName) {
      return this._super(parsedName) || this.adjustRoute(parsedName, 'route')._super(parsedName);
    },
    resolveTemplate(parsedName) {
      return this._super(parsedName) || this.adjustRoute(parsedName, 'template')._super(parsedName);
    },
    resolveController(parsedName) {
      return this._super(parsedName) || this.adjustRoute(parsedName, 'controller')._super(parsedName);
    },
  }),

You didn’t mention it, but this also supports routes nested within the routes directory. Again, thanks!


Possible to use custom file structure & file naming?
#10

Glad it worked!

For some reason I had to add resolveOther to the code when I was testing it a while back, don’t remember anymore why.