2011-07-03 6 views
1

Je souhaite utiliser la tâche Rake suivante pour plusieurs répertoires. Et chaque répertoire aurait besoin de constantes légèrement différentes définies. Comment puis-je gérer cela et rester sec?Tâche Rake flexible

namespace :assets do 
    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 do 
    rm_f OBJ 
    end  

    desc "Remove #{LIBFILE}" 
    task :clobber do 
    rm_f LIBFILE 
    end 

    file LIBFILE => OBJ do 
    sh "cat #{OBJ} >> #{LIBFILE}" 
    end 

    rule ".min.#{EXT}" => lambda{ |objfile| find_source(objfile) } do |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 

Répondre

1

Avec votre aide, j'ai enfin compris. Voici ce qui fonctionne pour moi jusqu'à présent:

namespace :assets do 
    task :set, [:ext, :objdir] do |t, args| 
    @ext = args.ext 
    @objdir = args.objdir 
    @bundle = "#{@objdir}/bundle.#{@ext}" 
    @src = FileList["#{@objdir}/*.#{@ext}"].select {|file| !file.match(/\.min\.#{@ext}|#{Regexp.escape(@bundle)}/)} 
    @min = @src.collect {|fn| File.join(@objdir, File.basename(fn).ext("min.#{@ext}"))} 

    Rake::Task.define_task 'assets:build' => @bundle 

    Rake::FileTask.define_task @bundle => @min do 
     sh "cat #{@min} > #{@bundle}" 
    end 

    Rake::Task.create_rule ".min.#{@ext}" => lambda{ |objfile| find_source(objfile) } do |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 
    end 

    desc "Remove minified files" 
    task :clean do 
    rm_f @min 
    end  

    desc "Remove bundle" 
    task :clobber do 
    rm_f @bundle 
    end 

    def find_source(objfile) 
    base = File.basename(objfile, ".min.#{@ext}") 
    @src.find {|s| File.basename(s, ".#{@ext}") == base} 
    end 
end 
3

Vous devez d'abord remplacer les constantes par des variables. Le prochain problème consiste à définir les variables. La tâche peut obtenir des variables.

Exemple:

namespace :assets do |x1,x2| 
    task :doit, :ext, :objdir do |tsk, args| 
    puts tsk 
    p args 
    end 
end 

Vous pouvez l'appeler avec:

rake assets:doit[js,objdir] 

Résultat:

assets:doit called with {:ext=>"js", :objdir=>"objdir"} 

Si vous voulez éviter de définir les variables pour chacun de votre tâche, vous pouvez ajouter une tâche 'set':

namespace :assets2 do |x1,x2| 
    task :set, :ext, :objdir do |tsk, args| 
    @args = args 
    puts "#{tsk} set: #{@args.inspect}" 
    end 
    task :doit do |tsk| 
    puts "#{tsk} called with #{@args.inspect}" 
    end 
end 

Appel: actifs2 râteau: set [js, objdir] actifs2: doIT

Résultat:

assets2:set set: {:ext=>"js", :objdir=>"objdir"} 
assets2:doit called with {:ext=>"js", :objdir=>"objdir"} 

Au lieu de définir tous les paramètres, vous pouvez définir un fichier de configuration.

Il y a un inconvénient. La tâche suivante ne fonctionnerait pas:

rake assets:doit[js,objdir] assets:doit[c,objdir2] 

actifs: doit être appelée une seule fois. le deuxième appel est ignoré, la tâche est déjà exécutée. il n'y a pas de contrôle des paramètres différents (une solution pour ceci, vous pourriez peut-être réinitialiser la tâche)

Edit: J'ai trouvé et testé un « reset 'méthode: Vous avez juste besoin d'ajouter tsk.reenable

namespace :assets do |x1,x2| 
    task :doit, :ext, :objdir do |tsk, args| 
    puts "#{tsk} called with #{args.inspect}" 
    tsk.reenable 
    end 
end 

Un autre problème: Si vos paramètres contiennent des espaces. vous pourriez avoir des problèmes.

============== Code pour la génération générique de règle: (voir commentaires)

namespace :assets3 do |x1,x2| 
    task :set, :ext, :objdir do |tsk, args| 
    @args = args 
    @src = FileList["*.rb"] 

    puts "#{tsk} set: #{@args.inspect}" 

    #Define rule, when extension is set. 
    rule ".min.#{@args[:ext]}" => lambda{ |objfile| find_source(objfile) } do |t| 
     puts "#{t} called with #{@args.inspect}" 
    end 

    end 

    task :doit do |tsk| 
    puts "#{tsk} called with #{@args.inspect}" 
    end 

    def find_source(objfile) 
    base = File.basename(objfile, ".min.#{@args[:ext]}") 
    #If nothing is found, rake will abort with 'can't convert nil into String (TypeError)' 
    #If I return '' in this case, I get 'Don't know how to build task 'test.min.js' (RuntimeError)' 
    @src.find {|s| File.basename(s, ".#{@args[:ext]}") == base} || '' 
    end 

end 
+0

Merci pour l'aide, je grok ce que vous obtenez. J'ai essayé, mais ça ne semble pas fonctionner. La tâche 'file' ne semble pas correctement définie de cette façon, et la tâche' build' n'obtient pas la dépendance définie. –

+0

Je reçois cette erreur: 'Dépendance circulaire détectée: TOP => assets: build => =>' –

+0

Il semble que les variables ne sont disponibles que dans la définition d'une tâche. –