سؤال

We are developing educational platform. We have two resource types: courses and lessons. So we do have following URL schema:

/(root)
└┬course-slug
 ├─info
 └┬lesson-slug
  └┬comments
   └─comment-id

URL to a lesson looks like this: /programming/what-is-loop/ and comments for this lesson would have following URL: /programming/what-is-loop/comments/.

Now we decided that course is optional. Some lessons are not inside any course, some inside many courses. So new URL schema looks like this:

/(root)
├┬course-slug
│├─info
│└┬lesson-slug
│ └┬comments
│  └─comment-id
│
└┬lesson-slug
 └┬comments
  └─comment-id

In other words course part of URL are optional. How to make CourseRoute optional, or how to reuse LessonRoute, CommentsRoute and CommentRoute (in fact there is little more)

هل كانت مفيدة؟

المحلول

Thx to all!

It turned out that easiest way is to move course-slug to query-params. Just few line of code needed to achive this:

App.LessonRoute = Em.Route.extend
  setupController: (controller, model, transition)->
    controller.set 'content', model

    course_slug = transition.queryParams.scope
    if course_slug
      ...
      @get('store').find('course', course_id).then (course)->
        controller.set 'course', course

App.LessonController = Em.ObjectController.extend
  scope: null # slug for course
  queryParams: ['scope']

Because course property simply moved from lesson-model to controller no heavy refactoring needed in templates or somewhere else.

نصائح أخرى

If you're very sure about what you're doing -- that means on UI you have both standalone lesson and nested lesson under course -- you can do this way (hope you understand CoffeeScript, it's not hard):

@resource 'course', path: ':course_id', ->
  @route 'info'
  @resource 'course.lesson', ':lesson_id' ->

@resource 'lesson', ->

This gives you different routes and urls. Then you can generate links like this:

{{link-to "Nested Lesson" "course.lesson" course lesson}}
{{link-to "Lesson" "lesson" lesson}}

This way, you have two lesson routes that can not be the same. You can use inheritance or mixin to reuse functionalities, like use the same controller/view/template.

App.LessonRoute = Em.Route.extend
  controllerName: 'lesson'
  templateName: 'lesson'   # Or use viewName if you need to define a view

  model: ->
    # get lesson

App.CourseLessonRoute = App.LessonRoute.extend
  model: ->
    # get lesson from course

# No need to define "CourseLessonController"
App.LessonController = Em.ObjectController.extend()

For comments, if you wish, you can use the same way. But I think you don't really need to define a url for comment. In this way you can just use setupController and renderTemplate to render CommentsController to comments outlet

App.LessonRoute = Em.Route.extend
  setupController: (controller, model) ->
    @_super.apply(@, arguments)

    comments = model.get('comments') # Just an example code to get comments
    @controllerFor('comments').set 'model', comments

  renderTemplate: ->
    @_super.apply(@, arguments)

    @render 'comments',
      into: 'lesson'
      outlet: 'comments'
      controller: 'comments'  # Not sure if this option can be ignored.

And your lesson template:

{{outlet comments}}
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top