Alloy 모델과 DB 연동

아직 완성된 글이 아닙니다.
—-
Alloy의 모델은 Backbone의 모델을 사용하므로, Backbone의 API와 Event를 그대로 사용할수있다. 일단 스튜디오에서 Alloy모델을 생성하게 되면 /model 폴더에 해당 파일이 생성되고 기본 구조는 다음과 같다.

1. 모델의 기본 구조

exports.definition = {
 config : {
 // table schema and adapter information
 },
extendModel: function(Model) { 
 _.extend(Model.prototype, {
 // Extend, override or implement Backbone.Model 
 });

 return Model;
 },
extendCollection: function(Collection) { 
 _.extend(Collection.prototype, {
 // Extend, override or implement Backbone.Collection 
 });

 return Collection;
 }
}

일반적인 MVC 모델의 경우 다음 그림과 같이 컨트롤러에서 모델과 뷰를 생성하고 모델을 뷰의 인자로 넘기게 되는데, Alloy도 같은 MVC 구조를 가지기 때문에 Alloy 모델은 컨트롤러에서 생성되어야한다.
< 그림1, 삽입>
– MVC 기본 아키텍쳐 UML

모델 생성은 Alloy.createModel() 메소드를 이용한다. 샘플 코드를 보자.

 var book = Alloy.createModel('book', {title:'Green Eggs and Ham', author:'Dr. Seuss'}); 
 var title = book.get('title');
 var author = book.get('author');
 // Label object in the view with id = 'label'
 $.label.text = title + ' by ' + author;

위 코드에서 book 객체는 백본 모델이기 때문에 백본의 API를 그대로 사용할 수 있다. 그리고 이렇게 생성된 모델을 다른 컨트롤러에서도 사용하고 싶은 경우가 매우 많을 것이다. 이럴때는 Alloy.Models.instance() 메소드를 이용해 접근할수있다.

var book = Alloy.Models.instance('book');

물론 XML 뷰에도 모델을 넘겨서 사용하고 싶을수도 있다. 다음과 같이 XML 뷰와 함께 모델을 정의하면, 컨트롤러는 모델과 뷰를 자동으로 생성한다.

 <Alloy>
 <Model id="myBook" src="book" instance="true"/>
 <Window>
 <TableView id="table" />
 </Window>
</Alloy>

XML 뷰를 통해 자동으로 생성된 모델은 다음과 같은 방법은 접근한다.
– id 지정시, 컨트롤러에서 $.myBook 으로 접근
– src를 이용해 Alloy.Models.book 으로도 접근 가능 (전역변수)
– src는 book.js 와 맵핑된다.
– instance가 true면 싱글톤 모델을 만든다. false면 다른 인스턴스를 만든다.

2. 모델 설정

모델의 config 객체는 columns, defaults, adapters 라는 3개의 객체를 가진다.

  • columns – 테이블 스키마, SQLite가 인식하지 못하는 값은 모두 TEXT 타입로 지정된다.
  • defaults – undefined일 경우 설정되는 기본값
  • adapters – 실제 저장소와 맵핑하기 위한 type과 collection_name을 갖는다.
exports.definition = {
 config: {
 "columns": {
 "title": "String",
 "author": "String"
 },
 "defaults": {
 "title": "-",
 "author": "-"
 },
 "adapter": {
 "type": "sql",
 "collection_name": "books"
 }
 }
}

3. Backbone.Model 클래스 확장하기

기존 모델을 확장해서 필요한 필드나 함수를 만들수있다. 예를 들면 다음과 같다.

exports.definition = {
  config : {
   // table schema and adapter information
  },
  extendModel: function(Model) { 
    _.extend(Model.prototype, {
      // Implement the validate method 
      validate: function (attrs) {
        for (var key in attrs) {
           var value = attrs[key];
           if (key === "title") {
             if (value.length <= 0) {
               return "Error: No title!";
             }
           }
           if (key === "author") {
             if (value.length <= 0) {
               return "Error: No author!";
             } 
           } 
        }
      },
      // Extend Backbone.Model
      customProperty: 'book',
      customFunction: function() {
        Ti.API.info('I am a book model.');
      }, 
   });

   return Model;
 }
}

위 코드를 컨트롤러에서는 다음과 같이 사용한다.

var book = Alloy.createModel('book', {title:'Green Eggs and Ham', author:'Dr. Seuss'}); 
// Since set or save(attribute) is not being called, we can call isValid to validate the model object
if (book.isValid() && book.customProperty == "book") {
 // Save data to persistent storage
 book.save();
}
else {
 book.destroy();
}

4. 콜렉션

콜렉션은 순서가 있는 모델들의 집합을 의미한다. 마찬가지로 Backbone의 콜렉션을 상속받았으므로 똑같이 쓸수있다. 콜렉션 생성은 Alloy.createCollection() 메소드를 사용한다.

var library = Alloy.createCollection('book'); 
library.fetch(); // Grab data from persistent storage

모델과 마찬가지로 전역적으로 사용하고 싶다면 Alloy.Collections 객체를 이용한다.

var library = Alloy.Collections.instance('book');

5. 콜렉션 확장하기

모델과 마찬가지로 확장가능하고 백본에서 구현하지 않고 인터페이스만 뚫어둔 comparator 메소드를 구현해서 콜렉션을 정렬할 수 있다.

exports.definition = {
config : {
 // table schema and adapter information
 },
extendModel: function(Model) { 
 _.extend(Model.prototype, {
 // Extend, override or implement the Backbone.Model methods 
 });
 return Model;
 },
extendCollection: function(Collection) { 
 _.extend(Collection.prototype, {

 // Implement the comparator method.
 comparator : function(book) {
 return book.get('title');
 }
}); // end extend
  return Collection;
 }
}

6. 이벤트 핸들링

on, off, trigger 3개의 주요 메소드를 활용한다. 주의해야할 것은 3.0부터 Alloy모델과 콜렉션은 타이타늄 메소드를 지원하지 않는다. (addEventListener, removeEventListener, fireEvent)
또하나 주의할점,Backbone의 add, change, destroy, fetch, remove, reset 이벤트는 오버라이딩하지 말것!

var library = Alloy.createCollection('book');
function event_callback (context) {
 var output = context || 'change is bad.';
 Ti.API.info(output);
};
// Bind the callback to the change event of the collection.
library.on('change', event_callback);
// Trigger the change event and pass context to the handler.
library.trigger('change', 'change is good.');
// Passing no parameters to the off method unbinds all event callbacks to the object.
library.off();
// This trigger does not have a response.
library.trigger('change');