natty

[grails] WebAlbum: ตอนที่ 2 จบ domain class

In grails on September 22, 2008 at 10:04 am

จาก ตอนที่ 1 เราแค่บอกว่าเราจะทำ domain class อะไรบ้าง แต่ก็เขียนไปแค่อันเดียว blog นี้เราจะเขียน domain class ที่เหลือให้หมดเลย หลักๆ จะอิงจาก tutorial เพราะจะได้เรียนรู้ไปในตัว

ครั้งที่แล้วมี User ไปแล้ว คราวนี้ก็เหลือ Album, Picture, Image

มาที่ Album กันก่อน

class Album implements Comparable {
User user
String caption
String description
SortedSet pictures
Integer picturesCount = 0
Date dateCreated = new Date()
Date lastUpdated = new Date()

static belongsTo = User
static hasMany = [ pictures : Picture ]

static optionals = [ 'description' ]

static constraints = {
caption(size: 1..40, blank: false)
description()
}

int compareTo(obj) {
obj.id.compareTo(id)
}
} 

การ implement interface comparable คือเพื่อจะทำให้ object ภายใน Class Album สามารถ sort ได้ compare ได้ เนื่องจากเป็นลิสต์ของ album

static belongsTo = User
static hasMany = [ pictures : Picture ]

ตัวแปร belongsTo บอกว่า Album มีความสัมพันธ์กับ User แปลง่ายๆ ว่า Album ขึ้นกับ User เป็นความสัมพันธ์อีกด้านหนึ่ง และ Album ก็มีหลาย pictures จากตัวแปร hasMany

int compareTo(obj) {
obj.id.compareTo(id)
}

ด้านบนเป็น method เอาไว้ compare object ด้วยการใช้ id

ต่อมาก็เป็น Picture.groovy

class Picture implements Comparable {</pre>
User user
 Album album
 SortedSet images
 String file
 Integer operation
 String caption
 String description
 String contentType
 Integer width
 Integer height
 Date dateCreated = new Date()
 Date lastUpdated = new Date()
 Boolean confirmDelete

 static belongsTo = [ User, Album ]
 static hasMany = [ images : Image ]

 static optionals = [ 'caption', 'description' ]

 static transients = [ 'file', 'operation', 'confirmDelete' ]

 static constraints = {
 caption(size: 0..40)
 description()
 }

 static mapping = {
 images cascade: 'all-delete-orphan', inverse: true
 description type: 'text'
 user index: 'pictures_user_index', unique: false
 album index: 'pictures_album_index', unique: false
 }

 static final Integer NoOp = 0
 static final Integer RotateClockWise90 = 1
 static final Integer RotateAntiClockWise90 = 2
 static final Integer Rotate180 = 3
 static final Integer Flip = 4
 static final Integer Flop = 5

 int compareTo(obj) {
 obj.id.compareTo(id)
 }
}

ซึ่งหน้าตาก็คล้ายๆ กับ domain class อื่นๆ แต่มีส่วนที่ต่างคือส่วนที่เกี่ยวกับการ mapping และการประกาศ final variable

static mapping = {
images cascade: 'all-delete-orphan', inverse: true
description type: 'text'
user index: 'pictures_user_index', unique: false
album index: 'pictures_album_index', unique: false
} 

ตรงนี้เป็นเรื่องของ GORM เกี่ยวกับ mapping DSL คือตั้งแต่ grails version 1.0 มาแล้วนั้น domain class สามารถถูก map เป็น schema อื่นๆ ได้โดยผ่าน ORM DSL เช่น เราอาจจะเปลี่ยนชื่อ table name ชื่อ column เรา enable caching ให้กับ mapping closure ได้ด้วย

image cascade น่าจะเป็นการกำหนด cascade ให้กับ image ของ picture object นี้ ให้เป็น all-delete-orphan และให้ inverse ได้ มี description ชนิด text มีการทำ index ไปที่ user และ album ที่เกี่ยวกับกับ picture นี้ ([variable] index)

เพิ่งแอบเห็น พี่ชาญวิทย์แปลเรื่อง mapping ไว้ให้แล้ว อ่านง่ายดี ภาษาเฉพาะทางสำหรับ mapping ใน GORM (ตอน 1)

ต่อไปก็เป็น Class Image ไม่ต้องอธิบายอะไรกันมากแล้ว คล้ายๆ กับที่ผ่านมา

class Image implements Comparable {
User user
Picture picture
Integer size
byte[] data
String contentType
Integer width
Integer height
Date dateCreated = new Date()
Date lastUpdated = new Date()

static belongsTo = [ User, Picture ]

static mapping = {
picture index: 'images_index', unique: true
size index: 'images_index', unique: true
data type: 'binary'
}

static constraints = {
data(maxSize: MAX_SIZE)
}

static final Integer MAX_SIZE = 10 * 1024 * 1024

static final Integer Original = 1
static final Integer Large = 2
static final Integer Medium = 3
static final Integer Small = 4

static final Integer[] Widths =  [ 0, 0, 500, 250, 100 ]
static final Integer[] Heights = [ 0, 0, 500, 250, 100 ]

static final String[] Names = [ '', 'Original', 'Large', 'Medium', 'Small' ]

int compareTo(obj) {
size.compareTo(obj.size)
}

String filename() {
Image.filename(picture.id, size)
}

static String filename(long id, int size) {
if (size == Original) {
return "${id}-${Names[size]}.jpg"
}
else {
return "${id}-${Names[size]}.png"
}
}
} 

ผ่านมา 2 ตอนแล้วไม่ได้รันซะที (ฮา) พยายามต่ออีกนิด มา generate controller และ view ให้กับ domain class ของเรากันดีกว่า เราจะใช้คำสั่ง grails generate-all กับ User, Album, Picture ส่วนกับ Image ไม่ต้อง เพราะมันจะเป็นแค่รูปๆ ที่แสดงขึ้นมา

grails generate-all User

หลังจากนั้นไปปรับไฟล์ grails-app/conf/DataSource.groovy นิดหน่อย เพื่อให้เก็บ HSQLDB เป็นไฟล์ใน db/devDB

eenvironments {
	development {
		dataSource {
			dbCreate = "update" // one of 'create', 'create-drop','update'
			url = "jdbc:hsqldb:file:db/devDB"
		}
	}

การเปลี่ยน url เพื่อเข้าใช้งาน อันนี้จะทำหรือไม่ทำก็ได้ หากเราไม่อยากเข้าผ่าน http://localhost:8080/WebAlbum แต่อยากเข้าผ่าน http://localhost:8080/natty อะไรแบบนี้ ก็ให้เพิ่ม web-jetty.xml

<?xml version="1.0"  encoding="ISO-8859-1"?>
<!DOCTYPE Configure PUBLIC "-//Mort Bay Consulting//DTD Configure//EN"
  "http://jetty.mortbay.org/configure.dtd">
<Configure class="org.mortbay.jetty.webapp.WebAppContext">
  <Set name="contextPath">/</Set>
</Configure>

เฮ้อ เรื่องเยอะ กว่าจะได้รัน ซัดเลยจ้ะ grails run-app แล้วลองเข้าไปเยี่ยมเยียนดูซิ เรากำลังได้ application แล้ว

Advertisements

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s

%d bloggers like this: