延迟加载模型中的关联

时间:2014-05-10 00:29:37

标签: javascript ruby-on-rails ember.js

我的模型在我的Ember.js应用程序中看起来如下:

MyApp.Game = DS.Model.extend({
  season_type:            DS.attr('string'),
  gamedate:               DS.attr('date'),
  home_team_name:         DS.attr('string'),
  visiting_team_name:     DS.attr('string'),
  gametime:               DS.attr('string'),
  home_team:              DS.belongsTo('team'),
  visiting_team:          DS.belongsTo('team'),
  home_team_pitcher:      DS.belongsTo('player'),
  visiting_team_pitcher:  DS.belongsTo('player'),
  home_players:           DS.hasMany('player'),
  visitor_players:        DS.hasMany('player')
});

这在控制器" A"中工作得很好。在另一个控制器中,让我们称之为控制器" B",我理想情况下还有两个属性,如下所示:

MyApp.Game = DS.Model.extend({
  season_type:            DS.attr('string'),
  gamedate:               DS.attr('date'),
  home_team_name:         DS.attr('string'),
  visiting_team_name:     DS.attr('string'),
  gametime:               DS.attr('string'),
  home_team:              DS.belongsTo('team'),
  visiting_team:          DS.belongsTo('team'),
  home_team_pitcher:      DS.belongsTo('player'),
  visiting_team_pitcher:  DS.belongsTo('player'),
  home_players:           DS.hasMany('player'),
  visitor_players:        DS.hasMany('player'),
  home_all_players:       DS.hasMany('player'),
  visitor_all_players:    DS.hasMany('player')
});

在这种情况下,我添加了home_all_playersvisitor_all_players。在这两个属性中有大量数据要跨越线路,我希望避免将其用于面向客户的控制器A。另一方面,控制器B是一个管理界面,管理员需要访问home_all_playersvisitor_all_players,以便他们可以更新MLB团队的阵容。

最简洁的方法是什么?我在服务器端猜测,我使用Ruby on Rails,我只是让序列化程序包括home_all_playersvisitor_all_players,具体取决于调用的路由。但是Ember.js方面的建模保持不变,所以我不确定解决这个问题的最佳方法是什么。

4 个答案:

答案 0 :(得分:0)

我认为,这取决于您需要访问特定数据集的整个应用流和交互,如果您希望用户遇到任何转换延迟或特定用户体验。

作为一般规则,我的后端负责为其客户提供最方便的API,因此他们可以提供最好的用户体验,为此,您可以使用嵌入式数据,侧载资源,新资源定义等。 ..

我在三个方面做了类似的事情:

1)发送查询参数,以便服务器知道如何序列化资源。

store.find('game', {id: 1, extend:'admin'});
store.find('game', {extend:'admin'});

2)根据您当前的用户身份验证,您的服务器可以知道如何序列化资源。

//the server response would be different based on the auth header 
store.find('game', 1);
store.find('game');

3)包含扩展资源的新资源。

MyApp.ExtendedGame = DS.Model.extend({
  game:                   DS.belongsTo('game'),
  home_all_players:       DS.hasMany('player'),
  visitor_all_players:    DS.hasMany('player')
});

答案 1 :(得分:0)

IMO你需要扩展你的模型。

App.Game = DS.Model.extend({
  ...
});

App.AdminGame = App.Game.extend({
  home_players:           DS.hasMany('player'),
  visitor_players:        DS.hasMany('player')
});

在这种情况下,您将拥有两个控制器和相关路线,分别是AdminGameController,GameController,GameRoute和AdminGameRoute。

您应该从相关路线中的服务器获取适当的模型。 Rails应该根据控制器返回正确的模型。

答案 2 :(得分:0)

我使用查询参数,并且在导轨方面ActiveModel::Serializer确定是否包含字段,数量,排序顺序等等。我不确定我是否会考虑使用不同的控制器客户虽然。

我即将开始使用类似功能,更常见的是对大量数据进行分页。我现在想到的是扩展DS.ManyArray并在meta中添加一些包含loaded_counttotal_countoffset等的数据。这可以由API返回。默认情况下可能是加载20条记录,然后可以调用函数来添加更多记录,或者将窗口移动到另一个范围,以保持内存受控。或者,通过查询参数,加载'em all。

答案 3 :(得分:0)

您可以使用默认属性和具有home_all_playersvisited_all_players属性的继承类创建基类,而不是在单个模型上进行中继。

这将是一个更好的OO方法(恕我直言)

Controller_A

MyApp.Game = DS.Model.extend({
  season_type:            DS.attr('string'),
  gamedate:               DS.attr('date'),
  home_team_name:         DS.attr('string'),
  visiting_team_name:     DS.attr('string'),
  gametime:               DS.attr('string'),
  home_team:              DS.belongsTo('team'),
  visiting_team:          DS.belongsTo('team'),
  home_team_pitcher:      DS.belongsTo('player'),
  visiting_team_pitcher:  DS.belongsTo('player'),
  home_players:           DS.hasMany('player'),
  visitor_players:        DS.hasMany('player')
});

Controller_B

MyApp.AdminGame = MyApp.Game.extend({
   home_all_players:       DS.hasMany('player'),
  visitor_all_players:    DS.hasMany('player')
});

同样适用于 Rails模型。更改您当前的模型,如

class Game < ActiveModel::Serializer
  ## Your code ..

  def home_all_players
    nil
  end

  def visitor_all_players
    nil
  end

  ## Your code ..
end

使用这些属性为管理员(扩展游戏)创建一个新模型

class AdminGame < Game
  def home_all_players
     self.home_all_players
  end

  def visitor_all_players
     self.visitor_all_players
  end
end

如果您不想在现有模型中返回nil,请在json渲染期间排除这些属性。请参阅此question