`
laowang
  • 浏览: 37485 次
  • 性别: Icon_minigender_1
  • 来自: 北京
社区版块
存档分类
最新评论

hellolift学习笔记(8)

阅读更多
随着代码的深入,涉及到的liftweb框架实现级别的代码越来越多,马上完全搞明白实现代码的愿望越来越奢侈,所以后续的笔记将侧重于例子中用到功能的解释,侧重框架的使用,只要不影响理解,尽量不再涉及框架实现层的东西。

9.Create An Entry(2--save)

form提交之后涉及到的过程就是采集数据,写入数据库,更新缓存数据。
采集数据的过程由框架来实现,将采集到的数据封装成一个Entry对象,传递给toform时设定的函数。
写入数据库的过程由BaseMapper.save 方法完成(实际是在Mapper中实现,当然其中很多工作又交给了MetaMapper对象去完成),我们所需要做的就是调用一下save方法,或者如果你愿意的话,在保存的过程中插入你自己想要做的一些事情。
例子中我们能看到afterCommit的使用
// Once the transaction is committed, fill in the blog cache with this entry.
  override def afterCommit =
    ((entry: Entry) => {BlogCache.cache ! AddEntry(entry, entry.author.is)}) :: Nil

,相似的还有以下一些函数可以利用
  def beforeValidation: List[A => Unit] = Nil
  def beforeValidationOnCreate: List[A => Unit] = Nil
  def beforeValidationOnUpdate: List[A => Unit] = Nil
  def afterValidation: List[A => Unit] = Nil
  def afterValidationOnCreate: List[A => Unit] = Nil
  def afterValidationOnUpdate: List[A => Unit] = Nil

  def beforeSave: List[A => Unit] = Nil
  def beforeCreate: List[(A) => Unit] = Nil
  def beforeUpdate: List[(A) => Unit] = Nil

  def afterSave: List[(A) => Unit] = Nil
  def afterCreate: List[(A) => Unit] = Nil
  def afterUpdate: List[(A) => Unit] = Nil

  def beforeDelete: List[(A) => Unit] = Nil
  def afterDelete: List[(A) => Unit] = Nil


还有一段代码没有看
override def setFilter = notNull _ :: trim _ :: crop _ :: super.setFilter

说实话,这个命名让我对自己的审美观产生了怀疑,哪位大神居然起了这么个名字!?首先,这不是个set方法,其次他的内容也不同于Iterable中的filter方法,估计他的命名原意是,set之前进行的filter工作。我们来看这个方法的原始定义
/**
   * A list of functions that transform the value before it is set.  The transformations
   * are also applied before the value is used in a query.  Typical applications
   * of this are trimming and/or toLowerCase-ing strings
   */
  protected def setFilter: List[FieldType => FieldType] = Nil

这是一个函数列表,每一个函数都接收一个本类型字段,对其加工之后仍然返回一个本类型字段,用以实现流水线似的转换工作。

这个名字倒是说明白了,这个函数的作用,在每次字段被赋值之前都将被这一系列函数加工。MappedField的子类中各自实现了自己使用的filter。

本例中body字段定义的setFilter使得对body字段有了一些限制,比如说crop方法决定了body的值如果大于构造参数的20000,将被截断,注意,这个行为不仅仅体现是表单提交时,即使是在代码中赋值也一样会被截断。

但是Entry的另一个字段title就稍微有些怪异。
object title extends MappedString(this, 128)

这个怪异在于,MappedString的缺省setFilter中并没有crop方法,所以虽然在toForm过程中maxlength(128)会被用来限制输入框的maxLength,但是如果在代码中赋值的话却不会被截断。

解决这个倒也简单,自己重载setFilter,或者用MappedPoliteString代替MappedString,这个类只干了这一件事(我真觉不出这是一个多好的设计)。

现在,我们也基本搞明白了MappedField构造时this之外参数的作用了。不过这里留下了一个疑问,现在的错误都被系统默默的吞掉了,如何给用户提示呢?

ok,只剩下一点点东西了,我快速的把这个过程close掉。

afterCommit:
在理解了viewblog的过程之后,这个afterCommit之后的处理就没有什么新鲜的了:通知BlogCache,缓存博客内容,通知正在关注这个博客的comet刷新内容。
这里也留下了个小疑问,订阅的comet是被记录在了sessions中,但是如果那个页面关闭,这个sessions中的值是何时被清除的呢?

viewentry:
t.save 之后,将跳转到/veiwentry,BlogUtil.viewentry演示了一种有body的snippet类型,body内容将会作为xhtml参数传递进来。
利用net.liftweb.util.BindHelpers.bind方法把指定namespace的标签值替换为合适的内容。
这里的疑问是,替换时为什么要显示的调用toString方法呢,我尝试去掉toString没有发现什么异常。

BlogUtil还有一个_entryview与DynamicBlogView的同名方法完全一致,怀疑是个小疏忽。

把几个疑问单拎出来:
1.现在的属性字段的错误被系统默默的吞掉了,如何给用户提示呢?
2.订阅的comet是被记录在了sessions中,但是如果那个页面关闭,这个sessions中的值是何时被清除的呢?
3.viewentry替换时为什么要显示的调用toString方法呢,我尝试去掉toString没有发现什么异常。

打完,收工!
分享到:
评论
3 楼 laowang 2009-11-23  
yangzhan 写道
老王,你对lift把html代码都写到Model里有什么看法呢?
看您对Lift的研究比较深,能否谈下Lift的优缺点呢?多谢!

呵呵,太惭愧了,如果看我第一篇你会知道我根本谈不上研究比较深,只是借这个方式来学习scala和lift而已。对于lift现在不敢有太多的评价,还在摸索了解阶段。
至于Model中嵌入html代码我是这么看的:
1.这种方式有他的优势,尤其是在ajax使用越来越多的情况下,我已经烦透了为一个ajax请求去实现并且配置一个页面,仅仅是为了返回一个非常简单的信息的方式。
2.我也一直思考,php那样的方式,如果真的这样的实现是传说中的那样可怕,怎么解释php被这样普遍的使用?作为纯web开发来说,严格的分层一定最合适的么?(我已经不接触php很多年了,如果这句话说得不靠谱,别扁我)
3.当然这种方式的使用,有他的缺点,必然不能适应所有的情况,先不说分层实现之类的东西,在对页面要求比较高的情况下,仅仅套页面工作也将是一场噩梦。

2 楼 yangzhan 2009-11-23  
老王,你对lift把html代码都写到Model里有什么看法呢?
看您对Lift的研究比较深,能否谈下Lift的优缺点呢?多谢!
1 楼 yangzhan 2009-11-21  
学习了,老王好勤奋!

相关推荐

Global site tag (gtag.js) - Google Analytics