【问题标题】:transform anorm (play framework) value before binding在绑定之前转换异常(播放框架)值
【发布时间】:2014-07-10 18:43:17
【问题描述】:

我有一个代表我的领域的案例类:

case class MyModel(rawValue: String, transformedValue: String)

rawValue 映射到数据库中的一个值,并被正确解析和绑定。我想要做的是将transformedValue 添加到我的模型中:这个值只是我对 rawValue 执行的一些任意转换。它映射到数据库/查询中的任何数据。

我有一个如下所示的解析器(在添加 transformedValue 之前):

val parser = {
  get[String]("rawValue") map {
    case rawValue => MyModel(rawValue)
  }
}

由于MyModel 是不可变的,并且在创建transformedValue 后我无法将其插入其中,因此最好的方法是什么以及在哪里添加这种转换(例如,向模型添加临时值)不使用变量?

来自 Java,我可能只是在域类中添加了一个 getTransformedValue getter,以对 rawValue 属性执行此转换。

【问题讨论】:

    标签: scala playframework-2.0


    【解决方案1】:

    由于transformedValue 似乎是一个派生属性,而不是在构造函数中提供的东西,您可以将它定义为函数体中的一个属性,可能使用lazy 限定符,以便它将仅按需计算(例如仅一次):

    case class MyModel(rawValue: String) {
      lazy val transformedValue: String = {
        // Transformation logic, e.g.
        rawValue.toLowerCase()
      }
    }
    

    val 在定义时进行评估; def 在调用时进行评估。 lazy val 在第一次访问时被评估。

    在很少需要的昂贵计算或逻辑需要的情况下,使用lazy 可能是合适的。但在大多数情况下,应该使用常规的valQuoting:

    lazy val 不是免费的(甚至很便宜)。仅当您绝对需要惰性来确保正确性而不是优化时才使用它。

    【讨论】:

    • 谢谢。这看起来像我在看到这个之前发布的解决方案。我喜欢使用“懒惰”的想法。您能否通过使用 val 而不是 def 来评论差异(就像我在解决方案中所做的那样)?
    • val 在定义时进行评估; def 在调用时进行评估。 lazy val 在第一次访问时被评估。见stackoverflow.com/a/7484933/376366
    • 查看更新的答案以了解何时使用惰性 val 而不是 val。
    【解决方案2】:

    我不明白您为什么不只在解析器本身中进行转换:

    def transformation(rawValue: String): String = ...
    
    val parser = {
        get[String]("rawValue") map {
            case rawValue => MyModel(rawValue, transformation(rawValue))
        }
    }
    

    或者,如果您出于某种原因不想在那里执行此操作,您可以使用 copy 创建具有新值的 MyModel 的新副本:

    val model = MyModel("value", ..)
    
    val modelWithTransform = model.copy(transformedValue = transformation(model.rawValue))
    

    您还可以重载 apply 以在伴随对象中自动应用转换:

    case class MyModel(rawValue: String, transformedValue: String)
    
    object MyModel {
    
        def apply(value: String): MyModel = MyModel(rawValue, transformation(rawValue))
    
        val parser = {
            get[String]("rawValue") map {
                case rawValue => MyModel(rawValue)
            }
        }
    }
    

    MyModel 可能是不可变的,但您始终可以创建另一个副本并更改一些值。

    【讨论】:

    • 感谢您的意见。我在看到这个之前添加了我的解决方案,并且会重视您比较两者的意见......您的解决方案确实看起来有点复杂
    • @oym 不是真的,只是利用一些语法糖。使用这种方法,您只需要进行一次计算,一旦解析就可以使用。
    【解决方案3】:

    事实证明这比我想象的要容易,而且解决方案看起来确实像我所说的我会在 java 中做的那样:

    我只是向 MyModel 添加了一个函数来进行这种转换:

    case class MyModel(rawValue: String) {
      def transformedValue = {
        // do the transformation here and return it
      }
    }
    

    【讨论】:

    • 这将在每次引用它时计算转换。只做一次,看我的回答。
    • 哦,我明白了。您不能在 def 中添加“懒惰”。仅限于 val。
    猜你喜欢
    • 1970-01-01
    • 2016-02-16
    • 1970-01-01
    • 2014-07-29
    • 2012-03-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多