在Ember.js中合并(DRY)类似的控制器/模型/模板

时间:2013-07-10 17:58:03

标签: model ember.js routes refactoring dry

我是Ember.js的新手。我有两套模型/控制器/模板处理非常相似的数据,我知道它们需要重构为一个。虽然数据非常相似,但我需要在输出到模板时按“Business”或“First”类型进行不同的解释。模板会将上述类型拆分为“活动”或“非活动”选项卡。我只是不确定这种“正确”的方式是什么。

我的routes.js

this.resource('manage', function() {
    this.resource('business', function() {
        this.route('active');
        this.route('inactive');
    });
    this.resource('first', function() {
        this.route('active');
        this.route('inactive');
    });

App.FirstRoute = Ember.Route.extend({
    model: function(){
        return App.First.find();
    },
});

App.BusinessRoute = Ember.Route.extend({
    model: function(){
        return App.Business.find();
    },
});

我的RESTAdapter(store.js):

App.Store = DS.Store.extend({
revision: 12,
adapter: DS.RESTAdapter.reopen({
  buildURL: function(record, suffix) {

      var modelUrlMapping = {}
      modelUrlMapping["first"] = "api/v002/manage.json?me=first"
      modelUrlMapping["business"] = "api/v002/manage.json?me=business"

      var url = ""
      if(modelUrlMapping[record] != undefined ){
        requestUrl = modelUrlMapping[record]
      }
      else{
        requestUrl = this._super(record, suffix);
      }
      return requestUrl;

    }
})

});

型号:

App.First = DS.Model.extend({
    listingId     : DS.attr('string'),
    location    : DS.attr('string'),
    occupied    : DS.attr('string'),
... (define some computed properties specific to First)

App.Business = DS.Model.extend({
    listingId     : DS.attr('string'),
    location    : DS.attr('string'),
    occupied    : DS.attr('string'),
... (define some computed properties specific to Business)

控制器:

App.ManageController = Ember.ObjectController.extend({
    content: [],
    needs: "application",
    applicationBinding: "controllers.application"
});

App.FirstController = Ember.ArrayController.extend({
    needs: "application",
    applicationBinding: "controllers.application",
    content: [],
    firstInactive: (function() {
    return this.get('content').filterProperty('showLabel') ;
    }).property('content.@each.showLabel'),

    firstActive: (function() {
            return this.get('content').filterProperty('showDuration');
    }).property('content.@each.showDuration'),
});

App.FirstActiveController = Ember.ArrayController.extend({
    needs: "first",
    firstBinding: "controllers.first",
});


App.FirstInactiveController = Ember.ArrayController.extend({
    needs: "first",
    firstBinding: "controllers.first",
});

App.BusinessController = Ember.ArrayController.extend({
    needs: "application",
    applicationBinding: "controllers.application",
    content: [],
    businessInactive: (function() {
    return this.get('content').filterProperty('showLabel') ;
    }).property('content.@each.showLabel'),

    businessActive: (function() {
            return this.get('content').filterProperty('showDuration');
    }).property('content.@each.showDuration'),
});

App.BusinessActiveController = Ember.ArrayController.extend({
    needs: "business",
    businessBinding: "controllers.business",
});


App.BusinessInactiveController = Ember.ArrayController.extend({
    needs: "business",
    businessBinding: "controllers.business",
});

模板(仅“第一”,“商业”几乎完全相同)

first.handlebars(标题标题):

<div id="content" class="span6">
    <h3 id="page_type" label="first" class="profile_heading">First</h3>
            <ul id="active_inactive_menu" class="nav nav-tabs">
                {{#linkTo 'first.active' tagName='li' href="#"}}<a>Active</a>{{/linkTo}}
                {{#linkTo 'first.inactive' tagName='li' href="#"}}<a>Inactive</a>{{/linkTo}}
            </ul>
        <div class="tab-content">

        {{outlet}}
    </div>          
</div>

第一/ active.handlebars

<div class="tab-pane active" id="active_list">  
{{#if_not_empty first.firstActive}}
    <ul class="nav nav-tabs nav-stacked">

    {{#each listing in first.firstActive}}
        {{render listingLine listing }}
    {{/each}}   
    </ul>
{{else}}
    No listing found.
{{/if_not_empty}}
</div>

第一/ inactive.handlebars

<div class="tab-pane" id="inactive_list">
{{#if_not_empty first.firstInactive}}
    <ul class="nav nav-tabs nav-stacked">
    {{#each listing in first.firstInactive}}
        {{render listingLine listing }}
    {{/each}}
    </ul>
{{else}}
    No listing found.
{{/if_not_empty}}
</div>

我已经提出了很多代码,我意识到这些是非常基本的Ember.js概念。但我确信还有其他人有类似的问题。重新考虑这个因素的正确方法是什么?如果您注意到,请在我的示例中指出任何其他违反最佳做法的行为。谢谢!

1 个答案:

答案 0 :(得分:2)

您是否考虑通过创建一个其他控制器可以从中扩展的基本控制器来减少重复代码?

这看起来像是:

App.BaseController = Ember.ArrayController.extend({
  needs: "application",
  applicationBinding: "controllers.application",
  content: [],
  inactive: (function() {
    return this.get('content').filterProperty('showLabel') ;
  }).property('content.@each.showLabel'),

  active: (function() {
    return this.get('content').filterProperty('showDuration');
  }).property('content.@each.showDuration'),
});

App.BusinessController = App.BaseController.extend();

App.FirstController = App.BaseController.extend();

至于模型,你可以做类似的事情,例如:

App.Base = DS.Model.extend({
  listingId     : DS.attr('string'),
  location    : DS.attr('string'),
  occupied    : DS.attr('string'),
});

App.Business = App.Base.extend();

App.First = App.Base.extend();

最后,您还可以考虑使用Mixins在控制器,模型等之间共享通用逻辑。

希望它有所帮助。