На прошлой неделе я создал новое одностраничное приложение, используя Ember.js в качестве клиентской среды (см. Часть 1 и Часть 2 ). Сегодня я дополняю приложение, добавляя Windows Azure Mobile Services для хранения данных. Если вы не хотите просматривать предыдущие два сообщения, я загрузил текущее приложение на GitHub по адресу https://github.com/Blackmist/emberapp.
Мобильные службы — это функция предварительного просмотра Windows Azure, поэтому вам может потребоваться включить предварительный просмотр для вашей учетной записи . Сделав это, выполните следующие действия, чтобы создать новый сервис и получить код HTML и JavaScript для добавления клиента в приложение.
-
На портале управления Windows Azure нажмите кнопку + NEW , а затем выберите Compute , Mobile Service , Create .
-
В диалоговом окне «Создание мобильной службы» введите уникальное значение в качестве URL-адреса. Вы можете создать новую базу данных или использовать существующую; В любом случае вам нужно будет указать имя пользователя и пароль для подключения к базе данных.
Примечание . Службы Windows Azure Mobile Services используют базу данных SQL в качестве внутреннего хранилища данных, но она абстрагируется от вас через службу на основе Node.js., которая предоставляет вам CRUD API. Теоретически, Microsoft может заменить серверную часть на что-то другое, например, хранилище таблиц, и это не повлияет на клиента.
-
После того, как вы откроете страницу «Ваш мобильный сервис создан», выберите меню « Данные» , а затем « Добавить таблицу» .
-
При появлении запроса создайте новую таблицу с именем posts . Примите все значения по умолчанию, установив флажок.
-
Затем щелкните значок молнии (быстрый запуск) слева от вкладок для вашего проекта. Вы вернетесь на страницу « Начало работы» . Здесь выберите Подключить существующее приложение HTML . Скопируйте и вставьте эту строку <script> …. </ script> в файл index.html . Безопасное место для вставки перед следующей строкой:
<!-- build:js scripts/main.js -->
Сохраните файл index.html .
-
Затем скопируйте код JavaScript, который определяет клиента. Добавьте это в файл app.js. Поместите его сразу после следующей строки:
var App = window.App = Ember.Application.create();
Сохраните файл app.js.
На этом этапе приложение загружает клиент Windows Azure Mobile Services, но ничего с ним не делает.
Эмбер-модель
Чтобы подключить мобильные сервисы к Ember, я использовал ember-модель . Зачем? Это обеспечивает базовую структуру с предположением, что вы принесете свой собственный доступ к данным; вы просто реализуете создание / сохранение / и т.д. функции, которые уже заглушены.
Примечание. Теоретически можно подумать, что любой клиент REST будет работать, поскольку у Mobile Services есть API REST, но на практике многие клиенты REST довольно самоуверенны. Как будто они ожидают корневой узел в данных JSON или хотят использовать PUT вместо PATCH для обновлений и тому подобного. Можно заставить работать с некоторыми усилиями, но уже есть клиент, так почему бы не использовать это?
Чтобы добавить Ember-модель в проект, выполните следующие действия:
-
Откройте новую командную строку / BASH / Terminal session и используйте Git, чтобы сделать локальный клон репозитория. НОТА! Это должен быть новый каталог, а НЕ внутри каталога emberapp .
git clone https://github.com/ebryn/ember-model
-
Перейдите в новый каталог ember-model и выполните следующие команды для создания проекта.
bundle
rake dist -
Скопируйте файл ember-model / dist / ember-model.js в каталог emberapp / app / scripts .
-
Добавьте ссылку на scripts / ember-model.js в файл index.html прямо под строкой, которая ссылается на «scripts / ember-model.js». Например:
<script src="components/ember/ember.js"></script>
<script src="scripts/ember-model.js"></script>
<!-- endbuild -->
Определите адаптер мобильных служб Windows Azure
Чтобы создать адаптер, который ember-модель может использовать для общения с Windows Azure Mobile Services, добавьте следующее в файл app.js. Это должно прийти после var client = new WindowsAzure.MobileServiceClient(.....);
строки:
// ember-model-based adapter Ember.WAMAdapter = Ember.Object.extend({ table: null, init: function() { this.table = this.get('table'); }, find: function(record, id) { var query = this.table.where({ id: id }); return query.read().then(function(data) { Ember.run(record, record.load, data); }); }, findAll: function(klass, records) { return this.table.read().then(function(data) { Ember.run(records, records.load, klass, data); }); }, findQuery: function(klass, records, params) { var query = this.table.where(params); return query.read().then(function(data) { Ember.run(records, records.load, klass, data); }); }, createRecord: function(record) { return this.table.insert(record.toJSON()).then(function(data) { Ember.run(function() { record.load(data.id, data); record.didCreateRecord(); }); }); } });
Это было довольно легко подключить, поскольку для этого просто требуется передать данные, возвращенные операцией Mobile Services, в Ember.run вместе с некоторыми другими функциями, которые предоставляет инфраструктура ember-mobile.
Определите модель
Добавьте следующее после адаптера. Это определяет модель для публикации и создает новый экземпляр адаптера. Обратите внимание, что я указываю таблицу для использования (posts) как часть вызова create для адаптера:
var attr = Ember.attr; //define model App.Post = Ember.Model.extend({ id: attr('number'), title: attr('string'), author: attr('string'), body: attr('string'), posted: attr('date') }); //Point the adapter at the table you want to use. App.Post.adapter = Ember.WAMAdapter.create({ table: client.getTable('posts') });
Подключите шаблоны и контроллер
Во второй части я создал несколько шаблонов, которые использовали статический контент и / или ничего не делали с введенными вами данными. Время это исправить.
Ниже приведены обновления к posts.hbs , файлу app.js (Маршруты, контроллеры) и новый шаблон post.hbs для отображения отдельных сообщений.
// Newpost controller App.NewpostController = Ember.ObjectController.extend({ title: '', author: '', body: '', save: function() { //create the post var now = new Date(); var post=App.Post.create({ title: this.get('title'), author: this.get('author'), body: this.get('body'), posted: now.toString('dddd, MMMM, yyyy'), }); post.save(); // set these back to '' so the form is pretty this.set('title',''); this.set('author',''); this.set('body',''); //transition back to posts this.transitionToRoute('posts'); } }); App.Router.map(function () { // put your routes here this.resource('posts', function() { this.resource('post', { path: ':post_id' }); }); this.resource('newpost'); }); //redirect to posts App.IndexRoute = Ember.Route.extend({ redirect: function() { this.transitionTo('posts'); } }); App.PostsRoute = Ember.Route.extend({ model: function () { return App.Post.findAll(); } })
<h2>{{title}}</h2> <h4>by {{author}}, <small>{{posted}}</small></h4> {{body}} <div class="well well-small"> <h4>Tags: <small>{{topics}}</small></h4> </div>
<div class="container-fluid"> <div class="row-fluid"> <div class="span3"> <ul class="nav nav-tabs nav-stacked"> {{#each model}} <li> {{#linkTo 'post' this}}{{title}}{{/linkTo}} </li> {{/each}} </ul> </div> <div class="span7"> {{outlet}} </div> </div> </div>
NewpostController
Контроллер теперь фактически сохраняет данные при отправке нового сообщения. Он использует App.Post.create для создания нового сообщения, а затем post.save () для его сохранения. Поскольку база данных изначально пуста, вам нужно создать один или два поста, чтобы заметить остальные изменения.
Posts.hbs
Обратите внимание, что в файле posts.hbs статический список заменяется итерацией по элементам в коллекции, и для каждого из них возвращается элемент списка. Изначально этот список будет пустым, пока вы не добавите несколько сообщений.
Также обратите внимание, что для каждого элемента есть {{#linkTo}}, который ссылается на маршрут с именем «post». Таким образом, каждый элемент в списке может быть выбран для отображения отдельного сообщения. Он будет отображаться в {{outlet}} внизу файла posts.hbs.
Post.hbs & почтовый маршрут
Для поддержки новой ссылки из шаблона сообщений в app.js был добавлен новый маршрут . Это вложенный маршрут, так как отдельный пост является дочерним по отношению к коллекции постов.
this.resource('posts', function() { this.resource('post', { path: ':post_id' }); });
Это также передает поле идентификатора сообщения в маршрут сообщения, что позволяет нам указывать отдельные сообщения через URL. Например, http: // localhost: 9000 / # / posts / 1 загрузит сообщение с идентификатором 1.
В самом шаблоне post.hbs нет ничего удивительного, поскольку он просто отображает выбранный пост.
Индексный маршрут
Обратите внимание, что я перенаправил индексный маршрут на маршрут сообщений. Это просто гарантирует, что посетители будут перенаправлены на страницу сообщений по умолчанию.
Проверьте это
Если вы используете ссылку «Запись» на панели навигации, при сохранении сообщения оно должно перенаправить вас на страницу «Сообщения» и отобразить новое сообщение в виде ссылки в списке сообщений. Нажатие на ссылку должно отобразить сообщение в правой части страницы. Если вы зайдете на портал управления Windows Azure и перейдете к своему экземпляру мобильных служб и к таблице сообщений, вы сможете увидеть созданные там записи.
Резюме
На этом этапе приложение позволяет вам хранить и извлекать данные из мобильных служб Windows Azure, но оно немного открыто для платформы ведения блогов, поскольку позволяет любому публиковать сообщения без аутентификации или авторизации. В следующей статье я покажу, как включить аутентификацию с помощью Windows Azure Mobile Services.