[৮.৬] ভ্যালিডেশন (Validation)
Create এবং Update অপারেশনের ক্ষেত্রে, যে ডাটা আমরা ডাটাবেস টেবিলে রাখব তাও নুন্যতম কোয়ালিটি মেইনটেইন করা আবশ্যক। নইলে যেসকল সমস্যার সম্মুখীন আমরা হতে পারি –
- কোনো এক বা একাধিক ফিল্ডের ভ্যালু খালি অবস্থায় টেবিলে এন্ট্রি হয়ে যেতে পারে।
- যেকোনো ফিল্ডের ভ্যালুর লিমিট অতিক্রম হয়ে যেতে পারে।
- যে ফিল্ড যেধরণের ডাটা টাইপ গ্রহণ করে থাকে তার বাইরের অন্য কোনো ডাটা টাইপের ভ্যালু ভুলে ইনপুট হয়ে যেতে পারে ইত্যাদি ।
এ ধরণের অনাকাঙ্ক্ষিত পরিস্থিতি এড়ানোর জন্য আমরা নতুন ডাটা Create বা Update করার পূর্বে তা একটা ভ্যালিডেশন চেকের মধ্য দিয়ে পাঠাবো এবং নিয়মের বাইরের কোন ডাটা ইনপুট হয়ে থাকলে তা জানিয়ে দেবো । যে নিয়মগুলো আমরা নিশ্চিত করব :
- BookName এবং Author ফিল্ড খালি থাকা যাবে না, Publication এর থাকা বা না থাকায় কিছু হবে না।
- BookName এর ক্যারেক্টার লিমিট থাকবে 1 থেকে 50 এর মধ্যে ।
- Author এর ক্যারেক্টার লিমিট থাকবে 5 থেকে 50 এর মধ্যে ।
এবারে পালা ইমপ্লিমেন্টেশনের। ভ্যালিডেশনের জন্য আমরা “ozzo-validation” প্যাকেজটি ব্যবহার করব। প্যাকেজটি নামানোর জন্য টার্মিনালে নিচের কমান্ডটি রান করি –
go get github.com/Go-ozzo/ozzo-validation
- ভ্যালিডেশনের কাজ কোথায় হবে?
আমাদের ভ্যালিডেশনের পুরো কোডটি থাকবে types/structures.go তে। কেননা, ozzo-validation এর Validate() ফাংশনটা একটা Struct এর মেথড হিসেবে যোগ করে দিতে হয়। এক্ষেত্রে আমরা echo.Context থেকে রিকোয়েস্ট ডাটা Bind করেছি প্রত্যেকবার types/structures.go এর BookRequest নামের Struct এর ইন্সট্যান্সে। সুতরাং BookRequest এর ভ্যালিডেশনের জন্য এর Validate() ফাংশনটি এর সাথেই রাখব।
- types/structures.go এ –
- প্রথমেই ভ্যালিডেশনের কোডটি দেখে নেই, তাহলে বুঝতে সুবিধা হবে কি করেছি আমরা –
types/structures.go
func (book BookRequest) Validate() error {
return validation.ValidateStruct(&book,
validation.Field(&book.BookName,
validation.Required.Error("Book name cannot be empty"),
validation.Length(1, 50)),
validation.Field(&book.Author,
validation.Required.Error("Author name cannot be empty"),
validation.Length(5, 50)),
)
}
2. Validate() ফাংশন শুধু এররের খোঁজে থাকে এবং নিয়মের বাইরে গেলেই তা এরর হিসেবে রিটার্ন করে থাকে।
3. যে ফিল্ডে আমরা নিয়ম সেট করতে চাই, সেটা validation.Field() মেথডে নিয়ে প্রয়োজনমত এক এক করে নিয়ম সেট করতে পারি।
4. এখানে আমরা BookName ও Author ফিল্ডের জন্য, ইনপুট না দিলে এবং রেঞ্জের বাইরে ডাটা ইনপুট দিলে এরর রিটার্ন করার ব্যবস্থা করেছি।
- controllers/book.go এ –
5. ভ্যালিডেশনের ফাংশন লেখা শেষে এখন আমাদের কাজ হচ্ছে controllers/book.go তে ফেরত যেয়ে CreateBook() ও UpdateBook() ফাংশনে এর প্রয়োগ করা।
6. CreateBook() এর ক্ষেত্রে রিকোয়েস্ট থেকে ইনপুট ডাটা types.BookRequest এর একটি ইন্সট্যান্সে Bind করার পর তা Validate() মেথড রান করে দেখব এবং নিয়মের বাইরে গেলে সেটা এরর হিসেবে রেসপন্সে পাঠাবো –
reqBook := &types.BookRequest{}
if err := e.Bind(reqBook); err != nil {
return e.JSON(http.StatusBadRequest, consts.InvalidInput)
}
if err := reqBook.Validate(); err != nil {
return e.JSON(http.StatusBadRequest, err.Error())
}
7. তাহলে CreateBook() এর সর্বশেষ রূপ দাঁড়াচ্ছে –
controllers/book.go
func CreateBook(e echo.Context) error {
reqBook := &types.BookRequest{}
if err := e.Bind(reqBook); err != nil {
return e.JSON(http.StatusBadRequest, "Invalid Data")
}
if err := reqBook.Validate(); err != nil {
return e.JSON(http.StatusBadRequest, err.Error())
}
book := &models.Book{
BookName: reqBook.BookName,
Author: reqBook.Author,
Publication: reqBook.Publication,
}
if err := BookService.CreateBook(book); err != nil {
return e.JSON(http.StatusInternalServerError, err.Error())
}
return e.JSON(http.StatusCreated, "Book was created successfully")
}
8. UpdateBook() এর ক্ষেত্রেও রিকোয়েস্ট থেকে ইনপুট ডাটা types.BookRequest এর একটি ইন্সট্যান্সে Bind করার পর তা Validate() মেথড রান করে দেখব এবং নিয়মের বাইরে গেলে সেটা এরর হিসেবে রেসপন্সে পাঠাবো –
reqBook := &types.BookRequest{}
if err := e.Bind(reqBook); err != nil {
return e.JSON(http.StatusBadRequest, consts.InvalidInput)
}
if err := reqBook.Validate(); err != nil {
return e.JSON(http.StatusBadRequest, err.Error())
}
9. তাহলে UpdateBook() এর সর্বশেষ রূপ দাঁড়াচ্ছে –
func UpdateBook(e echo.Context) error {
reqBook := &types.BookRequest{}
if err := e.Bind(reqBook); err != nil {
return e.JSON(http.StatusBadRequest, consts.InvalidInput)
}
if err := reqBook.Validate(); err != nil {
return e.JSON(http.StatusBadRequest, err.Error())
}
tempBookID := e.Param("bookID")
bookID, err := strconv.ParseUint(tempBookID, 0, 0)
if err != nil {
return e.JSON(http.StatusBadRequest, consts.InvalidID)
}
existingBook, err := BookService.GetBooks(uint(bookID))
if err != nil {
return e.JSON(http.StatusBadRequest, err.Error())
}
updatedBook := &models.Book{
ID: uint(bookID),
BookName: existingBook[0].BookName,
Author: existingBook[0].Author,
Publication: existingBook[0].Publication,
}
if err := BookService.UpdateBook(updatedBook); err != nil {
return e.JSON(http.StatusInternalServerError, err.Error())
}
return e.JSON(http.StatusCreated, "Book was updated successfully")
}
এরই মধ্য দিয়ে, অতি সহজেই আমরা আমাদের প্রজেক্টে ভ্যালিডেশন যোগ করে ফেললাম…