锁定老帖子 主题:在rails中优雅的进行模型校验
该帖已经被评为精华帖
|
|
---|---|
作者 | 正文 |
发表时间:2008-09-08
dave liu 写道 不管代码是怎么来的 代码中处理的方法似乎比gigix的好 gigix的有牛刀宰鸡的嫌疑
如果你半年里每天对着这一两百个action你就不会这么想了 |
|
返回顶楼 | |
发表时间:2008-09-08
gigix 写道
dave liu 写道
不管代码是怎么来的 代码中处理的方法似乎比gigix的好 gigix的有牛刀宰鸡的嫌疑
如果你半年里每天对着这一两百个action你就不会这么想了
俺们做的系统需要处理的有这种需求的表单不会有上百个,而且无非加个判断而已,是可以接收的,而且gigix的方法貌似是存在的写文件的问题。
另外我想问问gigix同学,你的方法中,在过滤器是不是要判断对哪个表单进行校验,怎么弄的啊?如果有些model的保存只涉及一个model也要去过滤下全修改全不修改吗?哎……头疼 |
|
返回顶楼 | |
发表时间:2008-09-08
right now 写道 另外我想问问gigix同学,你的方法中,在过滤器是不是要判断对哪个表单进行校验,怎么弄的啊?如果有些model的保存只涉及一个model也要去过滤下全修改全不修改吗?哎……头疼
sigh 以前Spring那么火的时候你们在干什么呢…真疑惑… 对于绝大多数action,你不需要知道里面出了”什么“错,你只需要知道只要里面出了错,那么所有的数据库操作都应该回滚 对于少数action,你需要在回滚的同时再回调一些东西来收拾残局 就这么简单 |
|
返回顶楼 | |
发表时间:2008-09-08
around_filter的方法确实比较巧妙,一开始看到就想起了spring,这个解决方案应该是优雅的,而且非常的通用。至于说什么删除图片的问题,根本不会存在,因为transaction fail的时候after_save这些根本也不会被调用的。用了快两年的rails,还没用过around_filter,汗。。。 这里学了一招 。
|
|
返回顶楼 | |
发表时间:2008-09-08
在保存模型时还要处理上传图片时,我自己的做法通常是在 before_save 中处理图片。
因为需要按照上传时间等信息生成 hash 后的图片文件名,再把图片文件名放入模型,最后保存模型。 在 before_save 中处理图片失败时可以抛出异常来引起事务回滚,如果放在 after_save 里面处理图片就不好办了吧? |
|
返回顶楼 | |
发表时间:2008-09-15
gigix 写道
liuqiang 写道
呵呵,针对20个表单的过滤器,代码肯定不止20行,2者代码都不是很多,没必要斤斤计较啦,综合考虑,您再仔细琢磨琢磨,哪种方法比较爽
8行 class TransactionFilter def filter(controller) return yield if controller.request.get? ActiveRecord::Base.transaction do yield end end end 你大概还需要2~3行把它声明在application.rb里面 作为比较,我这个项目大概有150~200个action 重点在于: (1)重复 (2)不必要的思考
比较欣赏这个方法。有点像简化版的声明型事务。
|
|
返回顶楼 | |
发表时间:2008-09-15
gigix 写道
right now 写道
另外我想问问gigix同学,你的方法中,在过滤器是不是要判断对哪个表单进行校验,怎么弄的啊?如果有些model的保存只涉及一个model也要去过滤下全修改全不修改吗?哎……头疼
sigh 以前Spring那么火的时候你们在干什么呢…真疑惑… 对于绝大多数action,你不需要知道里面出了”什么“错,你只需要知道只要里面出了错,那么所有的数据库操作都应该回滚 对于少数action,你需要在回滚的同时再回调一些东西来收拾残局 就这么简单
sigh , 我当然要知道出什么错啦,我还指望返回错误信息给用户呢!
LZ 和快克王给出的是错误校验的具体办法,你所说的是事务,你只不过是想说把这个校验放到filter中而已,这本身就是2回事。用了事务(当然是必须的),难道就不需要数据校验了不成?这个事情是省不掉的,但照你的意思,就是管他什么格式,只要知道出错了就可以了,我觉得这样太恐怖了。当然你可能又另有蹊径去解决,你还是说清楚吧(这种校验也是必要的),省得误导群众。
PS:借用一句话,这年头谁也不比谁多懂一点,劝各位还是按gigix的做法实践一遍在发言吧 |
|
返回顶楼 | |
发表时间:2008-11-06
gigix 写道 liuqiang 写道 注意,您还是把您这个方法的调用,说明下
class ApplicationController < ActionController::Base around_filter :transaction_filter def transaction_filter(&block) TransactionFilter.new.filter(self, &block) end 今天在google一个rails transaction问题的时候发现又回到了这篇,用gigix的这种方法会有一个问题: rails的around_filter是在整个action执行完以后才会执行,这样事务边界就被扩大到了整个action def foo #希望有个改进的filter机制从这里开始 model1.save model2.save #在任何render之前结束 render :action => :bar #而不是象现在的around_filter在这里结束 end 回头再看看rails的代码,是否能够找个简单的地方hack一下。 |
|
返回顶楼 | |
发表时间:2008-11-06
我非常反对gigix这种不管三七二十一,任何请求进来都统统最后给commit一把的做法。因为很早以前我就做过性能测试,对于每个请求都commit的做法,虽然对请求处理的速度影响很小(大约5%的性能损失),但是对数据库会造成非常大的压力,会让数据库的CPU占用率直线上升。
|
|
返回顶楼 | |
发表时间:2008-11-06
robbin 写道 我非常反对gigix这种不管三七二十一,任何请求进来都统统最后给commit一把的做法。因为很早以前我就做过性能测试,对于每个请求都commit的做法,虽然对请求处理的速度影响很小(大约5%的性能损失),但是对数据库会造成非常大的压力,会让数据库的CPU占用率直线上升。
gigix之前贴的代码里面是有判定非get request才进行transaction的open/commit,所以对数据库不会有影响的。 |
|
返回顶楼 | |