ruby - Flexible Rake task -
i use following rake task multiple directories. , each directory need different constants defined. how can handle , stay dry?
namespace :assets ext = 'js' objdir = 'public/javascripts' libfile = "#{objdir}/packaged.#{ext}" src = filelist["#{objdir}/*.#{ext}"].select {|file| !file.match(/\.min\.#{ext}|packaged\.#{ext}/)} obj = src.collect {|fn| file.join(objdir, file.basename(fn).ext("min.#{ext}"))} mine = %w(4sq app fb mbp).collect {|x| x + ".#{ext}"} desc "build #{libfile}" task :build => libfile desc "remove minified files" task :clean rm_f obj end desc "remove #{libfile}" task :clobber rm_f libfile end file libfile => obj sh "cat #{obj} >> #{libfile}" end rule ".min.#{ext}" => lambda{ |objfile| find_source(objfile) } |t| if ext == 'js' if mine.include?(file.basename(t.source)) sh "closure --js #{t.source} --js_output_file #{t.name}" else sh "closure --warning_level quiet --third_party --js #{t.source} --js_output_file #{t.name}" end elsif ext == 'css' sh "yuicompressor #{t.source} -o #{t.name}" end end def find_source(objfile) base = file.basename(objfile, ".min.#{ext}") src.find {|s| file.basename(s, ".#{ext}") == base} end end
first must replace constants variables. next problem set variables. task can variables.
example:
namespace :assets |x1,x2| task :doit, :ext, :objdir |tsk, args| puts tsk p args end end you can call with:
rake assets:doit[js,objdir] result:
assets:doit called {:ext=>"js", :objdir=>"objdir"} if want avoid set variables each of task, may add 'set' task:
namespace :assets2 |x1,x2| task :set, :ext, :objdir |tsk, args| @args = args puts "#{tsk} set: #{@args.inspect}" end task :doit |tsk| puts "#{tsk} called #{@args.inspect}" end end call: rake assets2:set[js,objdir] assets2:doit
result:
assets2:set set: {:ext=>"js", :objdir=>"objdir"} assets2:doit called {:ext=>"js", :objdir=>"objdir"} instead of setting parameters, may define configuration file.
there 1 disadvantage. following task not work:
rake assets:doit[js,objdir] assets:doit[c,objdir2] assets:doit called once. second call ignored, task executed. there no check different parameters (one solution this: perhaps reset task)
edit: found , tested 'reset'-method: need add tsk.reenable
namespace :assets |x1,x2| task :doit, :ext, :objdir |tsk, args| puts "#{tsk} called #{args.inspect}" tsk.reenable end end another problem: if parameters contains spaces. may trouble.
============== code generic generation of rule: (see comments)
namespace :assets3 |x1,x2| task :set, :ext, :objdir |tsk, args| @args = args @src = filelist["*.rb"] puts "#{tsk} set: #{@args.inspect}" #define rule, when extension set. rule ".min.#{@args[:ext]}" => lambda{ |objfile| find_source(objfile) } |t| puts "#{t} called #{@args.inspect}" end end task :doit |tsk| puts "#{tsk} called #{@args.inspect}" end def find_source(objfile) base = file.basename(objfile, ".min.#{@args[:ext]}") #if nothing found, rake abort 'can't convert nil string (typeerror)' #if return '' in case, 'don't know how build task 'test.min.js' (runtimeerror)' @src.find {|s| file.basename(s, ".#{@args[:ext]}") == base} || '' end end
Comments
Post a Comment