是的,存在几个类似的线程,但我们现在在2011年,并且已经发生了很大变化.
当我最初尝试学习框架(并放弃了慢编译时间和其他呻吟诱导事件)时,Grails 1.3.6与v1.3相比有了很大的改进.
在最新版本中花了几个月的时间,给我留下了深刻的印象,对应用程序进行原型设计是一件轻而易举的事(GORM很棒!).在开发模式下,不再需要重新启动,禁止更改域类.Groovy.lang非常棒(请记住,这与我在PHP中的日常工作生活相比).
现在,另一方面是Ruby/Rails,我对于浏览Ruby文档和探索Active Record(与GORM进行比较)几乎没有什么经验.来自PHP/Jquery,groovy语法是cake,ruby不是那么多,虽然可以访问.
Ruby/Rails风靡一时,而Groovy/Grails似乎正在加快速度.
我想听听两个阵营的说法(火焰引发战争欢迎)re:2011年langs/frameworks的优点/缺点.在选择框架时,重要的是要知道你正在进入什么,所以有在它,新手将受益,专家可以发泄; - )
花了一个小时的时间试图找出地球上的原因(coffeescript)
$.ajax
accepts: "application/json; charset=utf-8"
Run Code Online (Sandbox Code Playgroud)
没有绝对没有改变接受头,而这
$.ajax
dataType: "json"
Run Code Online (Sandbox Code Playgroud)
正确设置接受标头 application/json; charset=utf-8
我完全糊涂了,我错过了什么,或者是全年愚人节开玩笑的接受因素?
我想强制光滑创建像
select max(price) from coffees where ...
Run Code Online (Sandbox Code Playgroud)
但光滑的文档没有帮助
val q = Coffees.map(_.price) //this is query Query[Coffees.type, ...]
val q1 = q.min // this is Column[Option[Double]]
val q2 = q.max
val q3 = q.sum
val q4 = q.avg
Run Code Online (Sandbox Code Playgroud)
因为那些q1-q4不是查询,我无法获得结果,但可以在其他查询中使用它们.
这个说法
for {
coffee <- Coffees
} yield coffee.price.max
Run Code Online (Sandbox Code Playgroud)
生成正确的查询但不推荐使用(生成警告:"不推荐使用类ColumnExtensionMethods中的方法max:使用Query.max"). 如何在没有警告的情况下生成此类查询?
另一个问题是通过以下方式聚合:
"select name, max(price) from coffees group by name"
Run Code Online (Sandbox Code Playgroud)
试图解决它
for {
coffee <- Coffees
} yield (coffee.name, coffee.price.max)).groupBy(x => x._1)
Run Code Online (Sandbox Code Playgroud)
产生
select x2.x3, x2.x3, x2.x4 from (select x5."COF_NAME" …Run Code Online (Sandbox Code Playgroud) 在Scala 2.10中,显然我们正在改进反思.
这将如何影响lift-json,jerkson,sjson和朋友?此外,我们能否在不久的将来期望内置的JSON语言功能和Scala中的Groovy优秀GSON?
我问的原因是我非常喜欢这样做:
case class Foo(a: String, b: Int, bar: Bar)
case class Bar(c: Int)
val foo = Foo("hey", 10, Bar(23))
val json = foo.toJson
Run Code Online (Sandbox Code Playgroud)
没有环跳(即样板准备工作),即使是任意复杂的对象图.也许我问得太多了,但总能做到梦想.请打破我的2.10梦想,或者通过备受期待的Scala版本打开新的途径.
此外,关于案例类,似乎验证/创建,scalaz验证是首选的武器.它看起来非常精彩,可以作为对象创建的安全代理或作为错误收集器.然而,作为一个Scewbie,我发现scalaz有点挑战性,并且尽管它有明显的力量,我仍然抵抗F-ing黑暗面;-)
无论如何,这里的重点是,2.10反射我们应该能够在运行时绑定从表单帖子到案例类的属性的字段,并仅基于属性类型执行基本验证(即不会指定单独的验证逻辑,指定属性foo必须是一个String,因为它的类型已在case类中定义,我们现在可以正确地反映它
那么,勇敢的新世界到来,还是现有的工具是可预见的未来的支柱?
我有一个绑定到一个相当狭窄的盒子的链接列表; 足够狭窄的一些链接包装.
line-height设置为30px,适用于非包装链接; 但是,对于文本足够长以强制换行的链接,也会在其中应用30px行高,从而使其看起来好像有2个链接而不仅仅是链接文本的延续.
我想以某种方式(没有js或在中间件上结束计算字符串长度)来使包装的链接文本具有10px左右的行高,以给出连续而不是分离的视觉印象.
我目前的用例非常简单,无论是可变的还是不可变的Map都可以解决问题.
有一个采用不可变Map的方法,然后调用第三方API方法,该方法也采用不可变Map
def doFoo(foo: String = "default", params: Map[String, Any] = Map()) {
val newMap =
if(someCondition) params + ("foo" -> foo) else params
api.doSomething(newMap)
}
Run Code Online (Sandbox Code Playgroud)
有问题的地图通常很小,最多可能有一个嵌入的案例类实例列表,最多几千个条目.因此,再次假设在这种情况下对于不可变的影响很小(即通过newMap val副本基本上有2个Map实例).
不过,它让我有点唠叨,复制地图只是为了得到一张新的地图,上面贴着几个k-> v条目.
我可以params.put("bar", bar)为我想要处理的条目变为可变等等,然后params.toMap为api调用转换为immutable,这是一个选项.但后来我必须导入并传递可变映射,与使用Scala的默认不可变映射相比,这有点麻烦.
那么,对于在不可变映射上使用可变映射的合理/良好实践的一般指导原则是什么?
谢谢
编辑 所以,看起来不可变地图上的添加操作接近恒定时间,确认@ dhg和@Nicolas断言没有制作完整副本,这解决了所呈现的具体案例的问题.
难倒在这一个.在Grails中,似乎无法在域映射中的多个列上定义默认排序la static mapping = {sort'prop1 desc,prop2 asc'}或{sort([prop1:'desc',prop2:'asc']) }.只有第一列被排序,跛脚.
类似地,当尝试Groovy在多个列上对Grails findAllBy查询进行排序时,第二种排序会覆盖第一种.
def list = [[rowNum:2,position:3],[rowNum:1,position:2],[rowNum:3,position:1]]
list.sort {it.rowNum}的.sort {it.position}
在后一种情况下显然错过了船,经常排序.我看过帖子重新:实现可比性,但如果可能的话,寻找更简洁的东西.
我能够在编译之前自动执行任务:
compile in Compile <<= (compile in Compile).dependsOn(myTask)
Run Code Online (Sandbox Code Playgroud)
如何在编译后做同样的事情?
我知道我能做到:
compile in Compile <<= (compile in Compile) map{x=>
// post-compile work
doFoo()
x
}
Run Code Online (Sandbox Code Playgroud)
执行任意Scala代码,但我需要在编译事件发生时自动执行目标任务
做类似的事情:
val foo = TaskKey[Unit]("foo", "...")
val fooTask = foo <<= scalaInstance map {si =>
...
} dependsOn(compile in Compile)
Run Code Online (Sandbox Code Playgroud)
如果我从sbt>提示符输入"foo",则可以正常工作; 即任务在编译后执行,但目标是挂钩到编译任务本身,因此无论何时编译发生,foo任务在编译完成后自动调用.
这是可能的,还是我以错误的方式处理内置编译任务?
首先,通过SBT进行的增量构建非常棒,通常在<1秒范围内.但是,有时您必须进行完全清理/编译,或者在增量构建的情况下,您对一个文件进行更改,然后触发编译其他几十个文件.
这就是Scala开发变得不那么有趣了,因为工作流程的减慢可以鼓励上下文切换(检查电子邮件,最新的Stackoverflow线程等),这会巧妙地降低工作效率
那么,为了改进完整的清理/编译构建,以及(理想情况下)更改一个文件而不重新编译一半应用程序增量构建,需要避免哪些开发方法?
我可以想到的例子:
1)最好有一千个+行全部scala文件,或者几个文件分开?
2)我可以拥有蛋糕(模式)还是会延长构建时间?
3)我可以拥有pimp'd x,y,z库模式,还是更好地找到另一种方式?
4)包装对象(带有隐含)是构建时间杀手吗?
5)嵌套对象和特征?
6)隐含的方法/参数或停止聪明和明确?
具体来说,我正在考虑放弃一个蛋糕模式DAO我提出并整合到ScalaQuery案例类+伴随对象+最小数据库提供程序特征.仅此一项就可以删除20个scala文件.
应用程序足够小(120 scala + 10个java文件)现在重构,没有太多麻烦.显然,随着scala应用程序的增长,构建时间也会增长,仅基于LOC.我只是想看看在哪里修剪脂肪以及在哪里不打扰(即保持原样),因此当前和未来的应用程序将受益于scala提供的表现力,而不会不必要地增加构建时间.
感谢您在构建时间内体验scala开发的好,坏和丑的一些示例.
参考:
Scala 在scala控制器中返回关键字
处理错误
EDIT3
这是"最终"解决方案,再次感谢Dan Burton.
def save = Action { implicit request =>
val(orderNum, ip) = (generateOrderNum, request.remoteAddress)
val result = for {
model <- bindForm(form).right // error condition already json'd
transID <- payment.process(model, orderNum) project json
userID <- dao.create(model, ip, orderNum, transID) project json
} yield (userID, transID)
}
Run Code Online (Sandbox Code Playgroud)
然后是pimp'd Either项目方法,放在你的应用程序的某个地方(在我的例子中,一个impbits特性,sbt root和子项目扩展了它们的基础包对象:
class EitherProvidesProjection[L1, R](e: Either[L1, R]) {
def project[L1, L2](f: L1 => L2) = e match {
case Left(l:L1) => Left(f(l)).right
case Right(r) => Right(r).right …Run Code Online (Sandbox Code Playgroud) scala ×6
grails ×2
coercion ×1
compilation ×1
compile-time ×1
css ×1
frameworks ×1
groovy ×1
header ×1
immutability ×1
jquery ×1
json ×1
map ×1
mutable ×1
overriding ×1
performance ×1
reflection ×1
response ×1
return ×1
sbt ×1
scalaquery ×1
set ×1
slick ×1
sorting ×1
task ×1
types ×1
use-case ×1
word-wrap ×1