เขียน RESTful API ใน Node.js แบบ 'โคตรไว' ด้วย Loopback
เนื่องจากผมได้มีโอกาศไปรับงานนึงเกี่ยวกับการจัดการ Stock สินค้าซึ่งจาก Scale งานเนี่ยน่าจะใช้เวลาพัฒนาประมาณ 2 อาทิตย์แต่ลูกค้าแบบว่าเร่งมากบอกน้องพี่ขอ 7 วันได้ไหม!!
แม่เจ้าาาา รีบไปไหนเนี่ยพ่อคู๊ณณ แต่ถือเป็นโชคดีที่ก่อนหน้าที่ทำงานของผมได้ให้ผมทำ research เกี่ยวกับ node.js framework ตัวนึงชื่อว่า loopback ซึ่งหลังจากได้ลองใช้ขอบอกเลยว่ามันดีมากเลยอ่ะแกรร แบบว่าของมันต้องใช้อ่ะแกรร ว่าแล้วเราก็มาลองใช้งานกันเลยเถอะ
loopback คือ Node.js framework สำหรับสร้าง REST API อย่างรวดเร็วพร้อมเครื่องมือสำหรับสร้าง Model พร้อม validation และอื่นๆ อีกมากมายอย่างครบวงจรเรียกได้ว่าช่วยประหยัดเวลาในการพัฒนาเป็นอย่างมาก โดย ขั้นตอนการใช้ loopback เบื้องต้นมีดังนี้
Setup
สำหรับเริ่มใช้งานก็แบบชิลๆ เปิด terminal ขึ้นมา และพิมพ์คำสั่งดังนี้
npm install -g loopback-cli lb
เมื่อพิมพ์คำสั่งตามนี้จะปรากฏหน้าต่างให้ setup ข้อมูล api ดังนี้
What's the name of your application? hello-loopback (ชื่อของ api) Enter name of the directory to contain the project: hello-loopback (ไฟล์ต่างๆไว้ในโฟรเดอร์ชื่ออะไรถ้าไม่ใส่จะใส่ในไดเร็กทอรี่เดียวกับชื่อ api) Which version of LoopBack would you like to use? เวอร์ชันของ loopback ในที่นี้เลือกเวอร์ชัน 3.x What kind of application do you have in mind? เลือกค่าพื้นฐานของ api ในที่นี้เลือก empty-server
เมื่อใส่รายละเอียดต่างๆ เสร็จแล้ว loopback จะทำสร้างไฟล์ต่างๆ ตามที่เรา setup ไว้เป็นอันเสร็จขั้นตอนแรก
Create Model
เมื่อเรา setup เสร็จแล้วเราก็จะมาสร้าง model แรกกันโดยมีขั้นตอนดังนี้
cd hello-loopback lb model
เมื่อเราพิมพ์คำสั่ง lb model บรรทัดแรกจะขึ้นตัวแดงๆ มาไม่ต้องตกใจบรรทัดต่อมามันจะถามว่า
Enter the model name: blog (ให้เราใส่ชื่อ model ของเรา) Select model's base class: PersistedModel (เลือกประเภทของ model ที่เราจะสร้าง) Expose blog via the REST API? Y (model นี้เป็น REST api หรือเปล่า) Custom plural form: /blog (path ของ model นี้) Common model or server only? common (model นี้จะเอาไว้ที่ไหนในไดเรคทอรี่ server หรือ common)
เมื่อ setup model เสร็จมันก็จะให้เราใส่ property ของ model โดยมีรายละเอียดดังนี้
Property name: name (ชื่อของ property) Property type: string (ประเภทของ property) Required? Y (จำเป็นต้องใส่หรือไม่) Default value[leave blank for none]: (ค่า default ของ property นี้)
เมื่อเราใส่ property เสร็จมันก็จะวนถามใหม่เรื่อยๆ ให้เราใส่เรื่อยๆ จนกว่าจะพอใจเมื่อพอใจแล้วตรง Property name: ให้เว้นว่างไว้มันก็จะออกจากการสร้าง model
เมื่อเราเข้าไปดูในไดเรคทอรี่ common/models ก็จะเห็นไฟล์ชื่อ model ของเรา 2 ไฟล์คือ .js (จะอธิบายต่อไป) และ .json เก็บข้อมูลต่างๆ ของ model เรา
Connect database
เมื่อเราสร้าง model เสร็จแล้วสิ่งที่เราต้องทำต่อมาคือเชื่อมต่อกับฐานข้อมูลซึ่งสามารถทำได้โดยพิมพ์คำสั่ง
lb datasource
หลังจากนั้นมันจะขึ้นคำถามดังนี้
Enter the datasource name: mysql (ให้ใส่ชื่อ datasource อะไรก็ได้) Select the connector for mysql: MySQL (ให้เลือกฐานข้อมูลในที่นี้ใช้ MySQL) Connection String url to override other settings (eg: mysql://user:pass@host/db): mysql://root@127.0.0.1/test (ใส่รายละเอียดการเชื่อมต่อไม่ต้องใส่ก็ได้) host: 127.0.0.1 (ใส่ host ของฐานข้อมูล) port: 3306 (ใส่ port สำหรับเชื่อมต่อฐานข้อมูล) user: root (ใส่ username) password: (ใส่ password) database: test (ใส่ฐานข้อมูลที่ต้องเชื่อมต่อ) Install loopback-connector-mysql@^2.2: Y (ต้องการติดตั้ง loopback-connector-mysql หรือไม่)
หลังจากนั้นไปที่ไฟล์ server/model-config.js แก้ตรง
...
datasource: null
...
เป็น
...
datasource: ‘mysql’ (ชื่อของ datasource ที่เราสร้างขึ้น)
...
เพียงเท่านี้ก็เสร็จเรียบร้อยในขั้นตอนการเชื่อมต่อกับฐานข้อมูลแล้วต่อไปเราก็จะมาสร้างตารางจาก model ของเรากัน
Automigrate
เมื่อเรามี model แล้ว เชื่อมต่อฐานข้อมูลแล้ว ต่อมาเราก็จะทำการสร้างตารางสำหรับ model ของเรากันโดยเปิด editor ขึ้นมาแล้วสร้างไฟล์ชื่ออะไรก็ได้ใส่ไว้ในไดเรคทอรี่ server/boot โดยใส่ code ดังนี้
module.exports = (app) => {
app.dataSources.mysql.automigrate('blog', (err) => {
if (err) throw err;
app.models.blog.create([{
name: 'test1',
author: 'mike',
date: Date()
}, {
name: 'test2',
author: 'mike',
date: Date()
}, {
name: 'test3',
author: 'mike',
date: Date()
}, ], (err, blog) => {
if (err) throw err;
console.log('Models created: \n', blog);
});
});
};
code ด้านบนอธิบายได้ดังนี้
app.dataSources.mysql.automigrate('blog', (err) => {
...
});
เป็นฟังชันสำหรับ migrate ฐานข้อมูลของ loopback โดยส่ง parameter เข้าไปสองตัวคือ model ที่ต้องการ migrate และ callback
app.models.blog.create([{
name: 'test1',
author: 'mike',
date: Date()
},
...
]);
คือการเพิ่มข้อมูลใส่ในตารางที่เราทำการ migrate ** มีข้อควรระวังคือหากในตารางนั้นมีข้อมูลอยู่แล้วจะถูกเขียนทับ **
...
(err, blog) => {
if (err) throw err;
console.log('Models created: \n', blog);
}
...
คือการ handle callback เมื่อทำการ migrate สำเร็จ หลังจากนั้นเมื่อเราเตรียมทุกอย่างพร้อมเราจึงเริ่มทำรัน REST api ของเราโดยพิมพ์คำสั่ง
node .
เมื่อเข้าไปดูในฐานข้อมูลก็จะพบตารางชื่อตาม model ของเราโดยที่มีข้อมูลตามที่เรา insert เข้าไปดังภาพ
ทดลองใช้ API
หลังจากที่เรารัน REST api แล้วให้ลองเปิด browser เข้าไปที่ path 127.0.0.1:3000/explorer จะพบหน้าตาสำหรับทดลอง api ดังภาพ
หากเราต้องเพิ่มข้อมูลเข้าสู่ตารางให้เลือกที่ post ใส่ข้อมูลลงไป และกดที่ try out ดังภาพ
หลังจากนั้นเมื่อเราเข้าไปดูที่ฐานข้อมูลก็จะเห็นข้อมูลที่เราเพิ่มไปเมื่อกี้เข้ามา
หรือหากลองเปิด Browser แล้วเข้าไปที่ http://localhost:3000/api/blog ก็จะเห็นข้อมูลในฐานข้อมูลเราดังภาพเพียงแค่นี้เราก็สร้าง RESTful API สำหรับ CRUD เสร็จแล้วนะครับต่อไปเราจะมาทำ Custom API กัน
Custom API
เพราะในชีวิตจริง API เราของไม่ได้มีแต่ CRUD ต้องฟังชันการทำงานอื่นๆ ซึ่งใน loopback เนี่ยเราสามารถทำ API เอกได้ง่ายๆดังนี้เปิดไฟล์ Model ของเราขึ้นมาซึ่งไฟล์ Model ของเราจะอยู่ที่ common/models/ชื่อโมเดล.js ซึ่งพอเราเปิดขึ้นมาก็จะเป็นไฟล์ไม่ได้ทำๆ (ไฟล์เปล่าๆ) ที่มีข้อมูลหล่อมแหล่มดังนี้
'use strict';
module.exports = function(Blog) {
};
ให้เราสอดใส่ Code เข้าไปดังนี้
module.exports = function(Blog) {
Blog.hello = function(msg, callback){
callback(null, "Hello "+msg)
}
Blog.remoteMethod(
'hello', {
http: {
path: '/hello',
verb: 'get'
},
accepts: {
arg: 'msg',
type: 'string'
},
returns: {
arg: 'word',
type: 'string'
}
}
);
};
Code ข้างบนมีการทำงานคือเมื่อมีคน route ผ่าน method get มาที่ http://localhost:3000/api/blog/hello พร้อม parameter ชื่อ msg ก็จะตอบกลับดังรูปตัวอย่าง
โดย Code ข้างบนมีการทำงานดังนี้
module.exports = function(Blog) {
...
};
export module ของเราส่วน Parameter Blog ที่เข้ามาก็คือ model ของเราพร้อมฟังก์ชันเสริมต่างๆ นาๆที่ loopback เพิ่มมาให้
Blog.hello = function(msg, callback){
callback(null, msg)
}
เพิ่มฟังชันชื่อ hello เข้าไปใน model Blog โดยที่ parameter ที่ส่งเข้าไปตัวแรก msg คือค่าที่รับมาจาก request และ callback นี่ loopback ส่งเข้ามาให้เราสำหรับส่งข้อมูลกลับไปเมื่อเราทำงานเสร็จแล้ว จะสังเกตุเห็นว่าใน loopback รับ parameter 2 ตัว ตัวแรกที่เป็น null คือerr ในกรณีที่มี err ตัวที่สองคือค่าที่เราจะ response ออกไป
Blog.remoteMethod(
'hello', {
http: {
path: '/hello',
verb: 'get'
},
accepts: {
arg: 'msg',
type: 'string'
},
returns: {
arg: 'word',
type: 'string'
}
}
);
คือการตั้งค่า Custom API ของเรา
'hello', {
...
}
คือบอกว่าตั้งค่าของฟังก์ชันไหน
...
http: {
path: '/hello',
verb: 'get'
},
...
คือการเซ็ทพาท และ method ที่เข้ามา
...
accepts: {
arg: 'msg',
type: 'string'
},
...
คือการเซ็ท parameter ที่จะเข้ามา arg คือชื่อ type คือประเภท
...
returns: {
arg: 'word',
type: 'string'
}
...
คือการเซ็ทข้อมูล response ที่จะออกไปก็เหมือนเดิมครับ arg คือชื่อ และ type คือประเภท
Conclusion
เป็นอันเสร็จเรียบร้อยแล้วนะครับสำหรับการใช้ loopback สร้าง RESTful API เบื้องต้นในตอนต่อไป (ถ้าไม่ลืม) จะมาสอนใช้งาน loopback ร่วมกับ Angular 2 กันนะจ๊ะจุ๊ปปาก <3 สามารถดูตัวอย่าง source code ได้ ที่นี่ นะจ๊ะ