Liftことはじめ その5 mapper OneToMany
前述の記事の覚書
LiftのORMでOneToManyを実装。
各trackの添付を複数指定可能にする。(必然性はないが、音楽ファイルとTab符とか)
One側のTrackクラスは、OneToManyをMixIn。属性にattachesを定義。
model/Track
package code.model import net.liftweb.mapper._ import net.liftweb.util._ import net.liftweb.common._ object Track extends Track with LongKeyedMetaMapper[Track] { override def dbTableName = "tracks" } class Track extends LongKeyedMapper[Track] with IdPK with OneToMany[Long, Track]{ def this(albumid: Long, seq: Long, tracktitle: String) = { this() this.albumid(albumid) this.seq(seq) this.tracktitle(tracktitle) } def getSingleton = Track object albumid extends MappedLong(this) object seq extends MappedLong(this) object tracktitle extends MappedString(this, 100) { override def validations = valMaxLen(100, "name length must be under 100 characters long ") _ :: valMinLen(1, "you have to input!!") _ :: super.validations } object attaches extends MappedOneToMany(Attach, Attach.track, OrderBy(Attach.id, Ascending)) }
Many側のAttachクラス。属性にtrackを定義。
package code.model import net.liftweb.mapper._ object Attach extends Attach with LongKeyedMetaMapper[Attach] { override def dbTableName = "attaches" } class Attach extends LongKeyedMapper[Attach] with IdPK { def getSingleton = Attach def this(filename: String, mimetype: String, trackattach: Array[Byte]) = { this() this.filename(filename) this.mimetype(mimetype) this.trackattach(trackattach) } object filename extends MappedString(this, 100) object mimetype extends MappedString(this, 40) object trackattach extends MappedBinary(this) object track extends LongMappedMapper(this, Track) }
利用は、以下のようなコード。
package code.snippet import java.io._ import scala.xml.{NodeSeq, Text} import net.liftweb.util._ import net.liftweb.common._ import Helpers._ import code.model._ import net.liftweb.mapper._ import net.liftweb.http._ import S._ import SHtml._ import net.liftweb.http.js.{JsCmd, JsCmds} class TrackView { … // Save def addProcess() { try { val track: Track = isAtachFileExist(upload) match { case true => { val attach: Attach = new Attach(getFileParamHolder(upload).fileName, getFileParamHolder(upload).mimeType, getFileParamHolder(upload).file) val track: Track = Track.create.albumid(albumid.toLong).seq(seq.toLong).tracktitle(tracktitle) track.attaches += attach track.save track } case false => new Track(albumid.toLong, seq.toLong, tracktitle) } track.validate match{ case Nil => { track.save() S.notice("Added " + track.tracktitle) S.redirectTo("/track?albumid=" + albumid) } case x => { S.error("Validation Error!") S.redirectTo("/track?albumid=" + albumid) } } } catch { case e: java.lang.NumberFormatException => { S.error("SEQ must be the number!") S.redirectTo("/track?albumid=" + albumid) } } } // Select private def doList(reDraw: () => JsCmd)(html: NodeSeq): NodeSeq = { val tracks:List[Track] = Track.findAll(By(Track.albumid, getAlbumId().toLong), OrderBy(Track.seq, Ascending)) bind("track", html, "albumid" -> <input type="text" name="albumid" class="column span-10"/>) tracks.flatMap(trk => { trk.attaches.flatMap(atc => { … }