接着004中的例子,004中我们希望找出所有未完成的任务,好吧,我承认,我半途而废的事实在是太多了,也许有几百个上千个,谁知道呢,一张A4纸肯定打不下,也许我应该先列出前20条,一条一条解决以后再去考虑后面的?
事实就是这样,我要列出找到的前20条,并且距现在最近的事排在前面最先解决,更加以前的事就算忘了对现在的我也没什么影响。于是按照前面的方法,我们会这样说
Task.find_all_by_complete(false, :limit => 20)
进一步的,我们照004中的办法把find移入model,并且使用了with_scope,我们仍然能往find_incomplete里传入hash参数,这真是了不得。
# model/task.rb
belongs_to :project
def self.find_incomplete(options = {})
with_scope :find => options do
find_all_by_complete(false, :order => 'created_at DESC')
end
end
# task_controller.rb
def index
@tasks = Task.find_incomplete :limit => 20
end
# project_controller.rb
def show
@project = Project.find(params[:id])
@tasks = @project.tasks.find_incomplete :limit => 20
end
非常好,这样我们便能DRY and more powerful了。这时候上司过来了,狠狠的训了我们一顿,说什么要是谁还留着一个礼拜之前的工作没完成,今天晚上就通宵加班。我很清楚的记得我确实留着几个上个礼拜的任务,也许我应该按时间顺序排出来看看到底是哪些没完成,我可不想加班,我想应该别人也不想。
def index
@tasks = Task.find_incomplete(:limit => 20, :order => 'created_at')
end
遗憾的是,系统没能告诉我我应该去完成哪些该死的任务。之后看了hideto前辈的文章,我知道了,我们不能在调用find_incomplete时指定: order条件来覆盖该方法定义时默认的:order条件,那能不能改进一下我们的find_incomplete方法来解决这个问题呢?
很简单,我们可以将额外的参数merge进来:
# model/task.rb
def self.find_incomplete(options = {})
find_all_by_complete(false, {:order => 'created_at DESC'}.merge(options))
end
或者使用ActiveSupport对Hash的扩展方法reverse_merge:
# model/task.rb
def self.find_incomplete(options = {})
find_all_by_complete(false, options.reverse_merge(:order => 'created_at DESC'))
end
好吧,找到了任务就拼命去完成吧。