How can apply DRY to my EmberJS filtering?

I had a collection that I’m filtering in an EmberJS component. It’s filtering by country, fulfilled, mood. Each filter also has an “all” value which disables that filter. Which gave me:

export default Ember.Component.extend({
  markersByMood: function(){
    if(this.get('selectedMood') === 'all'){
      return this.get('markers');
    }
    return this.get('markers'.filterBy('properties.mood', this.get('selectedMood')));
  }.property('markers.[]', 'selectMood'),

  markersByCountry: function(){
    if(this.get('selectedCountry') === 'all'){
      return this.get('markers');
    }
    return this.get('markers'.filterBy('properties.country', this.get('selectedCountry')));
  }.property('markers.[]', 'selectCountry'),

  markersByFulfilled: function(){
    if(this.get('selectedFulfilled') === 'all'){
      return this.get('markers');
    }
    return this.get('markers'.filterBy('properties.fulfilled', this.get('selectedFulfilled')));
  }.property('markers.[]', 'selectedFulfilled'),

  filteredMarkers: Ember.computed.union("markersByMood", "markersByCountry", "markersByFulfilled")
});

The 3 filters repeat the same basic logic, how would you apply DRY to this?

Create a function that returns computed property

function makeFilterProperty(dep, prop, fn) {
  return Ember.computed('markers.[]', dep, function () {
    if(this.get(dep) === 'all'){
      return this.get('markers');
    }

    return this.get('markers').filterBy(`properties.${prop}`, this.get(dep));
  }).readOnly();
}
3 Likes