ruby - يعتمد - واجهة سطر الاوامر




كيفية تمرير الحجج سطر الأوامر لمهمة أشعل النار (12)

أثناء تمرير المعلمات ، يكون الخيار الأفضل هو ملف الإدخال ، يمكن أن يكون هذا التفوق json أو أي شيء تحتاجه ومن هناك قراءة هيكل البيانات والمتغيرات التي تحتاج إليها من ذلك بما في ذلك اسم المتغير كما هو الحاجة. يمكن أن يكون لقراءة ملف البنية التالية.

  namespace :name_sapace_task do
    desc "Description task...."
      task :name_task  => :environment do
        data =  ActiveSupport::JSON.decode(File.read(Rails.root+"public/file.json")) if defined?(data)
    # and work whit yoour data, example is data["user_id"]

    end
  end

مثال json

{
  "name_task": "I'm a task",
  "user_id": 389,
  "users_assigned": [389,672,524],
  "task_id": 3
}

إعدام

rake :name_task 

لدي مهمة أشعل النار التي تحتاج إلى إدراج قيمة في قواعد بيانات متعددة.

أود أن يمرر هذه القيمة في مهمة أشعل النار من سطر الأوامر ، أو من مهمة أشعل النار أخرى .

كيف يمكنني أن أفعل هذا؟


أردت فقط أن أتمكن من تشغيل:

$ rake some:task arg1 arg2

بسيط ، صحيح؟ (كلا!)

يدير Rake arg1 و arg2 كمهام ، ويحاول تشغيلها. لذلك نحن فقط إجهاض قبل أن يفعل.

namespace :some do
  task task: :environment do
    arg1, arg2 = ARGV

    # your task...

    exit
  end
end

خذ هذا ، بين قوسين!

إخلاء المسؤولية : أردت أن أكون قادرة على القيام بذلك في مشروع صغير جداً للحيوانات الأليفة. لا يقصد به استخدام "العالم الحقيقي" نظرًا لأنك خسرت القدرة على تنفيذ المهام المتسلسلة (مثل rake task1 task2 task3 ). المنظمة البحرية الدولية لا يستحق كل هذا العناء. فقط استخدم rake task[arg1,arg2] القبيحة rake task[arg1,arg2] .


أنا أحب بناء جملة "querystring" لتمرير الوسيطة ، خاصة عندما يكون هناك الكثير من الوسيطات التي سيتم تمريرها.

مثال:

rake "mytask[width=10&height=20]"

يجري "querystring":

width=10&height=20

تحذير: لاحظ أن بناء الجملة هو rake "mytask[foo=bar]" و NOT rake mytask["foo=bar"]

عند Rack::Utils.parse_nested_query داخل مهمة rake باستخدام Rack::Utils.parse_nested_query ، نحصل على Hash :

=> {"width"=>"10", "height"=>"20"}

(الشيء الرائع هو أنه يمكنك تمرير تجزئة ومصفوفات ، أكثر أدناه)

هذا هو كيفية تحقيق ذلك:

require 'rack/utils'

task :mytask, :args_expr do |t,args|
  args.with_defaults(:args_expr => "width=10&height=10")
  options = Rack::Utils.parse_nested_query(args[:args_expr])
end

في ما يلي مثال ممتد أكثر delayed_job_active_record_threaded مع Rails في ملفي delayed_job_active_record_threaded :

bundle exec rake "dj:start[ebooks[workers_number]=16&ebooks[worker_timeout]=60&albums[workers_number]=32&albums[worker_timeout]=120]"

تم تحليلها بنفس الطريقة المذكورة أعلاه ، مع تبعية بيئة (من أجل تحميل بيئة Rails)

namespace :dj do
  task :start, [ :args_expr ] => :environment do |t, args|
    # defaults here...
    options = Rack::Utils.parse_nested_query(args[:args_expr])  
  end
end

يعطي ما يلي في options

=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}

إذا كنت تريد تمرير الوسائط المسماة (على سبيل المثال باستخدام OptionParser القياسي) ، فيمكنك استخدام شيء كهذا:

$ rake user:create -- --user [email protected] --pass 123

لاحظ -- وهذا ضروري لتجاوز حجج Rake القياسية. يجب أن تعمل مع Rake 0.9.x ، <= 10.3.x.

لقد غيرت Newer Rake إعرابها عن -- والآن يجب عليك التأكد من عدم تمريرها إلى طريقة OptionParser#parse ، على سبيل المثال مع parser.parse!(ARGV[2..-1])

require 'rake'
require 'optparse'
# Rake task for creating an account

namespace :user do |args|
  desc 'Creates user account with given credentials: rake user:create'
  # environment is required to have access to Rails models
  task :create do
    options = {}
    OptionParser.new(args) do |opts|
      opts.banner = "Usage: rake user:create [options]"
      opts.on("-u", "--user {username}","User's email address", String) do |user|
        options[:user] = user
      end
      opts.on("-p", "--pass {password}","User's password", String) do |pass|
        options[:pass] = pass
      end
    end.parse!

    puts "creating user account..."
    u = Hash.new
    u[:email] = options[:user]
    u[:password] = options[:pass]
    # with some DB layer like ActiveRecord:
    # user = User.new(u); user.save!
    puts "user: " + u.to_s
    puts "account created."
    exit 0
  end
end

exit في النهاية سيحرص على عدم تفسير الحجج الإضافية كمهمة Rake.

كما يجب أن يعمل الاختصار للحجج:

 rake user:create -- -u [email protected] -p 123

عندما تبدو مثل أشعة أشعل النار هذا ، ربما حان الوقت للبحث عن أداة أخرى من شأنها أن تسمح هذا الخروج من مربع فقط.


بالإضافة إلى الإجابة عن طريق kch (لم أجد كيفية ترك تعليق على ذلك ، آسف):

لا يتعين عليك تحديد المتغيرات كمتغيرات ENV قبل الأمر rake . يمكنك فقط تعيينهم كالمعتاد معلمات سطر الأوامر مثل:

rake mytask var=foo

والوصول إلى تلك من ملف أشعلك كمتغيرات ENV مثل:

p ENV['var'] # => "foo"

خيار آخر شائع الاستخدام هو تمرير متغيرات البيئة. في ENV['VAR'] تقرأها عبر ENV['VAR'] ، ويمكنها تمريرها مباشرة قبل أمر rake ، مثل

$ VAR=foo rake mytask

في الواقع ردNick Desjardins الكمال. ولكن فقط للتعليم: يمكنك استخدام النهج القذر: باستخدام حجة ENV

task :my_task do
  myvar = ENV['myvar']
  puts "myvar: #{myvar}"
end 

rake my_task myvar=10
#=> myvar: 10

لتمرير الوسائط إلى المهمة الافتراضية ، يمكنك القيام بشيء كهذا. على سبيل المثال ، لنفترض أن "version" هو الوسيطة الخاصة بك:

task :default, [:version] => [:build]

task :build, :version do |t,args|
  version = args[:version]
  puts version ? "version is #{version}" : "no version passed"
end

ثم يمكنك الاتصال به على النحو التالي:

$ rake
no version passed

أو

$ rake default[3.2.1]
version is 3.2.1

أو

$ rake build[3.2.1]
version is 3.2.1

ومع ذلك ، لم أجد طريقة لتجنب تحديد اسم المهمة (افتراضي أو بناء) أثناء تمريرها في الوسائط. أحب أن أسمع إذا كان أي شخص يعرف من وسيلة.


لم أتمكن من معرفة كيفية تمرير الأفكار وأيضاً إلى: البيئة حتى انتهيت من ذلك:

namespace :db do
  desc 'Export product data'
  task :export, [:file_token, :file_path] => :environment do |t, args|
    args.with_defaults(:file_token => "products", :file_path => "./lib/data/")

       #do stuff [...]

  end
end

ثم اتصل على هذا النحو:

rake db:export['foo, /tmp/']

معظم الطرق المذكورة أعلاه لم تنجح بالنسبة لي ، ربما تم إيقافها في الإصدارات الأحدث. يمكن العثور على الدليل المحدث هنا: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks

يوجد هنا نسخ ولصق من الدليل:

task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
  # You can use args from here
end

استدعيه من هذا القبيل

bin/rake "task_name[value 1]" # entire argument string should be quoted

يمكنك تحديد وسيطات رسمية في أشعل النار بإضافة وسيطات رمز إلى استدعاء المهمة. فمثلا:

require 'rake'

task :my_task, [:arg1, :arg2] do |t, args|
  puts "Args were: #{args}"
end

task :invoke_my_task do
  Rake.application.invoke_task("my_task[1, 2]")
end

# or if you prefer this syntax...
task :invoke_my_task_2 do
  Rake::Task[:my_task].invoke(3, 4)
end

# a task with prerequisites passes its 
# arguments to it prerequisites
task :with_prerequisite, [:arg1, :arg2] => :my_task #<- name of prerequisite task

# to specify default values, 
# we take advantage of args being a Rake::TaskArguments object
task :with_defaults, :arg1, :arg2 do |t, args|
  args.with_defaults(:arg1 => :default_1, :arg2 => :default_2)
  puts "Args with defaults were: #{args}"
end

ثم من سطر الأوامر:

> rake my_task[1,2]
Args were: {:arg1=>"1", :arg2=>"2"}

> rake "my_task[1, 2]"
Args were: {:arg1=>"1", :arg2=>"2"}

> rake invoke_my_task
Args were: {:arg1=>"1", :arg2=>"2"}

> rake invoke_my_task_2
Args were: {:arg1=>3, :arg2=>4}

> rake with_prerequisite[5,6]
Args were: {:arg1=>"5", :arg2=>"6"}

> rake with_defaults
Args with defaults were: {:arg1=>:default_1, :arg2=>:default_2}

> rake with_defaults['x','y']
Args with defaults were: {:arg1=>"x", :arg2=>"y"}

كما هو موضح في المثال الثاني ، إذا كنت تريد استخدام مسافات ، فإن علامات الاقتباس حول اسم الهدف ضرورية للحفاظ على shell من فصل الوسائط في المساحة.

بالنظر إلى الكود في rake.rb ، يبدو أن rake لا يقوم بتحويل سلاسل المهام لاستخراج الوسيطات للمتطلبات الأساسية ، بحيث لا يمكنك القيام task :t1 => "dep[1,2]" . والطريقة الوحيدة لتعيين وسيطات مختلفة :invoke_my_task بشكل صريح ضمن إجراء المهمة التابعة ، كما في :invoke_my_task و :invoke_my_task_2 .

لاحظ أن بعض الأصداف (مثل zsh) تتطلب منك الهروب من الأقواس: rake my_task\['arg1'\]


desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
    puts args[:arg1]
end




command-line-arguments