Skip to content
cliffhangers edited this page Mar 26, 2012 · 11 revisions

Data

데이터 패키지는 41개의 클래스로 애플리케이션 데이터를 저장/로드한다. 하지만 다른 무엇보다 중요한 세 가지 Model, Store, Ext.data.proxy.Proxy가 있다. 이들은 거의 모든 애플리케이션에 쓰이고 또한 많은 satellite 클래스들을 지원한다.

Models and Stores

데이터 패키지의 중심은 Ext.data.Model이다. 모델은 애플리케이션의 몇 가지 타입의 데이터를 대표한다. 예를 들면 e-commerce 앱은 유저, 제품, 주문을 위한 모델을 가지고 있다. 가장 단순한 모델은 필드와 데이터 세트뿐이다. 모델의 네 가지 중요한 부분은 Fields, Proxies, Associations and Validations 다.

Let's look at how we create a model now: 우리가 모델을 만든 방법을 살펴보자. Ext.define('User', { extend: 'Ext.data.Model', fields: [ { name: 'id', type: 'int' }, { name: 'name', type: 'string' } ] });

모델들은 주로 Store와 함께 쓰인다. 이것은 기본적으로 Model 인스턴스들의 모음이다. Store를 세팅하고 데이터를 로딩하는 것은 간단하다.

Ext.create('Ext.data.Store', { model: 'User', proxy: { type: 'ajax', url : 'users.json', reader: 'json' }, autoLoad: true });

우리는 Store를 Ajax Proxy, 데이터가 로드된 url 그리고 데이터 디코드를 위해 사용한 Reader를 사용하여 설정했다. 이 예제의 서버는 JSON를 리턴한다. 그래서 우리는 응답을 읽기위해 Json Reader를 셋업했다. Store는 url로 설정된 users.json로부터 User 모델 인스턴스 세트들을 자동로딩한다.

{ success: true, users: [ { id: 1, name: 'Ed' }, { id: 2, name: 'Tommy' } ] } 라이브 데모를 보려면 Simple Store 예제를 보라.

Inline data

Store는 데이터를 inline으로 로드한다. 내부적으로 Store는 각각의 Model 인스턴스 데이터 오브젝트를 변환한다. Ext.create('Ext.data.Store', { model: 'User', data: [ { firstName: 'Ed', lastName: 'Spencer' }, { firstName: 'Tommy', lastName: 'Maintz' }, { firstName: 'Aaron', lastName: 'Conran' }, { firstName: 'Jamie', lastName: 'Avins' } ] });

Inline Data example

Sorting and Grouping Store는 로컬에서 정렬, 필터링 그리고 그룹핑이 가능하고, 게다가 원격 정렬, 필터링, 그룹핑도 지원한다. Ext.create('Ext.data.Store', { model: 'User',

sorters: ['name', 'id'],
filters: {
    property: 'name',
    value   : 'Ed'
},
groupField: 'age',
groupDir: 'DESC'

}); 방금 만든 Store에서 name먼저 정렬된 후 id가 정렬된다. 그리고 ‘Ed’란 이름이 필터링되고, age가 내림차순으로 group by 된다. 언제든지 Store API를 통해 손쉽게 정렬, 필터링, 그룹핑을 할 수 있다. 라이브 데모의 Sorting Grouping Filtering Store를 보라.

Proxies

Proxy는 Model 데이터를 로딩하고 저장하는 것을 핸들링하기 위해 Store에서 사용된다. 여기엔 두 가지 타입의 Proxy가 있는데 Client와 Server다. Client proxy 예제는 브라우저의 메모리에 저장하기 위한 Memory와 HTML5 로컬 스토리지를 사용가능한 경우의 Local Storage를 포함하고 있다.

Proxy는 Model에 다이렉트로 정의될 수 있다.

Ext.define('User', { extend: 'Ext.data.Model', fields: ['id', 'name', 'age', 'gender'], proxy: { type: 'rest', url : 'data/users', reader: { type: 'json', root: 'users' } } });

// Uses the User Model's Proxy Ext.create('Ext.data.Store', { model: 'User' });

이것은 두 가지 방법으로 도움을 준다. 첫째. User model을 사용하는 모든 Store는 똑같은 방식의 데이터 로딩이 필요할 것이다. 그래서 각각의 Store에 Proxy 정의가 중복되는 것을 피할 수 있다. 둘째. 우리는 지금 Store없이 Model 데이터를 로드하고 저장할 수 있다.

// Gives us a reference to the User class var User = Ext.ModelMgr.getModel('User');

var ed = Ext.create('User', { name: 'Ed Spencer', age : 25 });

// We can save Ed directly without having to add him to a Store first because we // configured a RestProxy this will automatically send a POST request to the url /users ed.save({ success: function(ed) { console.log("Saved Ed! His ID is "+ ed.getId()); } });

// Load User 1 and do something with it (performs a GET request to /users/1) User.load(1, { success: function(user) { console.log("Loaded user 1: " + user.get('name')); } });

Proxy는 HTML5의 LocalStorage와 SessionStorage의 신기능의 장점을 취할 수있다. 오래된 브라우저들이 HTML5 API를 지원하지 않더라도, 많은 애플리케이션에서 상당한 이점을 취할 수 있어 매우 유용하다.

Example of a Model that uses a Proxy directly

Associations

Model은 Associations API와 함께 링크될 수 있다. 대부분의 애플리케이션들은 많이 다른 Model과 거의 항상 연관된 Model을 다룬다. 블로그 저작 애플리케이션은 유저를 위한 Model과 글쓰기, 코멘트 기능이 있을 것이다. 각각의 유저는 글쓰기 및 코멘트를 달 수 있다. 그런 관계를 이런 식으로 표현할 수 있다.

Ext.define('User', { extend: 'Ext.data.Model', fields: ['id', 'name'], proxy: { type: 'rest', url : 'data/users', reader: { type: 'json', root: 'users' } },

hasMany: 'Post' // shorthand for { model: 'Post', name: 'posts' }

});

Ext.define('Post', { extend: 'Ext.data.Model', fields: ['id', 'user_id', 'title', 'body'],

proxy: {
    type: 'rest',
    url : 'data/posts',
    reader: {
        type: 'json',
        root: 'posts'
    }
},
belongsTo: 'User',
hasMany: { model: 'Comment', name: 'comments' }

});

Ext.define('Comment', { extend: 'Ext.data.Model', fields: ['id', 'post_id', 'name', 'message'],

belongsTo: 'Post'

});

당신 애플리케이션의 다른 Model들 사이의 풍부한 관계를 쉽게 표현할 수 있다. 각각의 Model은 다른 Model과 수없이 많은 Associations를 가지고 또한 어떤 명령에 의해 정의한 당신의 Model들을 가질 수 있다. 한번은 우리가 associated된 데이터를 쉽게 들락날락할 수 있는 Model 인스턴스를 보았다. 예를 들면, 만약 우리가 특정 User의 각각의 포스트에 모든 코멘트 로그를 남기길 원한다면, 우리는 이런식으로 할 수 있다.

// Loads User with ID 1 and related posts and comments using User's Proxy User.load(1, { success: function(user) { console.log("User: " + user.get('name'));

    user.posts().each(function(post) {
        console.log("Comments for post: " + post.get('title'));

        post.comments().each(function(comment) {
            console.log(comment.get('message'));
        });
    });
}

});

위의 우리가 만든 각각의 hasMany associations들은 Model에 신기능을 추가한 결과이다. 우리는 위에 짧게 user.posts()기능을 추가한 각각의User Model hasMany 포스트들을 선언하였다. Callinguser.posts()는 Post Model이 설정된 Store를 리턴한다. 결국 Post Model은 우리가 설정한 hasMany Comments associaion때문에 comments() 기능을 가지게 된다. Associations는 데이터를 로딩하는데 도움을 주고 또한 새로운 레코드를 만드는 데도 유용하다.

user.posts().add({ title: 'Ext JS 4.0 MVC Architecture', body: 'It's a great Idea to structure your Ext JS Applications using the built in MVC Architecture...' });

여기 인스턴트화된 새로운 포스트가 있다. 이것은 user_id 필드의 User id가 자동적으로 주어진다. Sync()를 호출하면 설정된 Proxy를 통해 새로운 포스트로 저장된다. 이것은 만약 당신이 실행종료 후 알림을 원할때 callback을 패스할 수 있는 비동기 실행이다.

belongTo association은 Model의 새로운 메소드를 발생시킨다. 여기 그걸 사용하는 방법이 있다. // get the user reference from the post's belongsTo association post.getUser(function(user) { console.log('Just got the user reference from the post: ' + user.get('name')) });

// try to change the post's user post.setUser(100, { callback: function(product, operation) { if (operation.wasSuccessful()) { console.log('Post's user was updated'); } else { console.log('Post's user could not be updated'); } } });

한번 더, function(getUser)를 로딩하는 것은 비동기이며, User 인스턴스를 가져오기 위해 callback function을 요구한다. setUser 메소드는 간단하게 foreign_key (여기서는user_id임)를 100으로 업데이트하고, Post model을 저장한다.통상적으로 callback은 성공여부에 관계없이 저장이 완료될때 triggered될 것을 패스할 수 있다.

Loading Nested Data

내장 데이터 로딩 당신은 왜 우리가 User.load 호출에 success function을 지나갔는지 궁금할 것이다. 하지만 User의 포스트와 코멘트에 접근할 때 반드시 그럴 필요는 없다. 이것은 위의 예제가 서버에서 유저를 가져오는 것을 요청할때 모든 내장 포스트와 코멘트를 가져오는것뿐만 아니라 user 데이터를 리턴하는 역할을 하기 때문이다.

{ success: true, users: [ { id: 1, name: 'Ed', age: 25, gender: 'male', posts: [ { id : 12, title: 'All about data in Ext JS 4', body : 'One areas that has seen the most improvement...', comments: [ { id: 123, name: 'S Jobs', message: 'One more thing' } ] } ] } ] }

데이터는 프레임웍에 의해 모두 자동으로 parse된다. 이것은 대부분 어디서든 당신의 데이터를 로드할 Model의 Proxy들과, 어떤 응답 포맷이든 다룰 그들의Reader들을 간편하게 설정할 수 있다. Ext JS 3버전에서 Model과 Store는 Grid, Tree, Form같은 많은 컴포넌트가 있는 프레임웍을 통하여 사용할 수 있다.

relationship을 사용하는 작동하는 Model 예제 Associations and Validations.데모를 보라.

물론 당신의 데이터를 none-nested fashion으로 로드하는 것도 가능하다. 이것은 만약 당신이 필요할때만 사용하는 관계형 데이터 “lazy load”가 필요할때 유용할 것이다. 우리는 어떤 연관 포스트도 없는 User 데이터만 포함된 응답 역할을 주는것을 제외하고, 이전처럼 그냥 User 데이터를 로드해보자.

// Loads User with ID 1 User's Proxy User.load(1, { success: function(user) { console.log("User: " + user.get('name'));

    // Loads posts for user 1 using Post's Proxy
    user.posts().load({
        callback: function(posts, operation) {
            Ext.each(posts, function(post) {
                console.log("Comments for post: " + post.get('title'));

                post.comments().each(function(comment) {
                    console.log(comment.get('message'));
                });
            });
        }
    });
}

});

For a full example see Lazy Associations 전체 예제를 보려면 Lazy Associations 를 보라.

Validations

현재 Ext JS 4 Model은 풍부한 데이터 유효성검사를 지원한다. 이걸 보여주기 위해 우리가 위에 사용한 Associations 예제를 빌드할 것이다. 우선 User model에 몇개의 validation을 추가해보자.

Ext.define('User', { extend: 'Ext.data.Model', fields: ...,

validations: [
    {type: 'presence', name: 'name'},
    {type: 'length',   name: 'name', min: 5},
    {type: 'format',   name: 'age', matcher: /\d+/},
    {type: 'inclusion', name: 'gender', list: ['male', 'female']},
    {type: 'exclusion', name: 'name', list: ['admin']}
],

proxy: ...

});

Validation은 같은 포맷의 필드 정의를 따른다. 각각의 경우, 우리는 필드와 validation 종류를 명시하였다. 우리 예제의 validation은 존재하는 name필드, 적어도 5자 길이, 숫자로 된 age 필드, “male” 또는 “female” 둘 중에 하나의 gender 필드, “admin”을 제외한 유저명을 쓸 수 있다. 몇몇 validation들은 추가 설정 옵션을 가지고 있다. 예를 들어 length validation은 min이나 max 속성, format은 matcher 등을 가질 수 있다. Ext JS와 custom rules 추가를 통해 손쉽게 빌드할 수 있는 다섯개의 validation이 있다. 우선 제대로 빌드된 하나를 보자.

-presence(현재)는 값을 가진 필드를 보장한다. Zero는 empty string이 아닌 유효한 값을 카운트한다. -format은 string이 정규식 포맷에 매칭되는 부분을 보장한다. 위의 예제에서 age 필드는 최소 1자 리 이상의 4자리 숫자를 보장한다. -length는 min과 max 길이 사이가 string인 경우를 보장한다. 두 개의 constraints는 옵션이다. -inclusion(포함)은 특정 값들의 세트가 포함된 값을 보장한다. (예: 성별은 male 혹은 female 둘 중 하나) -exclusion (제외)는 값이 특정 값의 세트가 아닌 경우를 보장한다.(예: ‘admin’처럼 블랙리스팅된 유저명)

// now lets try to create a new user with as many validation errors as we can var newUser = Ext.create('User', { name: 'admin', age: 'twenty-nine', gender: 'not a valid gender' });

// run some validation on the new user we just created var errors = newUser.validate();

console.log('Is User valid?', errors.isValid()); //returns 'false' as there were validation errors console.log('All Errors:', errors.items); //returns the array of all errors found on this model instance console.log('Age Errors:', errors.getByField('age')); //returns the errors for the age field

여기의 키 펑션은 validate()다. 이것은 모든 설정된 validation들과 Errors 오브젝트를 리턴한다. 이 간단한 오브젝트는 우리가 발견한 어떤 에러의 collection이다. 추가로 몇 개의 isValid() 같은 편리한 메소드다. 이것은 만약 어떤 필드에도 에러가 없다면 true를 리턴한다. 그리고 getByField()는 주어진 필드의 모든 에러를 리턴한다. Validation들을 사용하는 전체 예제를 보려면 Associations and Validations를 보라.

Clone this wiki locally