GraphQL ด้วย Graph Node บน JIB Chain

ผมไม่ได้เข้ามา blog นานพอสมควร เนื่องด้วยภาระกิจต่าง ๆ (ด้าน Blockchain นี่แหละครับ)

เดี๋ยวผมขอสรุป GraphQL กันหน่อยคืออะไร ถ้าสรุปสั้นๆ ก็เป็น A query language for your API ปกติเวลาเราทำ RESTFul API เราต้องไปดึงข้อมูลจาก database มาให้บริการ ไม่ว่าจะเป็น RMDB หรือ Documents DB แต่สุดท้ายตอนที่เราต้องส่งกลับ เราต้อง define structure กลับอยู่ดี ซึ่งตอน define structure นี้ ก็จะแล้วแต่ว่าฝั่งผู้เรียกต้องการใช้ข้อมูลอะไรบ้าง เราก็ส่งกลับไปให้ ซึ่งก็เป็นท่าปกติครับ

แต่ถ้าผู้ขอข้อมูลคนอื่น ต้องการข้อมูลบางอย่างเพิ่ม ฝั่งที่ดูและ API ก็จะมาปรับ Code โดยการเพิ่ม Data Fields ที่ผู้ข้อต้องการกลับไปให้แทนที่จะสร้างใหม่ เพราะเห็นว่าข้อมูลบางอย่างสามารถใช้ร่วมกันได้ ผู้ขอก็จะใช้งานได้ ซึ่งปัญหาเกิดขึ้นตรงนี้ครับ คือผู้ขอคนแรกๆ หรือคนก่อนหน้า เมื่อเรียก API ก็จะได้ข้อมูลที่ตัวเองไม่ต้องการใช้กลับไปด้วยครับ GraphQL มาช่วยแก้ปัญหาตรงนี้ครับ คือผู้ขอข้อมูลต้องการอะไรก็ส่งคำขอพร้อมแนบ Structure query ที่ตัวเองต้องการมาเลย ทำให้ระบบยืดหยุ่นมากครับ

เอาล่ะมาเข้าเรื่อง GraphQL บน JIB Chain ครับ (ผมติ้งต่างว่าผู้อ่านเข้าใช้เรื่องของ Blockchain มาพอสมควรนะครับ) สำหรับคนที่ทำ DApp บน Blockchain สาย EVM Compatible จะพอทราบกันดีอยู่แล้วว่า การ Query ข้อมูลบน Blockchain เป็นอะไรที่ทั้งซับซ้อนและช้าครับ The Graph จึงผุดโปรเจค Graph Node ขึ้นมาเพื่อทำการ Sync and Index ข้อมูลจาก Blockchain ออกมาไว้ให้ที่ PostgreSQL และเพิ่ม GraphQL library เข้าไปเผื่อให้ผู้ใช้สามารถใช้ได้ง่ายขึ้นผ่านหน้า WebUI เท่าที่ผมได้ทราบหากต้องการใช้ GraphQL ของ Chain สามารถใช้ได้ 2 วิธีดังนี้ครับ

  1. ผ่านบริการของ The Graph เอง ลองเข้าไปเล่นดูได้ที่ https://thegraph.com/explorer ครับ ข้อดีของที่นี่คือใช้บริการได้เลย สามารถเอา Subgraph ไป Deploy ได้ แต่ข้อเสียคือรองรับเฉพาะ Chain ใหญ่ ๆ มีชื่อเสียง ครับ หากเราทำ DApp สำหรับ Chain ที่ยังไม่มีชื่อเสียง วิธีการนี้จะใช้ไม่ได้
  2. ติดตั้ง Graph Node เอง ซึ่งขึ้นตอนการติดตั้งก็ไม่ยากมากนะครับ ลองไปดูตามลิงค์นี้ได้ครับ https://github.com/graphprotocol/graph-node (ผมขออนุญาตไม่ลงรายละเอียดนะครับ) วิธีการนี้เราจะ Sync and Index ข้อมูลจาก Chain ใดๆ ก็ได้ที่ทราบ RPC ครับ แต่วิธีการนี้เราก็ต้องเตรียมเครื่อง Server ไว้ติดตั้งและ sync data ครับ

แต่สำหรับคนที่สนในพัฒนา DApp บน JIB Chain ตอนนี้ทาง Chain มีบริการ Graph Node แบบ Official แล้วครับ เบื้องต้นเราสามารถใช้งานได้เลย (เข้าใจว่าจะสามารถ Deploy Subgraph ได้ด้วย แต่ผมยังไม่ได้ลองนะครับ)

GraphQL ของทาง JIB Chain เบื้องต้นสามารถลองเข้าไปใช้งานได้ที่ https://graph.jibchain.net/subgraphs/name/jbc/all/graphql

ในครั้งแรกก็จะเจอหน้าจอประมาณนี้ครับ

ให้ลองคลิกที่ Tab Explorer ลองดูครับ

ก็จะเห็น Query ต่างๆ ของ Subgraph นี้เตรียมไว้ให้ ว่าเราสามารถ Query ข้อมูลอะไรได้บ้าง ซึ่ง Query เองก็จะแตกต่างกันไปตามแต่ละ Subgraph ที่ได้ Deploy ขึ้นไปเพื่อให้ใช้งานครับ

จาก Query ด้านบนผมจะลองค้นหาดูว่ามี NFT Contracts อยู่เท่าไรบน JIB Chain ผมจะสามารถหาได้ง่ายๆ โดยการเลือกไปที่ Query ที่ชื่อว่า erc721Contracts ตัว UI จะทำการแปลงความต้องการของเรามาให้เป็น Query ในรูปแบบของ GraphQL ดังนี้ครับ

จากนั้นลองคลิกปุ่ม RUN ด้านบนดูครับ เราก็จะเห็นผลลัพธ์ของ Query ของเรา ซึ่งจากที่แสดงนี้เราจะเห็นรายการของ NTF Contract ทั้งหมดบน JIB Chain ครับ และการ Query จนได้ผลลัพธ์นั้นใช้เวลาน้อยมากครับ เร็วจัดเลยครับ

ผมจะลองหาต่อว่า แต่ละ NFT Contract มี Name และ Symbol อะไรผมก็เพียงแต่ทำตาม Step ดังนี้วนไปครับ

หรือถ้าพอเข้าใจโครงสร้างแล้วเราก็สามารถพิมพ์บน Query Edtitor ได้เลยครับ มี intellisense ให้ด้วยสบายกันไป

ผมจะลองหาต่อดูว่ามี NFT JIBLOOT (0x25c06d2b04bdd7e8cf07ce41c77a68b011b320cc) ตอนนี้ Mint ออกมาแล้วเท่าไรและมีใครถืออยู่บ้างก็เขียน Query ออกมาได้แบบนี้ครับ

และผมต้องการหาต่อไปไว้ว่ากระเป๋าที่ Mint JIBLOOT ได้ TokenID ที่ 1 (0x93743a270b02dfb28f0d4b81f54a2ab565ac124b) ถือ NFT อะไรบ้างผมก็สามารถเขียน Query ออกมาแบบนี้ครับ

และผมอยากรู้ต่อไปว่ากระเป๋าใบนี้ถือ NFT รายการสุดท้ายที่มี TokenID : 2188 คืออะไร ผมก็หาต่อไปอีก โดยเขียน Query ออกมาแบบนี้ครับ คือเอา Contract Address ไปหาต่อนั้นเองครับ เราก็ทราบว่าคือ NFT อะไรครับ ดั้งนี้ครับ

เบื้องต้นก็จะประมาณนี้ครับ ขอให้สนุกการค้นหาข้อมูลบน Chain นะครับ ไว้เผื่อมีเวลาผมจะมาพาเขียนเพื่อดึงมาใช้ในงานใน Application ต่อไปครับ ขอบคุณที่อ่านมาจนถึงตรงนี้ครับ

Review : Math for working programmer course

ผมจดจ้องที่จะลงเรียนคอร์สนี้มานานมากล่ะครับ ทั้งจากการติดตามพี่เดฟทาง facebook เอง หรืออ่านรีวิวจากคนอื่นๆ ที่ไปอบรมมา ซึ่งแต่ละคนที่ไปคอร์สนี้มา ผมว่าเป็น DEV ระดับแถวหน้า ของบ้านเราทั้งนั้น แน่นอนว่าคุณภาพคงไม่ต้องพูดถึง แต่กะนั้นก็มีสิ่งหนึ่งที่มันฉุดผมไว้ทุกครั้ง คือคำว่า Math เนื่องจากมันเป็นยาขมของผมมาตลอดตั้งแต่เรียนล่ะครับ ทำไมเป็นยาขมนะเหรอครับ เพราะตั้งแต่เรียนตอนเด็กๆ เราก็ไม่ค่อยเข้าใจจริง ๆ ยิ่งเมื่อมีการเปรียบเทียบเด็กเก่งต้องเรียนสายวิทย์-คณิต ซึ่งหลายคนก็คำนวนเร็วอย่างกับแสงแล้วด้วย ทำให้คนที่คำนวนได้ช้า ยิ่งรู้สึกด้อยเข้าไปใหญ่ และมันก็ชวนให้เราไม่อยากทำมันด้วยเพราะ ทำอย่างไรก็ไม่ได้เท่าคนเก่งๆ เขา

แต่เอาเถอะเราต้องเอาชนะใจตัวเองให้ได้ซักวันผมตั้งใจอย่างนั้น จนมาเดือนที่แล้วพี่เดฟโพสต์ว่าจะมาจัดที่ขอนแก่น และน้องป้องก็รีบจัดกลุ่มเพื่อนๆ เพื่ออบรม แน่นอนว่าผมตอบรับทันที ผมไม่ลังเล ละครับ (แต่ก็แอบหวั่นกับยาขมนี้อยู่ แต่เอาน่าจากรีวิวคนอื่น บอกนอนให้เต็มอิ่มก็พอล่ะ แต่ผมก็แอบไปทวน Discrete Math For Programming จากคอร์สของ BorntoDev ที่ซื้อไว้นานมากแล้ว) เพราะโอกาสมาถึงบ้านเราขนาดนี้ สิ่งที่ผมตั้งใจที่สุดที่อยากรู้คือ “ผมไม่รู้อะไรที่ผมรู้”

พอถึงวันไปสายนิดหน่อยครับ ปัญหาด้านการจราจรเพราะผมต้องขับรถมาราว 30 กิโลเมตร
เอาละรีวิวซักที

  • Day 1
    • เริ่มต้นจากการเริ่มทำความเข้าใจวิธีการคิดที่เราได้เรียนรู้มาและก็มันอยู่ทุกวันนั้นคือ Compute และพี่เดฟก็พามันนำมาเทียบกับ turing machine ทำให้ผมเห็นภาพมากขึ้น ว่าอ่อวิธีที่เราคิดและทำมามันคือแบบนี้นี่เอง (เจอไปหนึ่งดอก)
    • Computer thinking
    • Turing machine
    • Crash Course
    • TDD in C
    • ที่เราเคยเรียนและจำขึ้นใจมาว่า Assembly เป็นภาษาระดับต่ำ C เป็นภาษาระดับสูง (อุ้ยยย)
    • Lambda ผมชอบหัวข้อนี้ อาจจะเป็นเพราะผมเคยเขียน Lambda expressions – C# มาบ้างเลยทำให้ผมไหลลื่นตอนที่พี่เดฟเล่าครับ
    • What is the function
    • Pure function
  • Day 2
    • Funtional programing เน้น? นี่ผมค่อนข้างหลุดไปหลายจังหวะ เนื่องด้วยเราไม่คุ้น Hesskell เลย ทำให้คิดตามไม่ทัน ครับ

ผมได้รู้ว่าคณิตศาสตร์เป็น “ภาษา” ที่ดีครับ เพราะมันสื่อสารได้ตรงมากๆ ไม่เหมือนคำพูดหรือข้อเขียนที่มัน มันอาจจะอยู่ที่การตีความ

สิ่งที่ผมชอบและประทับใจ

  • น่าจะเป็นการนั่งฟังที่ยาวนานที่สุดแบบไม่อยากลุกไปใหนนานที่สุดล่ะครับ นั่งเป็น 10 ชั่วโมงยาวๆ ต่อวัน ทั้งที่จริงผมเพิ่งผ่าตัดใหญ่มาตอนต้นเดือน กุมภา นี่เอง นั่งยังลำบาก
  • พี่เดฟเป็นคนที่เล่าเรื่องทุกเรื่องได้สนุกและน่าสนใจมากครับ (อันนี้อาจจะเพราะเป็นไอดอล ของผมด้วยมั่งครับ)
  • พี่เดฟมีสองโหมดครับ
    • โหมดเริ่มเข้าเรื่อง
    • โหมดเข้าเรื่องแล้วแบบอินสุด หน้าตาจะดูเด็กกว่าวัยลงทันที 55
  • ได้รับรู้ความรู้สึก การเรียนของเมืองนอก (ผมแอบถามนอกรอบ ว่าต่างประเทศเขาเขียนกันเบอร์นี้ไหมครับ พี่เดฟก็ว่าเรียนกันขนาดนี้แหละ)
  • ผมเห็นพี่เดฟเขียนสมการต่างๆ บนกระดานแล้วมันเทห์ มันทำให้เราอยากรู้ไปให้ถึงที่มาที่ไป ผมเลยได้หนังสือเล่มนี้ “ภาษาจักรวาล” มาอ่าน สนุกดีนะครับ

อยากฝากทุกคนถ้ามีโอกาส ไปเรียนคอร์สนี้เถอะครับ แค่ได้ไปฟัง ได้รู้จักพี่เดฟก็คุ้มค่ามากแล้วครับ

แต่ที่ผมคุ้มที่สุดคือการได้มีโอกาส นั่งทานข้าวและดื่มเบียร์กัน ในช่วงเย็นของวันที่สองครับ
ได้แลกเปลี่ยนอะไรหลายๆ อย่างมาก ทั้งเรื่องครอบครัว เรื่อง Code เรื่องการศึกษา แวดวงการศึกษาใน ม. เนื่องจากมีหลายคนในวงสนทนา ก็ลาออกจากการทำงานใน มหาวิทยาลัยมา จึงคุยกันได้ออกรสออกชาติ มากจนร้านมาเตือนว่าถึงเวลาปิดร้าน 555

สุดท้ายพี่เดฟแนะนำให้ไปทบทวนคณิตศาสตร์ใหม่ทั้งหมด แน่นอนตามนั้นครับ เป็นจังหวะที่ดีมากๆ ที่ลูกสาวเริ่มเข้าเรียน จะได้ทั้งทบทวนและสอนลูกไปด้วยในตัวครับ

คณิตศาสตร์ ป.1 – ม.6

จากความตั้งใจที่ผมอยากรู้ว่า “ผมไม่รู้อะไรที่ผมรู้” เอาแค่เรื่องเล็กๆ ก็อย่าง Divide-and-conquer algorithm ที่เราใช้มันแทบตลอดเวลาครับ แต่คำถามที่ผมอยากรู้หลังจากเรียน มันเปลี่ยนไปครับ กลายเป็นว่า “การเรียนรู้อะไร เราต้องเริ่มรู้จากต้นทางที่มันถูกต้องเสียก่อน” ผมอาจจะใส่คำได้ไม่ลึกซึ้งมากพอ ผมขอยกคำจากพระสูตรที่ผมฟังบ่อยๆ คือ คิริมานนทสูตร ย่อหน้า “ครูที่ดี” แล้วกันครับ

ดูกรอานนท์ บุคคลผู้ไม่รู้พระนิพพานไม่ควรเป็นครู สั่งสอนท่านผู้อื่นในทางพระนิพพานเลย ต่างว่าจะสั่งสอนเขา จะสั่งสอนว่ากระไรเพราะตัวไม่รู้ เปรียบเหมือนบุคคลไม่เคย เป็นช่างเขียนหรือช่างต่างๆมาก่อน แล้วและอยากเป็น ครูสั่งสอนเขา จะบอกแก่เขาว่ากระไร เพราะตัวเองก็ไม่รู้ ไม่เข้าใจจะเอาอะไรไปบอกไปสอนเขา จะเอาแต่คำพูด เป็นครูทำตัวอย่างให้เขาเห็นเช่นนั้นไม่ได้ จะให้เขาเล่าเรียน อย่างไร เพราะไม่มีตัวอย่างให้เขาเห็นด้วยตาให้รู้ด้วยใจ เขาจะทำตามอย่างไรได้ ตัวผู้เป็นครูนั้นแลต้องทำก่อน ถ้าทำไม่ได้ก็ไม่ควรเป็นครูสอนเขา ถ้าขืนเป็นครูก็จะพาเขา หลงโลกหลงทาง เป็นบาปเป็นกรรมแก่ตัวนักหนาทีเดียว พระพุทธเจ้าตรัสแก่ข้าฯ อานนท์ดังนี้แล ตทนนฺตรํ ลำดับนั้น พระพุทธเจ้าตรัสเทศนา ต่อไปอีกว่า อานนฺท

Benchmark nanoexpress framework

วันนี้ว่างๆ ปกติผมนั่งติดตาม Web Framework benchmark จากที่นี่ https://web-frameworks-benchmark.netlify.app/result (เป็นที่หลักที่ผมไว้เทียบครับ)

ก่อนหน้านี้เล็ง ๆ nanoexpress ไว้บ้างว่าจะเอามาขึ้น project ก็ไม่ได้ขึ้นซักที วันนี้ว่าจะ PoC api เล็ก ๆ ซักตัวเลยลองมานั่ง Load Test ดูซักหน่อย โค้ดไม่มีอะไรมากเพราะผมต้องการดูว่ามันจะรับได้เยอะเท่าไร

import nanoexpress from ‘nanoexpress’;

const app = nanoexpress();

app.get(‘/’, (req, res) => {
return res.send({ status: ‘ok’ });
});

app.listen(3000);

ทดสอบ start ง่าย ๆ ยังไม่มี cluster

ตัวเลขออกมาดีเลยครับ

เอ้าลองแบบ Cluster ด้วย PM2 ดูหน่อย

เห็น CPU วิ่งเต็มๆ แล้วมันกระชุมกระชวยดีจริงๆ

ผลออกมาเเป็นที่หน้าพอใจ เดี่ยวลองขึ้นโปรเจ็คง่าย ๆ ดูซักตัวก่อนละกันครับ ว่าจะมี Hidden อะไรไหม

SwaggerSchema on C# Model

เมื่อเจอโจทย์ว่า มีบาง property ที่เราต้องการให้แสดงเฉพาะตอน GET และก็มีบาง Property ที่เราต้องการให้แสดงตอน POST จะทำอย่างไรได้บ้าง ซึ่ง .NET Core Mini API ก็มีความสะดวกให้เราสามารถใช้ Swagger ได้เลย เพราะเป็น Package ที่ติดมาตั้งแต่การสร้าง Project แล้ว เอาล่ะ ถ้าคุณเจอโจทย์แบบผมจะต้องทำอย่างไรบ้าง

Add package Swashbuckle.AspNetCore.Annotations ซ่ะ

เพิ่ม Attribute annotation เช่น

จากนั้นก็ไปปรับ AddSwaggerGen ที่ Program.cs ประมาณนี้

แค่นี้ก็ใช้ได้แล้วครับ (แต่ผมนั่งหาวิธีอยู่หลายชั่วโมงอยู่เหมือนกันครับ)

ผลลัพธ์ ส่วน GET

ผลลัพธ์ ส่วน POST (id,orderID and slipRef2 ไม่มีล่ะ)

Change Ubuntu 20.04 update source to mirror site in Thailand

Ubuntu 20.04 ออกในโค้ดเนม Focal Fossa โดยสามารถเพิ่ม deb-src ได้ที่ /etc/apt/source.list (แบ็คอัพไว้ก่อนด้วยนะครับ) โดยเพิ่ม code ตามด้านล่างนี้ครับ

deb http://mirrors.kku.ac.th/ubuntu/ focal main restricted universe multiverse
deb http://mirrors.kku.ac.th/ubuntu/ focal-security main restricted universe multiverse
deb http://mirrors.kku.ac.th/ubuntu/ focal-updates main restricted universe multiverse
deb http://mirrors.kku.ac.th/ubuntu/ focal-backports main restricted universe multiverse

จากนั้น ก็ sudo apt update ได้เลยครับเร็วปี้ดๆๆ

Restart WSL2 and Docker Desktop for Windows

หลายครั้งผมมักเจอปัญหาหลังจากเครื่อง Sleep หรือตื่นจากการ Hibernate WSL2 มักจะไม่สามารถงานได้ ผมก็จะคอยมา Start ใหม่โดยใช้คำสั่ง

wsl --shutdown -and wsl

จากนั้นก็ค่อยไปทำการ Restart เจ้า Docker Desktop อีกครั้ง โดยทำเป็น Manual ไป บ่อยครั้งขี้เกียจ เลยลองว่าวิธีการที่จะทำให้ Restart เจ้า WSL แล้ว ให้ Docker restart ตาม เลยได้ Step มาแบบนี้ครับ

  • ทำเป็น Powershell Script ไว้
  • Run script เมื่อต้องการ Restart ทั้ง 2 service

ผมสร้าง powershell script ไว้ทื่ home ผมโดยมี script ดังนี้ครับ

wsl --shutdown -and wsl

$processes = Get-Process "*docker desktop*"
if ($processes.Count -gt 0)
{
    $processes[0].Kill()
    $processes[0].WaitForExit()
}
Start-Process "C:\Program Files\Docker\Docker\Docker Desktop.exe"

จากนั้นเวลาจะใช้งานก็สั่ง

จากนั้นก็รอแปร๊บเดียว ทั้ง WSL2 และ Docker Desktop ก็พร้อมใช้งานแล้วครับ

ผมใช้ Docker ค่อนข้างเยอะ ตั้งแต่ build, pack, ship to deploy เลย ปัญหานี้ทำให้หงุดหงิดอยู่เหมือนกัน เนื่องจากจริงๆ แล้ว docker machine ไม่ตาย แต่ Service บางส่วนใช้งานไม่ได้ เช่น การเชื่อมต่อกับ registry อื่นๆ ที่เกี่ยวข้องทั้ง pull และ push ซึ่งมันจะฟ้องเราเมื่อเราเริ่มกระบวนการ deploy เท่านั้น บางครั้งทำงานสะดุดเหมือนกัน

เพิ่มการ Query object บน JS ได้ดังใจกับสาย Traditional SQL ด้วย AlaSQL

ช่วงนี้มีความจำเป็นต้อง Filters json ค่อนข้างหนักพอสมควร ใช้ filter บน js แล้ว เห็น code ที่ค่อนข้างซับซ้อนหน่อย ซึ่งบังเอิญหลังบ้านก็เก็บด้วย PostgreSQL ซึ่งเป็น Relational Database อยู่แล้ว ดังนั้นในทีม มีความรู้เรื่องของการ ใช้ SQL เป็นอย่างดีอยู่แล้ว

AlaSQL logo

จึงลองนำ JS Library เล็กๆ ตัวหนึ่งมาใช้นั้นคือ AlaSQL – à la SQL ) ซึ่งจากที่ลองใช้แล้ว สามารถช่วยให้การเล่นกับ Data ทำได้สะดวกขึ้นมาก (หรือผมเป็นสาย Traditional SQL ก็ไม่รู้) ตัวอย่างง่ายๆ ที่ได้ลองใช้งานครับ

ตัวอย่าง Group By

const res = await axios.get('/json/products.json');
var data = alasql('SELECT country, count(country) AS total,false AS isChecked FROM ? GROUP BY country', [res.data]);

ตัวอย่าง In codition

const data = alasql(`SELECT * FROM ? where country in (${inCountrys})`, [this.products]);

ตัวอย่าง Like condition

const data = alasql(`SELECT * FROM ? where name like '%${this.searchText}%'`, [this.productFilter]);

ดูเพิ่มได้จาก https://github.com/agershun/alasql เลยครับ Project active ดีครับ

Open terminal in current dir with shortcut on Ubuntu 20.04

2020-05-12_23-08

ผมใช้ Terminal ค่อนข้างบ่อย และก่อนหน้านี้ใช้ Mac มานาน ติด Terminal Here มาก คือเป็นโปรแกรมเล็ก ๆ ที่อำนวยความสะดวกในการเปิด terminal ที่ Directory ที่กำลังอยู่ พอย้ายมาใช้ ubuntu ก็ดีหน่อยเพราะมี build-in มาให้ด้วย แต่ก็ต้องคลิกขวา แล้วเลือก Open in terminal หรือมีง่ายกว่านั้น คือ ใช้ shortcut shift+f10 และกด e ก็เปิดได้เช่นกัน แต่ก็ต้องกดหลายปุ่มอยู่ดี ก็เลยหาวิธี config ง่าย และผูกไว้กับ f4 ปุ่มเดียวพอ มีวิธีการเซ็ตง่าย ๆ ดังนี้ครับ

  1. สร้างไฟล์ชื่อTerminal ภายได้ Directory ~/.local/share/nautilus/scripts โดยใส่ script ดังนี้ครับ
    #!/bin/sh
    gnome-terminal
    
  2. เปลี่ยนโหมดของไฟล์ที่เราสร้างเมื่อกี้ให้สามารถ execute ได้ จากนั้นทำการปิด instance ของ  nautilus
    chmod +x Terminal
    nautilus -q
    
  3. สร้างหรือแก้ไขไฟล์ ~/.config/nautilus/scripts-accels โดยเพิ่มเนื้อหาดังนี้ครับ
    F4 Terminal
    
  4. Test it! Open Nautilus, right click, and choose Scripts > Terminal. Or, use the keyboard shortcut that you’ve just configured 🙂 ทดสอบโดยคลิกขวาที่ Directory ที่ต้องการเปิด Terminal โดยเลือกไปที่ Scripts > Terminal หากสามารถเปิดได้ ก็ลองกดปุ่ม f4 ดูนะครับ หากไม่มีอะไรผิดพลาด terminal ควรจะแสดงออกมา

ปล. บันทึกไว้หน่อยเพื่อตอนติดตั้ง ubuntu จะได้กลับมาทำง่าย ๆ

ที่มา : https://stackoverflow.com/questions/48840027/ubuntu-open-terminal-in-current-folder-with-shortcut