Idiomatic multiple params


#1

I’m giving a talk this week about params and I want to make sure I’m giving the best the right information.

Would you give me feedback as to whether this code is idiomatic. The data is gathered in a form I have include the controller that gathers the form data and transforms it for the route.

The URL www.example.com/flights/2013-11-21/2013-11-30/seattle-auckland

###The Router

App.Router.map ->
  @resource "flights",
    path: "flights/:startDate/:endDate/:locations"
  @resource "flightSearch"

####The Controller set up the params for the route.

App.FlightSearchController = Em.ObjectController.extend
  
  actions: 
    save: ->
      startDate = moment(this.get('startDate'))
      endDate = moment(this.get('endDate'))
      startLocation = this.get('startLocation.location').toLocaleLowerCase()

      if this.get('destinationLocation')
        desinationLocation = this.get('destinationLocation.location').toLocaleLowerCase()
      else
        desinationLocation = startLocation

      startDateFomatted = startDate.format("YYYY-MM-DD")
      endDateFomatted = endDate.format("YYYY-MM-DD")
      locations = "#{startLocation}-#{desinationLocation}"
      
      search = Ember.Object.create
        startDate: startDateFomatted
        endDate: endDateFomatted
        locations: locations

      @transitionToRoute('flights', search)

####The Route

App.FlightsRoute = Em.Route.extend

  model: (params) -> 
    Ember.Object.create
      startDate: params.startDate
      endDate: params.endDate
      locations: params.locations

  setupController: (controller, model) ->
    controller.setProperties
      startDate: model.startDate
      endDate: model.endDate
      locations: model.locations

    controller.send('sendResults')

  serialize: (model) ->
    startDate: model.startDate, 
    endDate: model.endDate, 
    locations: model.locations

Cheers


#2

Its difficult to tell without seeing the context for this code but you seem to have a lot of duplication. Usually, in the model hook you would return the results of your query which you seem to be doing in controller.send(‘sendResults’). By doing this, you’re bypassing all of the goodness of the promise based router.

Why are you not querying in the model hook?


#3

Great questions @tarasm.

The model is backed by a web socket which sent in sendResults controller method. Does that help.


#4

So, is all of this code just for getting input from the user and handling parameters from the url?


#5

I get your point.

For this part of the app I’m discussing here the user enters date and location information into a form then the system sends that data through a web socket as I said. The web socket once triggered will return a series of flight results where ember will add each of the results into the list ordered by price. From there the user will be able to filter the results further.

A kayak.com built with ember.


#6

I feel like something smells, but I just can’t put my finger on it.

Can you show me the code for sendResults action from the FlightsController?

The FlightSearchController & FlightsRoute do something that seems strange to me. You’re handling an object that has params in place where resulting data should be. This starts in the last line of FlightSearchController#actions#save which passes url parameters as an object. This causes the Router to skip FlightsRoute#model because it assumes that it already has a model for this route.

I would do this:

App.FlightSearchController = Em.ObjectController.extend
  ...
  @transitionToRoute 'flights', startDate, endDate, locations

App.FlightsRoute = Em.Route.extend
  model: (params) ->
    this.set('params', params)
    return # query initial set of results 

  setupController: (controller, model) ->
    controller.setProperties('params', params)
    controller.set('content', model)    

  activate: () ->
    @controllerFor('flights').send('sendResults')

Better yet, I would use Route hierarchy

App.Router.map ->
  @resource "flights", ->
    this.route('results', { path: ':startDate/:endDate/:locations' });
    this.route('search');

App.FlightsSearchController = Em.Controller.extend
  actions:
     save: ->
       ...
       this.send('search', startDateFormatted, endDateFormatted, locations) # send search action up to hierarchy chain

App.FlightsRoute = Em.Route.extend
  actions:
    search: (startDate, endDate, locations) ->
      @transitionTo('results', startDate, endDate, locations)

App.FlightsResultsRoute = Em.Route.extend
  model: (params) ->
    @set('params', params)
    return # return a promise that resolves when initial set of data is sent ( if possible )
  
  setupController: (controller, models) ->
    @controller.set('content', models)
    @controller.setProperties @get('params')

App.FlightsResultsController = Em.ArrayController.extend
   actions:
     sendResults: ->
       # connect and append to content property to add results

This looks better to me, it tells you more about what’s going on.


#7

Great feedback thanks heaps.

I like the idea of just passing in the parameters to the transitionTo call. I will have a look at what is refactor does to the code.

Cheers