Skip to content

08.0.0 hasMany Associations

bazzel edited this page Nov 14, 2014 · 1 revision

What you will learn

  • Define and render a hasMany association
  • Change a timestamp into human readable format

Before you start

See the installation instructions. Use tag 8.0.0.

Render Reviews

  • Open app/templates/products/show.hbs.
  • Remove all but one <div class='row'> elements and the subsequent <hr/> tag from their <div class='reviews'> container.
  • Wrap the remaining <div> in the Handlebars {{each}} helper:
  {{#each reviews}}
    <div class='row'>
    ...
    </div>
    <hr/>
  {{/each}}
  • Open app/models/product.js and add a reviews association:
export default DS.Model.extend({
  ...
  image: DS.attr(),
  reviews: DS.hasMany('review', { async: true })
});
  • Inspect the error shown in the Console tab in the browser. Ember doesn't know the review model yet. Let's define it.
  • Enter the command ember g model review.
  • Open app/models/review.js and add the following attributes:
export default DS.Model.extend({
  description: DS.attr(),
  rating: DS.attr(),
  user: DS.attr(),
  createdAt: DS.attr()
})
  • Open app/templates/products/show.hbs and replace:
    • Anonymous with {{user}}
    • 10 days ago with {{createdAt}}
    • See more snippets like this... with {{description}}

Format time

The project uses moment.js which you can use to format the creation date of the review, so it can display 4 days ago instead of something like 2014-10-26T14:07:33.926Z.

  • Open app/models/review.js and add a property formattedCreatedAt:
export default DS.Model.extend({
  ...
  createdAt: DS.attr(),
  formattedCreatedAt: function() {
    return moment(this.get('createdAt')).fromNow();
  }.property('createdAt')
});
  • Open app/templates/products/show.hbs and replace {{createdAt}} with {{formattedCreatedAt}}.

Bonus: Format time with a helper

It's actually bad practice to define view logic in a model. Instead, you should define this logic in the controller or create a view helper that accepts a timestamp and returns the formatted version. Here we choose for the view helper.

  • In the terminal, enter ember g helper time-ago-in-words.
  • Open app/helpers/time-ago-in-words.js and replace
return input;

with

return moment(input).fromNow();
  • Open app/templates/products/show.hbs and replace
{{formattedCreatedAt}}

with

{{time-ago-in-words createdAt}}
  • Open app/models/review.js and remove the formattedCreatedAt property.