سؤال

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

أرغب في تمرير هذه القيمة إلى مهمة أشعل النار من سطر الأوامر، أو من آخر مهمة أشعل النار.

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

هل كانت مفيدة؟

المحلول

يجب أن تكون الخيارات والتبعيات داخل المصفوفات:

namespace :thing do
  desc "it does a thing"
  task :work, [:option, :foo, :bar] do |task, args|
    puts "work", args
  end

  task :another, [:option, :foo, :bar] do |task, args|
    puts "another #{args}"
    Rake::Task["thing:work"].invoke(args[:option], args[:foo], args[:bar])
    # or splat the args
    # Rake::Task["thing:work"].invoke(*args)
  end

end

ثم

rake thing:work[1,2,3]
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}

rake thing:another[1,2,3]
=> another {:option=>"1", :foo=>"2", :bar=>"3"}
=> work: {:option=>"1", :foo=>"2", :bar=>"3"}

ملحوظة:عامل task هو كائن المهمة، وهو ليس مفيدًا جدًا إلا إذا كنت تعرف/تهتم بالعناصر الداخلية لـ Rake.

ملاحظة القضبان:

في حالة تشغيل المهمة من Rails، فمن الأفضل تحميل البيئة مسبقًا عن طريق إضافة => [:environment] وهي طريقة الإعداد متكل مهام.

  task :work, [:option, :foo, :bar] => [:environment] do |task, args|
    puts "work", args
  end

نصائح أخرى

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

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"}

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

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

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

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

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

rake mytask var=foo

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

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

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

$ rake user:create -- --user test@example.com --pass 123

لاحظ ال --, ، وهذا ضروري لتجاوز وسيطات 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 test@example.com -p 123

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

لقد وجدت الجواب من هذين الموقعين: صافي مهووس و ايمد.

يجب أن يكون لديك الإصدار> 0.8 من Rake لاستخدام هذه التقنية

الوصف الطبيعي لمهمة أشعل النار هو:

desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
  #interesting things
end

لتمرير الحجج، قم بثلاثة أشياء:

  1. أضف أسماء الوسيطات بعد اسم المهمة، مفصولة بفواصل.
  2. ضع التبعيات في النهاية باستخدام :needs => [...]
  3. مكان | T ، args | بعد القيام به.(t هو الكائن لهذه المهمة)

للوصول إلى الوسائط الموجودة في البرنامج النصي، استخدم args.arg_name

desc 'Takes arguments task'
task :task_name, :display_value, :display_times, :needs => [:depends_on_taskA, :depends_on_taskB] do |t, args|
  args.display_times.to_i.times do
    puts args.display_value
  end
end

لاستدعاء هذه المهمة من سطر الأوامر، قم بتمرير الوسيطات في []s

rake task_name['Hello',4]

سوف يخرج

Hello
Hello
Hello
Hello

وإذا كنت تريد استدعاء هذه المهمة من مهمة أخرى، وتمرير الوسائط لها، فاستخدم الاستدعاء

task :caller do
  puts 'In Caller'
  Rake::Task[:task_name].invoke('hi',2)
end

ثم الأمر

rake caller

سوف يخرج

In Caller
hi
hi

لم أجد طريقة لتمرير الوسائط كجزء من التبعية، حيث ينكسر الكود التالي:

task :caller => :task_name['hi',2]' do
   puts 'In Caller'
end

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

$ VAR=foo rake mytask

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

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

rake my_task myvar=10
#=> myvar: 10

وأنا لم أستطع معرفة كيفية تمرير وسائط وأيضا: البيئة حتى عملت هذا الخروج:

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/']
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
    puts args[:arg1]
end

وأردت فقط أن تكون قادرة على تشغيل:

$ rake some:task arg1 arg2

وبسيط، أليس كذلك؟ (كلا!)

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

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

    # your task...

    exit
  end
end

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

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

وأنا استخدم حجة روبي العادية في ملف أشعل النار:

DB = ARGV[1]

وبعد ذلك كعب بالمهام أشعل النار في الجزء السفلي من ملف (منذ أشعل النار سوف تبحث عن مهمة على أساس أن اسم الحجة).

task :database_name1
task :database_name2

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

rake mytask db_name

وهذا يشعر أنظف لي من فار = فو ENV فار وسائط مهمة [بلاه، blah2] حلول.
كعب هو قليلا jenky، ولكن لا بأس إذا لديك فقط عدد قليل من البيئات التي هي الإعداد لمرة واحدة

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

وانها ستعمل مع أشعل النار "مساحة الاسم: taskname [ 'argument1']"

وملاحظة علامات الاقتباس مقلوب في تشغيل المهمة من سطر الأوامر.

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

مثال:

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

"سلسلة الاستعلام" هي:

width=10&height=20

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

عند التحليل داخل مهمة أشعل النار باستخدام 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

فيما يلي مثال أكثر شمولاً أستخدمه مع Rails في ملفي late_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"}}

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

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

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

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

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

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

إذا كنت لا يمكن ازعجت أن نتذكر ما هو الموقف الحجة هو ما وتريد أن تفعل شيئا مثل تجزئة حجة روبي. يمكنك استخدام وسيطة واحدة لتمرير في سلسلة ثم REGEX هذه السلسلة إلى تجزئة الخيارات.

namespace :dummy_data do
  desc "Tests options hash like arguments"
  task :test, [:options] => :environment do |t, args|
    arg_options = args[:options] || '' # nil catch incase no options are provided
    two_d_array = arg_options.scan(/\W*(\w*): (\w*)\W*/)
    puts two_d_array.to_s + ' # options are regexed into a 2d array'
    string_key_hash = two_d_array.to_h
    puts string_key_hash.to_s + ' # options are in a hash with keys as strings'
    options = two_d_array.map {|p| [p[0].to_sym, p[1]]}.to_h
    puts options.to_s + ' # options are in a hash with symbols'
    default_options = {users: '50', friends: '25', colour: 'red', name: 'tom'}
    options = default_options.merge(options)
    puts options.to_s + ' # default option values are merged into options'
  end
end

وعلى سطر الأوامر التي تحصل عليها.

$ rake dummy_data:test["users: 100 friends: 50 colour: red"]
[["users", "100"], ["friends", "50"], ["colour", "red"]] # options are regexed into a 2d array
{"users"=>"100", "friends"=>"50", "colour"=>"red"} # options are in a hash with keys as strings
{:users=>"100", :friends=>"50", :colour=>"red"} # options are in a hash with symbols
{:users=>"100", :friends=>"50", :colour=>"red", :name=>"tom"} # default option values are merged into options

لتشغيل المهام أشعل النار مع نمط الحجج التقليدية:

rake task arg1 arg2

وبعد ذلك استخدام:

task :task do |_, args|
  puts "This is argument 1: #{args.first}"
end

واضافة التالية التصحيح من الأحجار الكريمة أشعل النار:

Rake::Application.class_eval do

  alias origin_top_level top_level

  def top_level
    @top_level_tasks = [top_level_tasks.join(' ')]
    origin_top_level
  end

  def parse_task_string(string) # :nodoc:
    parts = string.split ' '
    return parts.shift, parts
  end

end

Rake::Task.class_eval do

  def invoke(*args)
    invoke_with_call_chain(args, Rake::InvocationChain::EMPTY)
  end

end

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

  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

مثال سلمان

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

تحليل تنفيذ

rake :name_task 
مرخصة بموجب: CC-BY-SA مع الإسناد
لا تنتمي إلى StackOverflow
scroll top