SQL yazmaya son! Bir kaç tablo daha - NOY#6

noyjavascriptoyunyoutube

6 yıl önce 0 yorum

Modeller üzerinde SQL yazmak yönetimi zorlaştırdığı için bir SQL oluşturucu kütüphaneye ihtiyacımızın olduğunu hissettim. Bir kaç araştırma yaptım fakat SQL'i daha basit nasıl yazarız konusunda yine tereddütlerim oldu baktığım kütüphaneler de bir sürü method içeriyordu. Eğer ben çok method kullanacaksam zaten SQL kullanırım ne gerek ve benim SQL oluşturucuya. Araştırdığım ve hoşuma giden kütüphaneler:

https://www.npmjs.com/package/sqlmaker
https://www.npmjs.com/package/squel

Fakat ben bu kütüphaneleri kullanmak istemedim :/ 2016 sıralarında kendi yazdığım bir kütüphane aklıma geldi. Dedim şuna bir bakayım (PHP üzerinde yazmıştım o sıralar). Bir SQL oluşturucu için gerekli çoğu methodu yazmışım ve bu çok basit. Sonra dedim ben bunu JavaScript'e çeviririm :) Standartlarını bozarak da olsa çevirebildim. Ve ismine

sqlmaster dedim :)

Birkaç uğraş ve çaba ile yayınladım ve npm üzerinde de paylaştım. Projemize kurmak için:

npm i sqlmaster --save

Nasıl kullanılacağını dokümanına yazdım. Biz ilk işimize user modelden başlayalım. Hemen insert sorgumuzu yazabiliriz. api/models/users.js dosyasını düzenleyelim.

const database = require('../../database');
const sm = require('sqlmaster');

class Users {
    insert(user) {
        var query = sm
        .from('users')
        .insert({
            name: user.name,
            email: user.email,
            date: new Date(),
        })
        .exec();

        return new Promise((resolve, reject) => {
            database.execute(query, (err, res) => {
                if (err !== null) {
                    reject(err)
                } else {
                    resolve(true);
                }
            })
        })
    }

    isExist(email) {
        var query = sm
        .from('users')
        .where('email = :email', {
            ':email': email
        })
        .select([
            "email"
        ])
        .exec();

        return new Promise((resolve, reject) => {
            database.execute(query, (err, res) => {
                if (err !== null) {
                    reject(err)
                } else {
                    if (res.rows.length > 0)
                        return resolve(true); // kullanıcı var
                    return resolve(false); // kullanıcı eklenmemiş
                }
            })
        })
    }
}

module.exports = new Users();

Dört tablo daha

Artık oyunumuzun asıl amacına gelelim yani "Oyunları yönetelim!"

İlk önce satranç'ın kurallarından bahsettiğim yazımdan bahsedeyim biraz. Aslında satranç'ın FEN ve SAN üzerinden neredeyse tüm modellemelerini yapabileceğimizi söylemiştik. Kısaca FEN, oyunun son durumu. SAN, oyunda yapılan tüm hareketlerdi. Peki biz buna göre nasıl bir tablo oluşturacağız ona bakalım.

Oyun için toplamda 3 adet tablo olacak bunlar: games, game_fen, game_san. Şunları içerecekler:

games

id from to date from_date to_date
oyunun id'si oyunu teklif eden veya açan kişinin id'si oyunu kabul eden kişinin id'si oyunun başlama tarihi (kalan zamanı) oyunu açan kişinin oyunun başlangıç tarihine süre eklenmiş (ör: 10dk) tarihi (kalan zamanı) oyunu kabul eden kişinin oyunun başlangıç tarihine süre eklenmiş (ör: 10dk) tarihi

game_fen 

id fen
oyunun id'si oyunu fen değeri

game_san 

id san
oyunun id'si oyunu san değeri

Oyunun san değeri belirli bir uzunlukta olmadığından bunun alan tipine TEXT vereceğiz. FEN değeri de aynı şekilde belirli bir uzunluğa sahip değil ama TEXT gibi bir ifade için ise çokta uzun değil. Bir kaç araştırma yaptım ama kesin bir sonuca varamadım en son 144 karakter olabileceği konusunda konuşmalar buldum:

http://www.talkchess.com/forum/viewtopic.php?topic_view=threads&p=531397&t=49083
http://www.talkchess.com/forum/viewtopic.php?t=49083
http://rybkaforum.net/cgi-bin/rybkaforum/topic_show.pl?tid=8689

Ama ben kesin bir sonuç bulunamadığını göz önüne alarak 255 karakter verme konusunda karar kıldım. Eğer ki 255 karakteri bile geçebilecek bir FEN olabilirse buna sonra değiniriz.

Tabloları oluşturalım

CREATE TABLE games (id SERIAL PRIMARY KEY, "from" INT, "to" INT, date DATE, from_date DATE, to_date DATE);
CREATE TABLE game_fen (id INT PRIMARY KEY, fen CHAR(255));
CREATE TABLE game_san (id INT PRIMARY KEY, san TEXT);

Ve son olarak kullanıcıların giriş yapmasını sağlayacak bir sistem daha kurmalıyız. Yani şifresini tutmalıyız. Bunun için user_password diye bir tablo oluşturalım.

id password
kullanıcının id'si kullanıcının şifresi
CREATE TABLE user_password (id INT PRIMARY KEY, password CHAR(128));

Kayıt sistemini değiştirelim

Şifreleme işlemi için pbkdf2Sync kullanacağız. user_password tablosu için bir model oluşturalım. api/models/userPassword.js dosyasını şöyle oluşturalım:

const database = require('../../database');
const sm = require('sqlmaster');
const crypto = require('crypto');

class UserPassword {
    insert (id, password) {
        return new Promise((resolve, reject) => {
            if (!password)
                return reject(new Error('password is null'));

            password = crypto.pbkdf2Sync(password, 'satranc', 100000, 64, 'sha512').toString('hex');

            var query = sm
            .from('user_password')
            .insert({
                id: id,
                password: password,
            })
            .exec();

            database.execute(query, (err, res) => {
                if (err !== null) {
                    reject(err)
                } else {
                    resolve(true);
                }
            })
        })
    }
}

module.exports = new UserPassword();

api/models/users.js dosyasını şöyle düzenleyelim:

const database = require('../../database');
const sm = require('sqlmaster');

const UserPassword = require('./userPassword');

class Users {
    insert(user) {
        var self = this;
        var query = sm
        .from('users')
        .insert({
            name: user.name,
            email: user.email,
            date: new Date(),
        })
        .returning('id')
        .exec();

        return new Promise((resolve, reject) => {
            database.execute(query, (err, res) => {
                if (err !== null) {
                    reject(err)
                } else {
                    // üstte yazılan returning sayesinde insert edilince id gelmesini sağlıyor.
                    UserPassword.insert(res.rows[0].id, user.password).then(res => {
                        resolve(true);
                    }, reject);
                }
            })
        })
    }
...

Diğer controller'ların erişmesi için api/models/index.js dosyasına bir satır ekleyelim ve şöyle olsun:

exports.Users = require('./users');
exports.UserPassword = require('./userPassword');

Böylelikle kullanıcılar artık password değerini gönderdiğinde onu da kaydetmiş olacak. Bu haftaki bölüm bu kadardı diğer bölümde görüşmek üzere.

Düşündüklerin nedir ?

Abdurrahman Eker

(1010 Eylül 11111001100)

  • Full Stack Developer Turkey/Sivas
  • İnternette Avare Kodcu
  • coffee
  • github
  • instagram
  • linkedin
  • youtube
  • Yeni içeriklerden haberdar olmak ister misin ?