代码之家  ›  专栏  ›  技术社区  ›  McPants

与Ember、Ember数据和Rails的多对多关系

  •  7
  • McPants  · 技术社区  · 11 年前

    我在试图使用Ember数据和rails在Ember.js中保存多对多关系时遇到了一个问题。该关联在成员方面运行良好,但当我尝试提交事务时,它在提交到rails时不会包括新关联的列表。任何帮助都将不胜感激,我一直在努力寻找一个在github上做这么简单的事情的示例应用程序,但我似乎找不到。

    这是我的Ember代码的一个简化版本:

    App.Store = DS.Store.extend
      revision: 11
      adapter: DS.RESTAdapter.create
        url: '/api'
    
    App.Router.map ->
      @resource 'rosters'
      @resource 'users'
    
    App.User = DS.Model.extend
      rosters: DS.hasMany 'App.Roster'
    
    App.Roster = DS.Model.extend
      users: DS.hasMany 'App.User'
    
    App.RostersEditRoute = Ember.Route.extend
      setupController: (controller, model) ->
        controller.set 'users_list', App.User.find()
    
    App.RostersEditView = Ember.View.extend
      userCheckbox: Em.Checkbox.extend
        checkedObserver: ( ->
          users = @get 'roster.users'
          if @get 'checked'
            users.addObject @get 'user'
          else
            users.removeObject @get 'user'
          @get('controller.store').commit()
        ).observes 'checked'
    

    编辑表单:

    each user in users_list
      label.checkbox
        view view.userCheckbox rosterBinding="current_roster" userBinding="user" | #{user.full_name}
    

    Rails后端(使用继承的资源和活动模型序列化程序gem):

    class User < ActiveRecord::Base
      has_many :rosters_users
      has_many :rosters, through: :rosters_users
      accepts_nested_attributes_for :rosters
    end
    
    class RostersUser < ActiveRecord::Base
      belongs_to :user
      belongs_to :roster
    end
    
    class Roster < ActiveRecord::Base
      has_many :rosters_users
      has_many :users, through: :rosters_users
      accepts_nested_attributes_for :users
    end
    
    module Api
      class RostersController < BaseController
      end
    end
    
    module Api
      class UsersController < BaseController
      end
    end
    
    module Api
      class BaseController < ActionController::Base
        inherit_resources
    
        respond_to :json
        before_filter :default_json
    
        protected
    
        # Force JSON
        def default_json
          request.format = :json if params[:format].nil?
        end
      end
    end
    
    class UserSerializer < BaseSerializer
      has_many :rosters, embed: :ids
    end
    
    class RosterSerializer < BaseSerializer
      has_many :users, embed: :ids
    end
    

    正如我所说,该关联在Ember上运行良好,但rails似乎没有获得新的关联数据。当我在web检查器中查看XHR选项卡时,我看到它只发送了以下内容:

    请求有效载荷 {“花名册”:{“created_at”:“2013年3月21日星期四23:16:02 GMT”,“team_id”:“1”}

    我返回了一个204无内容错误,因为没有任何更改。

    2 回复  |  直到 11 年前
        1
  •  17
  •   ahmacleod    11 年前

    尽管可以设置匹配 hasMany 关系,Ember Data实际上还不支持多对多关系(请参阅 this issue ). 现在您可以做的是使用成员关系模型来分解关系。

    App.User = DS.Model.extend
      rosterMemberships: DS.hasMany 'App.RosterMembership'      
    
    App.RosterMembership = DS.Model.extend
      user: DS.belongsTo 'App.User'
      roster: DS.belongsTo 'App.Roster'
    
    App.Roster = DS.Model.extend
      rosterMemberships: DS.hasMany 'App.RosterMembership'
    

    现在您可以使用 createRecord() deleteRecord() 使用成员关系模型添加和删除关系。

    不幸的是,在这个例子中,绑定到特定用户的名册集合并不那么容易。一个解决方案如下:

    App.User = DS.Model.extend
      rosterMemberships: DS.hasMany 'App.RosterMembership'
      rosters: ( ->
        @get('rosterMemberships').getEach('user')
      ).property 'rosterMemberships.@each.relationshipsLoaded'
    
    App.RosterMembership = DS.Model.extend
      user: DS.belongsTo 'App.User'
      roster: DS.belongsTo 'App.Roster'
      relationshipsLoaded: ( ->
        @get('user.isLoaded') and @get('roster.isLoaded')
      ).property 'user.isLoaded', 'roster.isLoaded'
    

    如果您绑定到 user.rosters ,则您的模板应在创建或销毁关系时更新。

        2
  •  0
  •   user2573698    11 年前

    替代解决方案:

    App.Roster = DS.Model.extend
      users_map: DS.attr('array')
      users: DS.hasMany 'App.User'
    
      users_change: (->
        @set('users_map', @get('users').map((el) -> el.id).toArray())
      ).observes('users.@each')
    

    到POST中的服务器,数据将发送用户ID数组