Scala Play Forms:使用 HLists 绕过 22 个字段的限制
Scala Play Forms: using HLists to get around the 22 fields limitation
Slick 使用 HList 的一种 hack 来管理超过 22 列的表,例如这个(自动生成的)行模型构造函数:
type SamplesRow = HCons[Int,HCons[String,HCons[Option[String],HCons[Int,HCons[String,HCons[Int,HCons[Int,HCons[Option[Int],HCons[Option[Float],HCons[Option[Float],HCons[Option[String],HCons[Option[String],HCons[Boolean,HCons[Option[String],HCons[Option[String],HCons[Option[String],HCons[Option[String],HCons[Option[String],HCons[Option[Int],HCons[Option[Float],HCons[Option[Float],HCons[Option[Float],HCons[Option[String],HCons[Option[String],HNil]]]]]]]]]]]]]]]]]]]]]]]]
def SamplesRow(id: Int, name: String, shortName: Option[String] = None, sampleTypeId: Int, receivedDate: String, projectId: Int, taxoId: Int, quantifMethodId: Option[Int] = None, concentration: Option[Float] = None, volume: Option[Float] = None, description: Option[String] = None, comment: Option[String] = None, istrashed: Boolean = false, commentCustomer: Option[String] = None, createdAt: Option[String] = None, updatedAt: Option[String] = None, createdBy: Option[String] = None, updatedBy: Option[String] = None, poId: Option[Int] = None, `260280Ratio`: Option[Float] = None, `260230Ratio`: Option[Float] = None, rin: Option[Float] = None, concUpdatedAt: Option[String] = None, concUpdatedBy: Option[String] = None): SamplesRow = {
id :: name :: shortName :: sampleTypeId :: receivedDate :: projectId :: taxoId :: quantifMethodId :: concentration :: volume :: description :: comment :: istrashed :: commentCustomer :: createdAt :: updatedAt :: createdBy :: updatedBy :: poId :: `260280Ratio` :: `260230Ratio` :: rin :: concUpdatedAt :: concUpdatedBy :: HNil
}
我可以使用相同的技巧让一个表单保存 24 个值吗?喜欢
val tableForm: Form[SamplesRow] = Form(
mapping(
ID -> ignored(-1),
NAME -> text,
SHORT_NAME -> optional(text),
SAMPLE_TYPE_ID -> number,
RECEIVED_DATE -> default(text, NOW),
PROJECT_ID -> number,
TAXO_ID -> number,
QUANTIF_METHOD_ID -> optional(number),
CONCENTRATION -> optional(of[Float]),
VOLUME -> optional(of[Float]),
DESCRIPTION -> optional(text),
COMMENT -> optional(text),
IS_TRASHED -> default(boolean, false),
COMMENT_CUSTOMER -> optional(text),
CREATED_AT -> optional(text),
UPDATED_AT -> optional(text),
CREATED_BY -> optional(text),
UPDATED_BY -> optional(text),
PO_ID -> optional(number),
RATIO_260_280 -> optional(of[Float]),
RATIO_260_230 -> optional(of[Float]),
RIN -> optional(of[Float]),
CONC_UPDATED_AT -> optional(text),
CONC_UPDATED_BY -> optional(text)
)(SamplesRow)(???)
)
我觉得上面的构造函数 def SamplesRow
可以用作 apply
方法,但是我可以将什么用作“unapply
”?
我知道我应该使用嵌套映射,但是我无法将结果直接映射到 Slick 行模型,而且编写 100 行代码来实现转换以便我可以执行插入听起来很愚蠢.
我很想完全摆脱 Forms 并用自定义 JsObject 解析替换它们:
// Controller Action:
val content = request.body.asJson
val row = rowFromJson(content)
// Somewhere else
import play.api.libs.json._
def rowFromJson(j: JsObject): SamplesRow = {
SamplesRow(
(j \ "id").as[Int],
(j \ "name").as[String]
...
)
}
其中 SamplesRow
是 Samples#TableElementType
的 table Samples <: AbstractTable[_]
。
Slick 使用 HList 的一种 hack 来管理超过 22 列的表,例如这个(自动生成的)行模型构造函数:
type SamplesRow = HCons[Int,HCons[String,HCons[Option[String],HCons[Int,HCons[String,HCons[Int,HCons[Int,HCons[Option[Int],HCons[Option[Float],HCons[Option[Float],HCons[Option[String],HCons[Option[String],HCons[Boolean,HCons[Option[String],HCons[Option[String],HCons[Option[String],HCons[Option[String],HCons[Option[String],HCons[Option[Int],HCons[Option[Float],HCons[Option[Float],HCons[Option[Float],HCons[Option[String],HCons[Option[String],HNil]]]]]]]]]]]]]]]]]]]]]]]]
def SamplesRow(id: Int, name: String, shortName: Option[String] = None, sampleTypeId: Int, receivedDate: String, projectId: Int, taxoId: Int, quantifMethodId: Option[Int] = None, concentration: Option[Float] = None, volume: Option[Float] = None, description: Option[String] = None, comment: Option[String] = None, istrashed: Boolean = false, commentCustomer: Option[String] = None, createdAt: Option[String] = None, updatedAt: Option[String] = None, createdBy: Option[String] = None, updatedBy: Option[String] = None, poId: Option[Int] = None, `260280Ratio`: Option[Float] = None, `260230Ratio`: Option[Float] = None, rin: Option[Float] = None, concUpdatedAt: Option[String] = None, concUpdatedBy: Option[String] = None): SamplesRow = {
id :: name :: shortName :: sampleTypeId :: receivedDate :: projectId :: taxoId :: quantifMethodId :: concentration :: volume :: description :: comment :: istrashed :: commentCustomer :: createdAt :: updatedAt :: createdBy :: updatedBy :: poId :: `260280Ratio` :: `260230Ratio` :: rin :: concUpdatedAt :: concUpdatedBy :: HNil
}
我可以使用相同的技巧让一个表单保存 24 个值吗?喜欢
val tableForm: Form[SamplesRow] = Form(
mapping(
ID -> ignored(-1),
NAME -> text,
SHORT_NAME -> optional(text),
SAMPLE_TYPE_ID -> number,
RECEIVED_DATE -> default(text, NOW),
PROJECT_ID -> number,
TAXO_ID -> number,
QUANTIF_METHOD_ID -> optional(number),
CONCENTRATION -> optional(of[Float]),
VOLUME -> optional(of[Float]),
DESCRIPTION -> optional(text),
COMMENT -> optional(text),
IS_TRASHED -> default(boolean, false),
COMMENT_CUSTOMER -> optional(text),
CREATED_AT -> optional(text),
UPDATED_AT -> optional(text),
CREATED_BY -> optional(text),
UPDATED_BY -> optional(text),
PO_ID -> optional(number),
RATIO_260_280 -> optional(of[Float]),
RATIO_260_230 -> optional(of[Float]),
RIN -> optional(of[Float]),
CONC_UPDATED_AT -> optional(text),
CONC_UPDATED_BY -> optional(text)
)(SamplesRow)(???)
)
我觉得上面的构造函数 def SamplesRow
可以用作 apply
方法,但是我可以将什么用作“unapply
”?
我知道我应该使用嵌套映射,但是我无法将结果直接映射到 Slick 行模型,而且编写 100 行代码来实现转换以便我可以执行插入听起来很愚蠢.
我很想完全摆脱 Forms 并用自定义 JsObject 解析替换它们:
// Controller Action:
val content = request.body.asJson
val row = rowFromJson(content)
// Somewhere else
import play.api.libs.json._
def rowFromJson(j: JsObject): SamplesRow = {
SamplesRow(
(j \ "id").as[Int],
(j \ "name").as[String]
...
)
}
其中 SamplesRow
是 Samples#TableElementType
的 table Samples <: AbstractTable[_]
。