สาวน้อยน่ารักคนนี้ อายุแค่ 16
แต่ปีน overhang เหมือนเป็นของเล่นๆ
ภาพจากการแข่งขัน bouldering เมื่อวันอาทิตย์ที่ผ่านมา
ผมลองเล่นกีฬานี้ครั้งแรก เมื่อนานมาแล้ว อาจจะ 8-9 ปีมาแล้ว
เริ่มจากไปเที่ยว Railay กระบี่ แหล่งปีนเขาที่ติด 10 อับดับแรกของโลก
ไปทดลองเล่น โดยมีอาจารย์เจ้าถิ่น สาวสวย หุ่นดี ชื่อรำพึง เป็นคนสอนให้
ผมเป็นคนกลัวความสูง
ยิ่งปีนสูงก็ยิ่งเสียว
ยังจำการปีนแบบ multi-pitch ซึ่งเป็นการปีนระยะที่สูงเกินกว่าความยาวเชือก
เลยต้องมีการสลับปลายเชือกกันกลางทาง
เหงื่อนี่ไหลเป็นน้ำเลย กลัวผิด
clip ผิด แกะผิด มันจะล่วงลงมาตายเอาได้
Friday, May 26, 2006
ติดตั้ง Maven-Proxy
วันนี้นั่งติดตั้ง Maven-Proxy
link เอกสารการ config ก็ดัน error 404 อีก
ก็เลยต้องมองหาตัวอย่างจาก testcase ของเขาแทน
สรุปขั้นตอนการติดตั้ง
1. download Maven-Proxy ซึ่งเลือกได้ 2 แบบคือ
เป็น War file กับ Stand-alone application
ผมเลือกใช้แบบ Stand-alone
2. สร้าง configuration file หน้าตาประมาณนี้
Link
3. สั่ง start server ด้วยคำสั่ง
ในฝั่ง client ก็ให้ไป set ใน file
~/.m2/settings.xml
เพิ่มส่วน Mirrors เข้าไป
Note: maven1 กับ maven2 มี repository structure คนละแบบกัน
เวลา config server ก็ต้องเลือก repository ให้ถูก version ด้วย
link เอกสารการ config ก็ดัน error 404 อีก
ก็เลยต้องมองหาตัวอย่างจาก testcase ของเขาแทน
สรุปขั้นตอนการติดตั้ง
1. download Maven-Proxy ซึ่งเลือกได้ 2 แบบคือ
เป็น War file กับ Stand-alone application
ผมเลือกใช้แบบ Stand-alone
2. สร้าง configuration file หน้าตาประมาณนี้
Link
3. สั่ง start server ด้วยคำสั่ง
java -jar maven-proxy-standalone-0.2-app.jar maven-proxy.properties
ในฝั่ง client ก็ให้ไป set ใน file
~/.m2/settings.xml
เพิ่มส่วน Mirrors เข้าไป
<settings>
.
.
<mirrors>
<mirror>
<id>maven-proxy</id>
<name>maven proxy</name>
<url>http://myserver:8888/repository</url>
<mirrorOf>central</mirrorOf>
</mirror>
</mirrors>
.
.
</settings>
Note: maven1 กับ maven2 มี repository structure คนละแบบกัน
เวลา config server ก็ต้องเลือก repository ให้ถูก version ด้วย
Related link from Roti
Thursday, May 25, 2006
Solve Sudoku Puzzle with Python
เคยเขียนเรื่องการ solve Sudoku ด้วย Oz
กับ Solve ด้วย java ไปแล้ว
Peter Norvig ปล่อยบทความว่าด้วยการใช้
Solving Every sudoku Puzzle ออกมา
โดย implement ด้วย python
แค่เริ่มต้น declare ตัวแปรต่างๆ ผมก็ร้องว้าวแล้ว
วิธีการที่ใช้ solve ก็คือ constraint propagation กับ search
จำนวนบรรทัด ใช้ไปแค่ 100 บรรทัด
ผมชอบวิธีที่เขาเขียน code
ติดใจมาจากหนังสือ "Artificial Intelligence Programming" ที่เขาเขียน
กับ Solve ด้วย java ไปแล้ว
Peter Norvig ปล่อยบทความว่าด้วยการใช้
Solving Every sudoku Puzzle ออกมา
โดย implement ด้วย python
แค่เริ่มต้น declare ตัวแปรต่างๆ ผมก็ร้องว้าวแล้ว
rows = 'ABCDEFGHI'
cols = '123456789'
digits = '123456789'
squares = [r+c for r in rows for c in cols]
unitlist = ([[r+c for r in rows] for c in cols] +
[[r+c for c in cols] for r in rows] +
[[rows[r+dr]+cols[c+dc] for dr in (0,1,2) for dc in (0,1,2)]
for r in (0,3,6) for c in (0,3,6)])
units = dict((s, [u for u in unitlist if s in u])
for s in squares)
peers = dict((s, set(s2 for u in units[s] for s2 in u if s2 != s))
for s in squares)
วิธีการที่ใช้ solve ก็คือ constraint propagation กับ search
จำนวนบรรทัด ใช้ไปแค่ 100 บรรทัด
ผมชอบวิธีที่เขาเขียน code
ติดใจมาจากหนังสือ "Artificial Intelligence Programming" ที่เขาเขียน
Related link from Roti
Sunday, May 21, 2006
Hibernate Validator
Feature หนึ่งของ Rails ที่ผมชอบก็คือส่วนของ validation มันเป็นส่วนเดียวกับ Model
ใน Hibernate version 3.x นี้ ก็ได้มี Feature นี้ใส่เข้ามาเหมือนกัน
แต่แยกอยู่ใน package Hibernate Annotations
การ config validation จะใช้ Annotation เข้ามาช่วย
ประเด็นที่น่าสนใจ ก็คือ แล้วเราจะ check validate ตอนไหน
(ตอน submit form, ตอน save)
และด้วยวิธีใด
เอาวิธีแรกสุดก่อน ก็คือทำเป็น constrains ใน Database
กรณีนี้ ถ้าเราใช้ Schema Tool ของ Hibernate ทำการ generate sql
ตัว Schema Tool ก็จะสร้าง constrains ให้เป็นไปตามที่เรากำหนด
เช่นตัวอย่างของเรา มี @NotNull อยู่ ดังนั้น column name นี้ใน database
ก็ต้องเป็น
วิธีถัดมา ก็คือระบุให้ Hibernate Throw Exception
ถ้ามีการพยายาม save Entity นี้
วิธีนี้ทำได้โดย ระบุ ValidateXXEventListener ใน Configuration
เขียน TestCase สำหรับกรณีนี้ได้แบบนี้
วิธีสุดท้าย ก็คือเราสามารถดึงเอาส่วน validate ไปทำที่ส่วน Presentation ก็ได้
โดยใช้ ClassValidator เข้ามาช่วย
ลองดูตัวอย่างของ TestCase กรณีนี้
เราสามารถ override Validate Message ได้โดย
provide file ที่ชื่อ
ตัวอย่าง file
ใน Hibernate version 3.x นี้ ก็ได้มี Feature นี้ใส่เข้ามาเหมือนกัน
แต่แยกอยู่ใน package Hibernate Annotations
การ config validation จะใช้ Annotation เข้ามาช่วย
@Entity
public class Province {
private Long id;
private String name;
@Id
@GeneratedValue(strategy=GenerationType.AUTO)
public Long getId() {
return id;
}
public void setId(Long id) {
this.id = id;
}
@Column
@NotNull
public String getName() {
return name;
}
public void setName(String name) {
this.name = name;
}
}
ประเด็นที่น่าสนใจ ก็คือ แล้วเราจะ check validate ตอนไหน
(ตอน submit form, ตอน save)
และด้วยวิธีใด
เอาวิธีแรกสุดก่อน ก็คือทำเป็น constrains ใน Database
กรณีนี้ ถ้าเราใช้ Schema Tool ของ Hibernate ทำการ generate sql
ตัว Schema Tool ก็จะสร้าง constrains ให้เป็นไปตามที่เรากำหนด
เช่นตัวอย่างของเรา มี @NotNull อยู่ ดังนั้น column name นี้ใน database
ก็ต้องเป็น
not null
ด้วยวิธีถัดมา ก็คือระบุให้ Hibernate Throw Exception
ถ้ามีการพยายาม save Entity นี้
วิธีนี้ทำได้โดย ระบุ ValidateXXEventListener ใน Configuration
<event type="pre-update">
<listener
class="org.hibernate.validator.event.ValidatePreUpdateEventListener" />
</event>
<event type="pre-insert">
<listener
class="org.hibernate.validator.event.ValidatePreInsertEventListener" />
</event>
เขียน TestCase สำหรับกรณีนี้ได้แบบนี้
public void testValidate() throws Exception {
Province p = new Province();
try {
session.save(p);
fail("shold not be here");
} catch (PropertyValueException e) {
}
}
วิธีสุดท้าย ก็คือเราสามารถดึงเอาส่วน validate ไปทำที่ส่วน Presentation ก็ได้
โดยใช้ ClassValidator เข้ามาช่วย
ลองดูตัวอย่างของ TestCase กรณีนี้
public void testAppValidate() {
Province p = new Province();
ClassValidator<Province> pv = new ClassValidator<Province>(Province.class);
try {
pv.assertValid(p);
fail("fail");
} catch (InvalidStateException e) {
InvalidValue[] iv = pv.getInvalidValues(p);
assertEquals(1, iv.length);
assertEquals("name", iv[0].getPropertyName());
}
}
เราสามารถ override Validate Message ได้โดย
provide file ที่ชื่อ
ValidatorMessages.properties
ตัวอย่าง file
validator.notNull=Hey. not null please
Related link from Roti
Rails Memo #2
ครั้งก่อนพูดถึงการตั้งชื่อ Controller, View ไป
คราวนี้ลองมาดูกฎการตั้งชื่อ Model บ้าง
Model จะมาคู่กับ Database Table เสมอ
โดยชื่อ Model ต้องเป็นเอกพจน์ ส่วนชื่อ Table ต้องเป็นพหูพจน์
ชื่อ table ที่ประกบกับ model นี้ ก็ต้องเป็น
ที่น่าสนใจก็คือ Rails ใช้กฎอะไรในการแปลง เอกพจน์ เป็น พหูพจน์
class ที่เกี่ยวข้องในเรื่องนี้ อยู่ใน package ActiveSupport
มีชื่อว่า
ลองดูตัวอย่าง ตารางการแปลงของ Rails ดู
ถ้าอยากรู้ว่าอะไรแปลงเป็นอะไร ก็สามารถใช้
ทีนี้กระโดดไปที่ scaffold บ้าง
เวลาที่เราสั่ง generate scaffold เราใช้คำสั่งต่อไปนี้
แน่นอน modelName ที่ระบุใน scaffold อยู่ในรูปเอกพจน์
แต่ชื่อของ controller ที่ scaffold generate ให้นี้จะอยู่ในรูป พหูพจน์
เช่น
จะได้
เรื่องการใช้เอกพจน์ หรือพหูพจน์นี้ จริงๆพอใช้ไปสักพัก ก็จะเริ่มรู้สึก
เป็นธรรมชาติขึ้น (ฝรั่งคงไม่มีปัญหา เพราะเป็นภาษาเขา)
ซึ่งมันก็สื่อดีเหมือนกัน เช่น
คราวนี้ลองมาดูกฎการตั้งชื่อ Model บ้าง
Model จะมาคู่กับ Database Table เสมอ
โดยชื่อ Model ต้องเป็นเอกพจน์ ส่วนชื่อ Table ต้องเป็นพหูพจน์
class Property < ActiveRecord::Base
ชื่อ table ที่ประกบกับ model นี้ ก็ต้องเป็น
properties
ที่น่าสนใจก็คือ Rails ใช้กฎอะไรในการแปลง เอกพจน์ เป็น พหูพจน์
class ที่เกี่ยวข้องในเรื่องนี้ อยู่ใน package ActiveSupport
มีชื่อว่า
Inflections
กับ Inflector
ลองดูตัวอย่าง ตารางการแปลงของ Rails ดู
inflect.plural(/$/, 's')
inflect.plural(/s$/i, 's')
inflect.plural(/(ax|test)is$/i, '\1es')
inflect.plural(/(octop|vir)us$/i, '\1i')
inflect.plural(/(alias|status)$/i, '\1es')
...
inflect.irregular('person', 'people')
inflect.irregular('man', 'men')
inflect.irregular('child', 'children')
...
inflect.uncountable(%w(equipment information rice money species series fish sheep))
ถ้าอยากรู้ว่าอะไรแปลงเป็นอะไร ก็สามารถใช้
script/console
ทดสอบดูได้~/projects/rail/akando_dev $ script/console
Loading development environment.
>> "person".pluralize
=> "people"
>> "mouse".pluralize
=> "mice"
>>
ทีนี้กระโดดไปที่ scaffold บ้าง
เวลาที่เราสั่ง generate scaffold เราใช้คำสั่งต่อไปนี้
script/generate scaffold modelName
แน่นอน modelName ที่ระบุใน scaffold อยู่ในรูปเอกพจน์
แต่ชื่อของ controller ที่ scaffold generate ให้นี้จะอยู่ในรูป พหูพจน์
เช่น
script/generate scaffold Property
จะได้
class PropertiesController
ใน file properties_controller.rb
เรื่องการใช้เอกพจน์ หรือพหูพจน์นี้ จริงๆพอใช้ไปสักพัก ก็จะเริ่มรู้สึก
เป็นธรรมชาติขึ้น (ฝรั่งคงไม่มีปัญหา เพราะเป็นภาษาเขา)
ซึ่งมันก็สื่อดีเหมือนกัน เช่น
Project.find(1)
ย่อมดีกว่า
Projects.find(1)
----
project = Project.find(1)
project.milestones.each {|milestone|
...
}
ดูดีกว่า
project.milestone.each {|milestone|
...
}
Related link from Roti
Subscribe to:
Posts (Atom)