将ManyToMany记录保存到rails后端

时间:2013-04-24 12:55:55

标签: ember.js ember-data

我无法使用ember-data将相关记录保存到Rails后端。

型号:

FP.Student = DS.Model.extend

  firstName:    DS.attr('string')
  lastName:     DS.attr('string')
  imageUrl:     DS.attr('string')

  room:         DS.hasMany('FP.Room')
  parents:      DS.hasMany('FP.Parent')
  observations: DS.hasMany('FP.Observation')


FP.Observation = DS.Model.extend

  name:         DS.attr('string')
  description:  DS.attr('string')
  observedAt:   DS.attr('string')

  room:         DS.belongsTo('FP.Room')
  educator:     DS.belongsTo('FP.Educator')
  students:     DS.hasMany('FP.Student', embedded: true)

我想将一个已存在的学生列表从一个选择视图添加到一个新的观察。假设学生模型已经收集在controller.selectedStudents我做:

 saveObservation: ->
    console.log "ObservationsController saveObservation"
    obs = @get('newObservation') # new observation is created previously
    obs.set('observedAt', new Date)
    obs.set('room', @get('room'))
    obs.set('educator', @get('room.educators').objectAt(0))
    selected = @findSelectedStudents()
    obs.get('students').pushObjects(selected)
    obs.get('transaction').commit()

findSelectedStudents: ->
    @get('selectedStudents').map( (id) =>
      @get('students').find( (student) ->
        student.id is id
      )
    )

生成的json发送回服务器看起来像(这是来自服务器日志):

Started POST "/observations" for 127.0.0.1 at 2013-04-24 21:04:12 +1000
Processing by ObservationsController#create as JSON
  Parameters: {"observation"=>
{"name"=>"DDS", "description"=>"asdsad", "observed_at"=>"Wed Apr 24 2013 21:04:04 GMT+1000 (EST)", "room_id"=>203, "educator_id"=>535, 
"students"=>[{"id"=>605, "first_name"=>"Steven", "last_name"=>"Richards", "image"=>"https://www.filepicker.io/api/file/CTUCsDGwdEVaS"},
 {"id"=>607, "first_name"=>"Anna", "last_name"=>"Stone", "image"=>"https://www.filepicker.io/api/file/CTUCsDGwdEVaS"}]}}
 Completed 500 Internal Server Error in 5ms

抱歉布局,但有2名学生,有完整的属性列表。服务器抛出的错误是ActiveRecord::AssociationTypeMismatch - Student(#70343949384800) expected, got ActiveSupport::HashWithIndifferentAccess(#70343953246680)

现在,我已经开始使用ajax回调,将学生序列化为student_ids数组,其中只包含学生ID。服务器接受此调用并设置关联。但我更喜欢使用余烬数据,而不是手动记录管理的麻烦,我发现手动ajax解决方案。

我尝试在观察中设置student_ids数组,但之后没有任何内容被发送回服务器。

我认为如果关联名为student_attributes,当前调用可能有效,但如果学生记录不脏,则发送所有数据似乎是浪费时间。

那么,我是否应该尝试覆盖序列化程序以发回一系列student_ids?或者我错过了其他什么?

感谢,

马丁

1 个答案:

答案 0 :(得分:1)

要在服务器上保持多对多关系,我正在攻击序列化程序的hasMany方法,以在映射中添加选项serialized

这是序列化程序(CoffeeScript):

App.Serializer = DS.RESTSerializer.extend

  # redefine to make it possible to serialize a relationship by an array of ids
  # to enable it, a 'serialized' property should be set to 'ids' in the adapter mapping
  # the key in the hash will be the type of the object in the relation ship + _ids'
  # example : for an hasMany('App.Category'), the key will be category_ids
  addHasMany: (hash, record, key, relationship) ->
    type = record.constructor
    name = relationship.key

    serializedType = @serializedType type, name

    if serializedType is 'ids'
      key = @singularize(@keyForAttributeName(type, name)) + "_ids"
      manyArray = record.get name
      serializedIds = []
      manyArray.forEach (record) ->
        serializedIds.push record.get('id')
      hash[key] = serializedIds
    else
      return @_super hash, record, key, relationship

  # method to access the serialized option in adapter mapping
  serializedType: (type, name) ->
    @mappingOption type, name, 'serialized'

这是一个映射配置例子:

App.Adapter.map App.Product,
  categories:
    serialized: 'ids'

有了这个,当我提交Product时,json将包含一个键category_ids,其中包含相关类别ID的数组。

更新:

要正确使用定义的App.Serializer,您应该将其添加到应用程序的适配器中:

App.Adapter = DS.RESTAdapter.extend
  serializer: App.Serializer

要在您的应用程序中使用此适配器,您必须在商店中设置它:

App.Store = DS.Store.extend
  adapter: 'App.Adapter'