複数のエントリ ビューを含むネストされたエントリ ビューを使用して、to do ビューで構成される to do リストを実装しようとしています。各エントリは削除できるため、コンテナ ビューから削除できます。
私のRailsアプリに接続すると、これはほとんど機能します。削除ボタンがクリックされると (またはコンソールで App.ToDoEntry.find(x).deleteRecord() がトリガーされると)、インスタンスは isDirty=true に設定されますが、エントリは引き続きビューに表示されます。
何が起こっているのかをテストするために、Fixtures を使用して別の jsfiddle を作成し、それを単独で動作させることができるかどうかを確認しました。そうすることで、Ember データのフィクスチャのバグにも遭遇した可能性があると思います。
まず、これが私が取り組んできた Rails + Ember アプリです。
レール
class ToDo < ActiveRecord::Base
has_many :to_do_entries, dependent: :destroy
attr_accessible :is_deleted, :is_staging, :is_template, :title
validates_presence_of :title
end
class ToDoSerializer < ActiveModel::Serializer
attributes :id,
:title
has_many :to_do_entries, embed: :objects
end
class ToDoEntry < ActiveRecord::Base
belongs_to :to_do
attr_accessible :completed_at, :is_deleted, :priority, :title
validates_presence_of :to_do, :title
end
class ToDoEntrySerializer < ActiveModel::Serializer
attributes :id,
:to_do_id,
:title,
:priority
end
残り火
/*---------------*/
/* Application */
/*---------------*/
PLURAL_MAPPINGS = {"to_do_entry": "to_do_entries"};
App = Em.Application.create({
rootElement: '#content',
store: DS.Store.create({
adapter: DS.RESTAdapter.create({ plurals: PLURAL_MAPPINGS }),
revision: 4
})
});
/*---------------*/
/* Controllers */
/*---------------*/
App.TodoController = Ember.ObjectController.extend({
destroy: function() {
this.transaction = App.store.transaction();
this.transaction.add(this.get('content'));
if (window.confirm("Are you sure you want to delete?")) {
this.get('content').deleteRecord();
this.transaction.commit();
App.router.transitionTo('todo');
}
else{
this.transaction.rollback();
this.transaction = null;
}
}
});
App.Todo_entriesController = Ember.ArrayController.extend();
App.Todo_entryController = Ember.ObjectController.extend({
destroy: function() {
this.transaction = App.store.transaction();
this.transaction.add(this.get('content'));
if (window.confirm("Are you sure you want to delete?")) {
this.get('content').deleteRecord();
this.transaction.commit();
App.router.transitionTo('todo');
}
else{
this.transaction.rollback();
this.transaction = null;
}
}
});
/*--------*/
/* Models */
/*--------*/
App.ToDo = DS.Model.extend({
title: DS.attr('string'),
group: DS.belongsTo('App.Group'),
to_do_entries: DS.hasMany('App.ToDoEntry', { embedded: true })
});
App.ToDoEntry = DS.Model.extend({
title: DS.attr('string'),
to_do_id: DS.attr('number'),
priority: DS.attr('number'),
todo: DS.belongsTo('App.ToDo')
});
/*-------*/
/* Views */
/*-------*/
App.TodoView = Ember.View.extend({
templateName: 'app/templates/todo'
});
App.Todo_entriesView = Ember.View.extend({
templateName: 'app/templates/todo_entries'
});
App.Todo_entryView = Ember.View.extend({
templateName: 'app/templates/todo_entry',
destroyEntry: function() {
console.log('Todo_entryView - destroyEntry');
this.get('controller').destroy();
},
init: function(){
this._super();
this.set(
'controller',
App.Todo_entryController.create({ content: this.get('content') })
);
}
});
/*-----------*/
/* Templates */
/*-----------*/
todo.hbs
<article>
<h1>{{title}}</h1>
<div class="widget_links">
<a {{action destroy target="view"}}>Delete</a>
</div>
{{outlet}}
</article>
todo_entries.hbs
{{#if isLoading}}
<p>Loading...</p>
{{else}}
<ul class="list">
{{collection contentBinding="content" itemViewClass="App.Todo_entryView"}}
</ul>
{{/if}}
todo_entry.hbs
<li>
{{#if isLoading}}
Loading...
{{else}}
{{view.content.id}}) {{view.content.title}} Priority: {{view.content.priority}}
<a {{action destroyEntry href="true" target="view"}}>Delete</a>
{{/if}}
</li>
/*--------*/
/* Router */
/*--------*/
App.Router = Ember.Router.extend({
enableLogging: true,
location: 'hash',
root: Ember.Route.extend({
index: Ember.Route.extend({
route: '/',
connectOutlets: function(router) {
var todo = App.ToDo.find(21);
router.get('applicationController').connectOutlet('todo', todo);
var todoController = router.get('todoController');
todoController.connectOutlet('todo_entries', todoController.get("to_do_entries"));
}
})
})
});
App.initialize();
前述のように、これはほぼ機能しますが、イライラすることにビューからエントリが削除されないようです。ここで明らかに間違ったことをしていますか、それともバグですか?
備品のバグ?
次に、フィクスチャを使用して動作するバージョンを作成しました。ただし、App.ToDo.find() (つまり、findAll) が要求されない限り、フィクスチャ データは読み込まれないようです。
以下に 2 つの例を示します。
実行するのは 1 つで、削除に失敗します。
http://jsfiddle.net/danielrosewarne/vDGhe/1/
1 つ目は、関連付けられたエントリを使用して、単一の to do を読み込みます。「削除」をクリックすると、警告が正しく表示され、オブジェクトが無効になります。ただし、エントリはビューに残ります。
コンソールをオンにして表示すると、isDirty 状態が true に設定されていることがわかります。
やることが複数あり、すべて問題ありません
http://jsfiddle.net/danielrosewarne/LeLyy/1/
2 つ目は、すべての To Do レコードをインデックス ビューに一覧表示することで、思われるデータを事前に読み込みます。to do をクリックしてエントリを表示すると、期待どおりに削除が機能します。(ちなみに、これは、例 1 のコンソールで App.ToDo.find() を実行するだけでも機能します。)
これは Ember データのバグのように感じます。私は正しいのでしょうか、それとも何か間違っているのでしょうか?
ありがとう、
ダン