Ext JS 4 – The Data Package (Veri Paketi) – Bölüm 2

Tekrar merhaba,

Bir önceki Ext JS 4 veri paketi (Data package) – Bölüm 1 ile ilgili yazımın devamı olan bölüm 2′ ye hoş geldiniz. Bu bölümde sizlere ilişkiler (assocations), iç içe verilerin yüklenmesi (nested data), geçerlilik ve doğrulama (validations) konularını aktarmaya çalışacağım.

İlişkiler (Assocations)

Model’ler Assocations API yardımıyla birbirleri ile bağlantılı hale getirilebilirer. Birçok uygulamada pek çok model kullanılır ve genellikle bu modeller birbirleri ile ilişki halinde olurlar. Örneğin bir blog yazma uygulamasında kullanıcılar (Users), yazılan makaleler (Posts) ve yorumlar (Comments) bu durum için iyi bir örnek teşkil eder. Her kullanıcı yeni makaleler yazabilir ve bu makaleler için yorumları alabilir. Bu ilişkileri aşağıdaki gibi ifade edebiliriz;

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

    // kısaltma olarak { model: 'Post', name: 'posts' }
    hasMany: 'Post'
});

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

    proxy: {
        type: 'rest',
        url : 'data/posts',
        reader: {
            type: 'json',
            root: 'posts'
        }
    },

    // her bir makale sadece bir kullanıcıya aittir
    belongsTo: 'User',
    hasMany: { model: 'Comment', name: 'comments' }
});

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

    // her bir yorum sadece bir makaleye aittir
    belongsTo: 'Post'
});

Bu uygulamada farklı modeller arasında zengin ilişkileri ifade etmek çok kolay görünmektedir. Her bir modelin diğer modeller ile ilişkisi herhangi bir sayıda olabilir ve modeller herhangi bir sıralamada tanımlanabilir. Bir modeli ilişkili olarak tanımladığımızda diğer modellere ve bunların verilerine rahatça erişebiliriz. Örneğin; Belirli bir kullanıcıya ait tüm makaleleri ve onlara bağlı yorumları tek seferde dökmek yada konsola basmak istersek aşağıdaki gibi bir yöntemi kullanabiliriz;

// ID'si 1 olan kullanıcının yüklenmesi başarılı olursa
// ona bağlı tüm makaleleri ve makalelere bağlı yorumları
// konsola basar
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'));
            });
        });
    }
});

Bu durumda her modele otomatik olarak ilişkide olduğu model’ in çoğul hali isminde bir fonksiyon eklenir. user.posts() fonksiyonu ile bir kullanıcının birden fazla makalesi (hasMany) kuralıyla ilişkili verilerine ulaşabileceğimiz store objesi döndürülür. Buna bağlı olarak Post modeline tamımladığımız her bir makale bir kullanıcıya bağlıdır (belongsTo) ve her makalenin birden fazla yorumu olabilir (hasMany) kuralıyla ilişkili Comments modeli, yine otomatik olarak oluşturulan posts.comments() fonksiyonu sayesinde Comments store’ unu ve bağlı verileri döndürülür.

İlişkileri verileri yüklemekten ziyade ilişkili yeni kayıtlar oluşturmak için daha kullanışlıdır:

user.posts().add({
    title: 'Ext JS 4.0 MVC Mimarisi',
    body: 'Bu büyük fikir Ext JS uygulamarınızı MVC mimarisini kullanarak inşaa etmenizi sağlar'
});

user.posts().sync();

Kullanıcıya yeni makale verisi eklenirken otomatik olarak user_id alanına kullanıcıya ait ID’ de eklenir. sync() fonksiyonu ise, yapılandırılmış proxy üzerinden yeni makaleyi kaydeder. Eğer bu kaydetme işlemi tamamlandığında haberdar olmak isterseniz bir callback (geri çağırma) ile işlemin başarılı yada başarısız oldugunu kontrol edebilirsiniz.

BelongsTo ilişkisi ise model’de bağlı olduğu modele ait yeni bir fonksiyonlar oluşturur. Aşağıda nasıl kullanıldığını görelim;

// kulllanıcıya ait referansı her bir makalenin bir kullanıcısı olur
// ilişkisi ile (belongsTo) alalım
post.getUser(function(user) {
    console.log('Posta ait kullanıcının referansı: ' + user.get('name'))
});

// makalenin kullanıcısını değiştirmeyi deneyelim
post.setUser(100, {
    callback: function(product, operation) {
        if (operation.wasSuccessful()) {
            console.log('Makaleye ait kullanıcı güncellendi');
        } else {
            console.log('Makalete ait kullanıcı güncellenemedi');
        }
    }
});

Bu sefer getUser() fonskiyonu kullanarak kullanıcı bilgilerini asenkron olarak yüklenebildiğini görüyoruz. setUser() fonksiyonu makale (Post) modelinde bulunan yabancı anahtar (foreign key) olan user_id alanını 100 olarak günceller. Her zamanki gibi işlem tamamlandığında callback yöntemi ile başarılı yada başarısız sonuçları takip edebiliriz.

İç İçe Verileri (Nested Data) Yüklemek

Users.load fonksiyonu kullanarak ve yukarıda anlatılan proxy ve ilişkileri tanımlayarak iç içe işlemler sayesinde bir kullanıcıya ait tüm ilişkili verileri geri döndürebilirsiniz. Bu durumda iç içe çağırılan methodlar ve bunların ilişkileri sayesinde sunucuya birden fazla istek gönderilecektir. Bunun başka bir yolu olup olmadığını merak ediyor olabilirsiniz. Bu durum yerine verilerinizi sunucuda aşağıdaki gibi bir yapıda tek seferde döndürmek alternatif bir çözümdür. Bu durumda daha önce tanımlanan model ilişkileri tüm bu veriyi de algılayacaktır.

{
    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'
                        }
                    ]
                }
            ]
        }
    ]
}

Tüm bu veriler uygulama çatısında otomatik olarak ayrıştırılır. Modellere vekil’ ler (proxy) aracılığı ile neredeyse heryerden veri yüklemek oldukça kolaydır ve okuyucular (readers) json, xml v.s. herhangi bir dönüş tipini okuyabilirler.

İlişkiler ve validasyonlara ait çalışan demoyu inceleyiniz.

Modeller aracılığı ile tabiki iç içe olmayan verileri de yüklemek mümkündür. Tembel yükleme (lazy loading) denilen bu yöntem  sadece ilişkisel verileri yüklemek için yararlı olabilir. Önce normal yöntemle kullanıcıları yüklüyoruz ve işlem başarılı olduktan sonra devamında kullanıcılara ait olan makaleleri yüklüyoruz ve buna ait callback yöntemi ile geri döndürülen makalelerin içerisinde Ext.each yöntemi ile dönerek her bir makaleye ait yorumlara da erişebiliriz.

Tembel ilişkilendirme (Lazy Assocations) yöntemini çalışan demosundan inceleyiniz.

Doğrulama ve Geçerlilik Denetimi (Validations)

Ext JS 4 modelleri doğrulama özelliği sayesinde çok daha zengin özelliklere büründü. Bunu göstermek için daha önceki örneklerimizde tanımladığımız ilişkisel modelleri kullanarak doğrulamaları bunların  üzerine inşa edeceğiz. İlk olarak User model’ine bazı validasyonlar tanımlıyoruz:

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: ...
});

Doğrulama alan tanımlamaları field (alan) tanımlamalarıyla benzerlik göstermektedir. Her iki durumda da alanı ve doğrulama tipini belirleriz. Yukarıdaki örneğimizde ‘name‘ alanı en az 5 karakter olabilir, ‘age’ alanı sadece numara olabilir, ‘gender‘ alanı ‘male‘ veya ‘female‘ olabilir ve ‘username‘ admin dışındaki herşey olabilir. Bazı dogrulamalar ‘lenght’ alanında oldugu gibi minimum veya maksimum değerleri alabilir. Yerleşik olarak 5 adet doğrulama bulunmasına karşın ‘format‘ alanındaki gibi kurallı ifadeler (REGEX) kullanarak yada birçok kombinasyon uygulayarak birçok geçerlilik doğrulamasını yapabilirsiniz.

  • persence varlığın sadece bir tane olduğunu yani tekil olduğunu garantiler ve doğrular ancak string alanın boş olmasını kabul etmez
  • lenght varlığın minimum veya maksimim değerler arasında kalmasını garanti eder ama her iki durumu birden kullanmak isteğe bağlıdır.
  • format varlığın verilen kurallı ifade ile doğrulanmasını garanti eder. (Kurallı ifadelerle ilgili daha ayrıntılı araştırma yapmanızı öneririm)
  • inclusion varlıgın verilen dizi içerisindeki değerlerden birisi olmasını garanti eder. (Enum veri tipine benzetebiliriz)
  • exclusion varlığın verilen dize içerisindeki değerler dışında tutulmasını sağlar. (Örneğin ‘admin’ gibi bir verinin bloklanmasını önlemek için)

Şimdi farklı olasılıklarla bir kullanıcıyı oluşturup doğrulamarı test edelim. Burada doğru yada yanlış veriler girip validasyonları çalıştırarar ne şekilde sonuçlar döndürdüğünü inceleyeceğiz:

// şimdi hatalı veriler içeren bir kullanıcı oluşturmaya çalışalım
var newUser = Ext.create('User', {
    name: 'admin',
    age: 'twenty-nine',
    gender: 'not a valid gender'
});

// oluşturduğumuz yeni kullanıcı için validasyonları çalıştırıyoruz
// ve errors değişkenine atıyoruz
var errors = newUser.validate();

// doğrulama hatası varsa 'false' döndürülür
console.log('Kullanıcı doğrulandı mı?', errors.isValid());

// Modelde bulunan tüm hataları bir dizi olarak döndürür
console.log('Tüm hatalar:', errors.items);

// Age alanı ile ilgili hataları döndürür
console.log('Age alanı hataları:', errors.getByField('age'));

validate() fonksiyonu modelde bulunan tüm tanımlanmış validasyonları çalıştırır ve geriye Errors adında bir obje döndürür. Bu basıt obje içinde herhangi bir hata varsa barındırır, ve genel olarak tüm doğrulamaların geçerli olup olmadığını isValid() fonksiyonuyla kontrol etmemizi sağlar. Eğer ‘true‘ dönerse herhangi bir alanda herhangi bir hata bulunmakatadır anlamına gelir. Ancak getByField() fonksiyonuyla belirli bir alana ait hatalara da ulaşabiliriz.

İlişkilendirilme ve doğrulamaların birlikte kullanıldığı demoyu inceleyiniz.

Kaynak:
http://www.sencha.com/learn/the-data-package/

Bu makalenin başlangıcı olan Bölüm – 1:
http://www.tayfunoziserikan.com/blog/ext-js-4-the-data-package-veri-paketi-bolum-1

Evet gördüğünüz gibi birçok yeni işlevsel özelliği bünyesinde barındıran Ext JS 4 Veri Paketi (Data Package) işleri oldukça kolaylaştırıyor ve Ext JS 4 kullanarak hazırlanmış JavaScript uygulamalarınızı daha da güçlendiriyor. ORM ile ilişkili olan bu konuyu ağırlıklı olarak Ext JS’in eğitim merkezinde (learning center)  bulunan ilişkili makalesinden yararlanarak ve kendi yorumumu katarak hazırlamaya çalıştım. Diğer konular için de bu adresi yakından takip etmenizi tavsiye ederim.  Umarım sizlere faydası olmuştur.

İyi çalışmalar dilerim.

About tayfun.ozis.erikan

Web Developer, Graphic & Web Designer Zend Framework, CodeIgniter, ExtJS & Sencha Touch User Kebab Framework Developer The co-founder of lab2023 - internet technologies
This entry was posted in Açık Kaynak, Akıl Defterim, Ext JS, JavaScript, Seminerler & Etkinlikler, Seminerler Notlarım and tagged , , , , , , , , , , , , , , , , . Bookmark the permalink.

Leave a Reply

Your email address will not be published. Required fields are marked *

*

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>