【问题标题】:Lazy load an association in model延迟加载模型中的关联
【发布时间】:2014-05-10 00:29:37
【问题描述】:

我的 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 端的建模保持不变,所以我不确定解决这个问题的最佳方法是什么。

【问题讨论】:

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


    【解决方案1】:

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

    一般来说,我的后端负责为其客户端提供最方便的 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')
    });
    

    【讨论】:

      【解决方案2】:

      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 应该根据控制器返回正确的模型。

      【讨论】:

        【解决方案3】:

        我使用查询参数,在 Rails 端,ActiveModel::Serializer 确定是否包含字段、多少、排序顺序等。我不确定我是否会考虑在客户端上使用不同的控制器不过。

        我即将开始使用类似的功能,更普遍地对大量数据进行分页。我现在的想法是扩展DS.ManyArray并在meta中添加一些数据,包括loaded_counttotal_countoffset等,所有这些都可以通过API返回。默认可能是加载 20 条记录,然后可以调用函数来添加更多记录,或者将窗口移动到另一个范围,以控制内存。或者,通过查询参数,全部加载。

        【讨论】:

          【解决方案4】:

          您可以创建一个具有默认属性的基类和一个具有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

          【讨论】:

            猜你喜欢
            • 2014-01-15
            • 2012-03-12
            • 1970-01-01
            • 2011-11-07
            • 1970-01-01
            • 1970-01-01
            • 1970-01-01
            • 2018-05-22
            • 2020-02-22
            相关资源
            最近更新 更多