Ruby 能不能覆盖 rake assets:precompile

tiseheaini · 2013年04月26日 · 最后由 edokeh 回复于 2013年06月01日 · 3133 次阅读

我在实现一个 gem,当中需要在 rake assets:precompile 编译完成后执行一些额外的操作。 只知道可以打开一个类,然后添加一个方法,但在 actionpack-3.2.8/lib/sprockets/assets.rake 里面用的是 DSL 语法,不知道如何修改里面的实现方法。 我在项目目录里面
ruby-china/lib/tasks/xxxxx.rake

namespace :assets do
  desc "kill kill kill precompile"
  task :precompile => :production do
    invoke_or_reboot_rake_task "assets:precompile:all"
    system("echo 'push assets to remote' >> ~/asset.log ")
  end 
end

这样写一个 rake 是可以实现功能。 但写在 gem 的 lib/tasks/xxxx.rake里面就没办法运行 如果无法实现,只能在安装 gem 的时候将 xxxx.rake 文件复制到项目中,不过这样的实现很恶心,不知道大家有没有更加优雅的实现方式。@jasl @camel

没有做过类似的需求,帮你 google 了一下 http://stackoverflow.com/questions/6205968/how-do-i-override-rake-tasks-for-a-custom-database-adapter 这个需求似乎和你的场景类似,不知对你有没帮助

#1 楼 @jasl 貌似类似,不过不太明白怎么在 xxxx.rake 里面打猴子补丁,看 stackoverflow 里面,好像是要先删除一个 task 然后再去覆盖它??请指教

#2 楼 @tiseheaini 在外边没办法测试,你注意下

Rake::Task['db:create'].enhance do
  Rake::Task['db:after_create'].invoke
end

这个 所以说可以推断,tasks 会存储在 Rake::Task 集合里,invoke 方法可以通过代码调用 task

谢谢帮忙,我是在 http://stackoverflow.com/questions/8112074/overriding-rails-default-rake-tasks 找到的方法 先使用 Rake::Task["assets:precompile"].clear 把 task 清除掉,然后再去写一个结构一样的方法重新实现。 不过用这种方式没办法修改默认的描述信息

巧了,正好也在研究这个事情,可以跟 LZ 分享一下

要在给某个 task 增加前置 task,可以这样

Rake::Task[:foo].enhance [:add_prereq_1, :add_prereq_2]

增加后置的 @jasl 已经说了,就是这样

Rake::Task["db:test:prepare"].enhance do
  Rake::Task["db:test:special_task_after_prepare"].invoke
end

以上来自 http://www.dan-manges.com/blog/modifying-rake-tasks

但是对于 assets:precompile 这个任务,如果你用上面的方法去增加一个后置 task 的话,会有问题 具体表现为执行 rake assets:precompile 能够运行后置 task 而执行 RAILS_ENV=production RAILS_GROUPS=asset rake assets:precompile 则不能

我研究了下源码,发现症结在这里 https://github.com/rails/rails/blob/v3.2.12/actionpack/lib/sprockets/assets.rake#L12 因为一个内置任务运行的时候,使用了 Kernel.exec,这会导致整个进程被 replace 掉,所以原来的后置 task 就丢了,解决办法我还在想,不知道 LZ 这方面的进展如何?

了解了,你没有用 enhance 方法来追加后置,而是清空原来的任务,重新自己定义 感谢分享!

哦,想到个问题,这样做的话如果有另外一个 task 也做同样的事情,似乎有冲突吧?

#8 楼 @edokeh 看 stackoverflow 上面没有说这样的问题,我测试了一下我写的 gem,还可以,看具体的需求

我意思是如果两个 gem 都做类似的事情的话,貌似先加载的 gem 所追加的任务不会被执行吧?

需要 登录 后方可回复, 如果你还没有账号请 注册新账号