web-dev-qa-db-ja.com

エンバーデータモデル内で配列を表す方法は?

モデルに配列が含まれる場合、DS.hasManyを指すDS.Modelを使用する必要がありますか?配列要素が実際にモデルではない(IDや独自のエンドポイントがない)場合でも、もっと良い方法はありますか?

私はDS.hasManyを使用していますが、findを呼び出さず、DS.RESTAdapterhasManyを呼び出しても、拡張{ embedded: true }が404をスローしてモデルにアクセスしようとしています。私はこのエラーを初めて見ています(明らかにこのモデルに関連して、それなしでなくなるので):

Uncaught Error: assertion failed: Emptying a view in the inBuffer state is not allowed and should not happen under normal circumstances. Most likely there is a bug in your application. This may be due to excessive property change notifications. ember-latest.js:43

これはどういう意味で、何が原因なのでしょうか?

スタックトレースは次のとおりです。

Ember.assert ember-latest.js:43
Ember.View.states.inBuffer.empty ember-latest.js:13644
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12257
Ember.CollectionView.Ember.ContainerView.extend.arrayWillChange ember-latest.js:14477
invokeAction ember-latest.js:3193
iterateSet ember-latest.js:3175
sendEvent ember-latest.js:3323
Ember.Array.Ember.Mixin.create.arrayContentWillChange ember-latest.js:6963
Ember.ArrayProxy.Ember.Object.extend.arrangedContentArrayWillChange ember-latest.js:9281
Ember.ArrayProxy.Ember.Object.extend._arrangedContentWillChange ember-latest.js:9235
invokeAction ember-latest.js:3193
iterateSet ember-latest.js:3175
sendEvent ember-latest.js:3323
notifyObservers ember-latest.js:1872
Ember.notifyBeforeObservers ember-latest.js:2016
propertyWillChange ember-latest.js:2594
iterDeps ember-latest.js:2077
dependentKeysWillChange ember-latest.js:2092
propertyWillChange ember-latest.js:2592
set ember-latest.js:1416
DS.Model.Ember.Object.extend.dataDidChange ember-data-latest.js:3145
Map.forEach ember-latest.js:1273
OrderedSet.forEach ember-latest.js:1145
Map.forEach ember-latest.js:1271
DS.Model.Ember.Object.extend.dataDidChange ember-data-latest.js:3128
invokeAction ember-latest.js:3193
iterateSet ember-latest.js:3175
sendEvent ember-latest.js:3323
notifyObservers ember-latest.js:1872
Ember.notifyObservers ember-latest.js:1999
propertyDidChange ember-latest.js:2632
Ember.Observable.Ember.Mixin.create.propertyDidChange ember-latest.js:7917
Ember.Observable.Ember.Mixin.create.notifyPropertyChange ember-latest.js:7930
didChangeData ember-data-latest.js:2053
Ember.StateManager.Ember.State.extend.sendRecursively ember-latest.js:15446
Ember.StateManager.Ember.State.extend.send ember-latest.js:15431
DS.Model.Ember.Object.extend.send ember-data-latest.js:3058
DS.Store.Ember.Object.extend.load ember-data-latest.js:1737
DS.Store.Ember.Object.extend.loadMany ember-data-latest.js:1763
embeddedFindRecord ember-data-latest.js:3434
hasAssociation ember-data-latest.js:3459
ComputedPropertyPrototype.get ember-latest.js:2968
get ember-latest.js:1362
getPath ember-latest.js:1484
get ember-latest.js:1355
getWithGlobals ember-latest.js:4041
Binding.connect ember-latest.js:4140
connectBindings ember-latest.js:4600
finishPartial ember-latest.js:4610
Class ember-latest.js:8315
Ember.Mixin.create.create ember-latest.js:8457
Ember.View.Ember.Object.extend.createChildView ember-latest.js:13179
Ember.View.states.inBuffer.appendChild ember-latest.js:13622
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
(anonymous function) ember-latest.js:19043
(anonymous function) ember-latest.js:19208
(anonymous function)
(anonymous function) handlebars-1.0.0.beta.6.js:1512
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
program2
(anonymous function) handlebars-1.0.0.beta.6.js:1529
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember._HandlebarsBoundView.Ember._MetamorphView.extend.render ember-latest.js:18075
Ember.wrap.newFunc ember-latest.js:949
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
bind ember-latest.js:18129
(anonymous function) ember-latest.js:18199
(anonymous function) ember-latest.js:18271
program1
(anonymous function) handlebars-1.0.0.beta.6.js:1529
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14078
Ember.View.Ember.Object.extend.forEachChildView ember-latest.js:12486
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14077
Ember.wrap.newFunc ember-latest.js:949
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12239
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
(anonymous function) ember-latest.js:19043
(anonymous function) ember-latest.js:19208
(anonymous function)
(anonymous function) handlebars-1.0.0.beta.6.js:1512
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14078
Ember.View.Ember.Object.extend.forEachChildView ember-latest.js:12486
Ember.ContainerView.Ember.View.extend.render ember-latest.js:14077
Ember.wrap.newFunc ember-latest.js:949
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.states.inBuffer.appendChild ember-latest.js:13625
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12257
Ember.View.Ember.Object.extend.appendChild ember-latest.js:13058
EmberHandlebars.ViewHelper.Ember.Object.create.helper ember-latest.js:18687
(anonymous function) ember-latest.js:18844
(anonymous function) ember-latest.js:19624
(anonymous function) ember-latest.js:18167
(anonymous function)
(anonymous function) handlebars-1.0.0.beta.6.js:1512
Ember.View.Ember.Object.extend.render ember-latest.js:12223
Ember.View.Ember.Object.extend.renderToBuffer ember-latest.js:12872
Ember.View.Ember.Object.extend.createElement ember-latest.js:12669
Ember.View.states.preRender.insertElement ember-latest.js:13558
Ember.View.Ember.Object.extend.invokeForState ember-latest.js:12257
invoke ember-latest.js:3428
iter ember-latest.js:3475
RunLoop.flush ember-latest.js:3531
RunLoop.end ember-latest.js:3447
Ember.run.end ember-latest.js:3639
autorun ember-latest.js:3705

助けてくれてありがとう。

Update:This fiddle は機能しますが( docs の例では)、これらのオブジェクトはタグが実際のモデルではない場合(つまり IDを持たない場合 )に表示されますか?

30
dechov

ええと...少し難しかったですが、この投稿ですべての答えを組み合わせて、うまくいきました。

まず、新しいタイプ「配列」の変換を作成する必要があります。

DS.ArrayTransform = DS.Transform.extend({
  deserialize: function(serialized) {
    return (Ember.typeOf(serialized) == "array")
        ? serialized 
        : [];
  },

  serialize: function(deserialized) {
    var type = Ember.typeOf(deserialized);
    if (type == 'array') {
        return deserialized
    } else if (type == 'string') {
        return deserialized.split(',').map(function(item) {
            return jQuery.trim(item);
        });
    } else {
        return [];
    }
  }
});

App.register("transform:array", DS.ArrayTransform);

今、あなたのモデルでは、それを別の属性として使用してください:

App.myModel = Ember.Model.extend({
    name : DS.attr('string'),
    cont : DS.attr('array')
}

これで完了です。配列に要素を追加するときは、pushObjectを使用することを忘れないでください。

コントローラ内:

this.get('model.cont').pushObject('new Item');

これが誰かのお役に立てば幸いです。

52
Jorgeblom

私はraw変換を使用します。これはember-dataリビジョン11では次のようになります。

DS.RESTAdapter.registerTransform('raw', {
    deserialize: function(serialized) {
        return serialized;
    },  
    serialize: function(deserialized) {
        return deserialized;
    }   
});

次に、モデル内でこれを行います。

App.MyModel = Ember.Model.extend({
    anArray: DS.attr('raw')
});

そして、どこでも通常の配列のようにanArrayを使用できます。

29
Shreyans

Ember-Data(バージョン10)でカスタム配列タイプを作成する例を次に示します。

DS.JSONTransforms.array =

  # If the outgoing json is already a valid javascript array
  # then pass it through untouched. In all other cases, replace it
  # with an empty array.  This means null or undefined values
  # automatically become empty arrays when serializing this type.

  serialize: (jsonData)->
    if Em.typeOf(jsonData) is 'array' then jsonData else []


  # If the incoming data is a javascript array, pass it through.
  # If it is a string, then coerce it into an array by splitting
  # it on commas and trimming whitespace on each element.
  # Otherwise pass back an empty array.  This has the effect of
  # turning all other data types (including nulls and undefined
  # values) into empty arrays.

  deserialize: (externalData)->
    switch Em.typeOf(externalData)
      when 'array'  then return externalData
      when 'string' then return externalData.split(',').map((item)-> jQuery.trim(item))
      else               return []

これで、モデル属性でカスタムタイプを使用できます。

App.CalenderWeek = DS.Model.extend
  selected_days = DS.attr('array')

そして今あなたがレコードをフェッチするとき:

App.CalendarWeek.find(1)

これらの着信jsonレコードは両方とも、配列に正しく逆シリアル化されます。

{ selected_days: ['Monday', 'Tuesday', 'Saturday'] }

または

{ selected_days: 'Monday, Tuesday, Saturday' }
20
Mayank Patel

Ember Data 1.0.0 Betaでは、カスタムトランスフォームの「サブクラス」を「登録」する機能が提供されています。私はそれを拡張DS.Transformオブジェクトとして参照したいと思います。

DS.ArrayTransform = DS.Transform.extend({
    deserialize: function(deserialized) {
        // ...
        return deserialized;
    },

    serialize: function(serialized) {
        // ...
        return serialized;
    }
});

App.register('transform:array', DS.ArrayTransform);
9
Ryan

サーバーと交換するカスタムデータ構造がどうしても必要な場合は、DS.attr.transformsし、たとえば新しいarrayコーデックを宣言します。

既存の属性コーデックの実装については、 ソースコード を参照してください。独自のものを追加するのに良い場所です。

4
Mike Aski

興味深いことに、この質問に対する他の4つの回答はすべて、ほぼ同じデシリアライズ関数とシリアライズ関数を持っているため、次のように単純化できます。

import Em from 'ember'
import DS from 'ember-data'

# Presumably based on these answers: http://stackoverflow.com/questions/12168570/how-to-represent-arrays-within-ember-data-models
# All we need to do is always make sure an array is returned from serialize or deserialize

toArray = (data) ->
  switch Em.typeOf(data)
    when 'array'  then data
    when 'string' then JSON.parse(data)
    else []

export default DS.Transform.extend
  deserialize: toArray
  serialize: toArray

これは、_ ember-cli-coffees6 を使用して、import/export サポート

1
Devin G Rhode

ここで少しゲームに遅れましたが、新しい配列コーデックを宣言する単純な実装であるjFiddleがここにあります

http://jsfiddle.net/Nook/ab2Xf/

0
chibro2