217 votes

Comment passer des arguments dans une tâche Rake avec environnement dans Rails ?

Je suis capable de passer des arguments comme suit :

desc "Testing args"
task: :hello, :user, :message do |t, args|
  args.with_defaults(:message => "Thanks for logging on")
  puts "Hello #{args[:user]}. #{:message}"
end

Je suis également capable de charger l'environnement actuel pour une application Rails

desc "Testing environment"
task: :hello => :environment do 
  puts "Hello #{User.first.name}."
end

Ce que j'aimerais faire, c'est avoir la possibilité d'avoir des variables et un environnement

desc "Testing environment and variables"
task: :hello => :environment, :message do |t, args|
  args.with_defaults(:message => "Thanks for logging on")
  puts "Hello #{User.first.name}. #{:message}"
end

Mais ce n'est pas un appel de tâche valide. Quelqu'un sait-il comment je peux y parvenir ?

14 votes

Pouvez-vous s'il vous plaît mettre à jour pour accepter la nouvelle réponse d'Inger.

395voto

inger Points 4841

Juste pour faire suite à ce vieux sujet ; voici ce que je pense qu'un Rakefile actuel (depuis longtemps) devrait faire là. C'est une version améliorée et corrigée de la réponse gagnante actuelle (hgimenez) :

desc "Testing environment and variables"
task :hello, [:message]  => :environment  do |t, args|
  args.with_defaults(:message => "Thanks for logging on")
  puts "Hello #{User.first.name}. #{args.message}"   # Q&A above had a typo here : #{:message}
end

Voici comment l'invoquer ( http://guides.rubyonrails.org/v4.2/command_line.html#rake ) :

  rake "hello[World]" 

Pour des arguments multiples, il suffit d'ajouter leurs mots-clés dans le tableau de la déclaration de la tâche ( task :hello, [:a,:b,:c]... ), et les passer séparés par des virgules :

  rake "hello[Earth,Mars,Sun,Pluto]" 

Note : le nombre d'arguments n'est pas vérifié, donc la planète impaire est laissée de côté :)

39 votes

Cette réponse devrait être la réponse acceptée.

31 votes

Mec...rake me semble toujours si peu "ruby" pour moi. La plupart des choses dans Ruby votre première supposition est comment il fonctionne réellement. Cette syntaxe est juste bizarre. </rant>

0 votes

Je suis d'accord pour dire que ce n'est pas un déchet (<-sorry for the unusual syntax-) Sérieusement, je comprends votre préoccupation mais IMHO c'est juste une limitation des DSL internes : vous ne pouvez pas complètement redéfinir librement la syntaxe mais c'est toujours assez étonnant de voir jusqu'où vous pouvez aller (bien que ce ne soit pas un lisp). BTW, à quoi ressemblerait une API/DSL plus intuitive pour l'objectif ci-dessus ?

120voto

hgmnz Points 7239

TLDR ;

task :t, [args] => [deps] 

Réponse originale

Lorsque vous passez des arguments aux tâches rake, vous pouvez exiger l'environnement en utilisant l'option :needs. Par exemple :

desc "Testing environment and variables"
task :hello, :message, :needs => :environment do |t, args|
  args.with_defaults(:message => "Thanks for logging on")
  puts "Hello #{User.first.name}. #{args.message}"
end

Mis à jour selon le commentaire de @Peiniau ci-dessous

Quant à Rails > 3.1

task :t, arg, :needs => [deps] # deprecated

Veuillez utiliser

task :t, [args] => [deps]

13 votes

Notez que les documents les plus récents décrivent l'option :needs de cette façon : "Ce format est toujours pris en charge pour des raisons de compatibilité, mais son utilisation n'est pas recommandée." (Je ne mentionne ceci que pour les futurs navigateurs, car cela suggère qu'éventuellement :needs ne sera plus supporté. La section s'appelle "Format des paramètres de tâches dépréciés"...)

6 votes

Bug dans ce code : met "Hello #{User.first.name}. #{:message}" ... cela n'imprime pas "Thanks for logging on", juste "message". Correction : #{args.message} pour la dernière substition.

53 votes

Depuis Rails 3.1, 'task :t, arg, :needs => [deps]' est obsolète. Veuillez utiliser 'task :t, [args] => [deps]' à la place.

60voto

mikezter Points 1074

Par souci d'exhaustivité, voici l'exemple tiré de l'application docs mentionné ci-dessus :

   task :name, [:first_name, :last_name] => [:pre_name] do |t, args|
     args.with_defaults(:first_name => "John", :last_name => "Dough")
     puts "First name is #{args.first_name}"
     puts "Last  name is #{args.last_name}"
   end

Notes :

  • Vous pouvez omettre le #with_defaults appel, évidemment.
  • Vous devez utiliser un Array pour vos arguments, même s'il n'y en a qu'un seul.
  • Les conditions préalables ne doivent pas être un Array .
  • args est une instance de Rake::TaskArguments .
  • t est une instance de Rake::Task .

3 votes

Cela explique pourquoi args.empty? me donnait des résultats bizarres. args ressemble à un hash, mais c'est une Rake::TaskArguments . Donc, si vous voulez un comportement spécial lorsque aucun argument n'est passé, appelez #to_hash o #to_s avant de vérifier si args est vide.

21voto

Dogweather Points 2487

Une autre façon de procéder : utiliser les variables d'environnement du système d'exploitation. Avantages de cette approche :

  • Toutes les tâches dépendantes de rake obtiennent les options.
  • La syntaxe est beaucoup plus simple, elle ne dépend pas du DSL de rake qui est difficile à comprendre et qui change au fil du temps.

J'ai une tâche rake qui nécessite trois options de ligne de commande. Voici comment je l'invoque :

$ rake eaternet:import country=us region=or agency=multco

C'est très propre, simple, et juste la syntaxe bash, ce que j'aime. Voici ma tâche rake. Aussi très propre et sans magie :

task import: [:environment] do
  agency = agency_to_import
  puts "Importing data for #{agency}..."
  agency.import_businesses
end

def agency_to_import
  country_code = ENV['country'] or raise "No country specified"
  region_slug  = ENV['region']  or raise "No region specified"
  agency_slug  = ENV['agency']  or raise "No agency specified"
  Agency.from_slugs(country_code, region_slug, agency_slug)
end

Cet exemple particulier ne montre pas l'utilisation des dépendances. Mais si le :import tâche dépendait des autres, ils auraient également accès à ces options. Mais en utilisant la méthode normale des options de rake, ils ne le feraient pas.

12voto

Lonny Eachus Points 76

Bien que ces solutions fonctionnent, à mon avis, c'est trop compliqué.

De plus, si vous procédez de cette manière dans zsh, vous obtiendrez des erreurs si les parenthèses de votre tableau ne sont pas échappées avec '\'.

Je recommande d'utiliser le tableau ARGV, qui fonctionne bien, est beaucoup plus simple et est moins sujet aux erreurs. Par exemple

namespace :my_example do
  desc "Something"
  task :my_task => :environment do
    puts ARGV.inspect
  end
end

entonces

rake my_example:my_task 1 2 3

#=>  ["my_example:my_task", "1", "2", "3"]

La seule chose que vous devez garder à l'esprit est que ARGV[0] est le nom du processus, donc utilisez uniquement ARGV[1..-1].

Je me rends compte qu'à proprement parler, cette solution ne répond pas à la question, car elle n'utilise pas l'environnement comme élément de la solution. Mais le PO n'a pas indiqué pourquoi il a inclus cette stipulation, qui pourrait donc s'appliquer à son cas d'utilisation.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X