Saya punya tugas menyapu yang perlu memasukkan nilai ke beberapa basis data.
Saya ingin meneruskan nilai ini ke tugas menyapu dari baris perintah, atau dari tugas menyapu lain .
Bagaimana saya bisa melakukan ini?
Saya punya tugas menyapu yang perlu memasukkan nilai ke beberapa basis data.
Saya ingin meneruskan nilai ini ke tugas menyapu dari baris perintah, atau dari tugas menyapu lain .
Bagaimana saya bisa melakukan ini?
Jawaban:
opsi dan dependensi harus ada di dalam array:
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
Kemudian
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"}
CATATAN: variabel
task
adalah objek tugas, tidak sangat membantu kecuali Anda tahu / peduli tentang Rake internal.
CATATAN KERETA API:
Jika menjalankan tugas dari rails, yang terbaik untuk preload lingkungan dengan menambahkan
=> [:environment]
yang merupakan cara untuk mengatur tugas yang tergantung .
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
rake thing:work[1, 2, 3]
karena tidak akan berhasil dan Anda akan mendapatkan kesalahanDon't know how to build task
rake thing:work'[1,2,3]'
rake thing:work\[1,2,3\]
rake 'thing:work[1,2,3]'
:environment
simbol dari tugas Anda. aplikasi rel memiliki: tugas lingkungan ...
t
artinya task
, mengapa tidak hanya menggunakan task
sebagai nama param?
Anda bisa menentukan argumen formal di rake dengan menambahkan argumen simbol ke panggilan tugas. Sebagai contoh:
require 'rake'
task :my_task, [:arg1, :arg2] do |t, args|
puts "Args were: #{args} of class #{args.class}"
puts "arg1 was: '#{args[:arg1]}' of class #{args[:arg1].class}"
puts "arg2 was: '#{args[:arg2]}' of class #{args[:arg2].class}"
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
Kemudian, dari baris perintah:
> rake my_task [1, false] Argumennya adalah: {: arg1 => "1",: arg2 => "false"} kelas Rake :: TaskArguments arg1 adalah: '1' dari String kelas arg2 adalah: 'false' dari String kelas > rake "my_task [1, 2]" Argumennya adalah: {: arg1 => "1",: arg2 => "2"} > rake invoke_my_task Argumennya adalah: {: arg1 => "1",: arg2 => "2"} > rake invoke_my_task_2 Argumennya adalah: {: arg1 => 3,: arg2 => 4} > rake with_prerequisite [5,6] Argumennya adalah: {: arg1 => "5",: arg2 => "6"} > rake with_defaults Argumen dengan default adalah: {: arg1 =>: default_1,: arg2 =>: default_2} > rake with_defaults ['x', 'y'] Argumen dengan default adalah: {: arg1 => "x",: arg2 => "y"}
Seperti yang ditunjukkan dalam contoh kedua, jika Anda ingin menggunakan spasi, tanda kutip di sekitar nama target diperlukan untuk menjaga shell agar tidak memecah argumen di spasi.
Melihat kode di rake.rb , tampaknya rake tidak menguraikan string tugas untuk mengekstraksi argumen untuk prasyarat, jadi Anda tidak bisa melakukannya task :t1 => "dep[1,2]"
. Satu-satunya cara untuk menentukan argumen yang berbeda untuk prasyarat adalah dengan memanggilnya secara eksplisit dalam aksi tugas dependen, seperti pada :invoke_my_task
dan :invoke_my_task_2
.
Perhatikan bahwa beberapa cangkang (seperti zsh) mengharuskan Anda untuk keluar dari kurung: rake my_task\['arg1'\]
WARNING: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
zsh: no matches found: ...
), sehingga Anda perlu untuk melarikan diri kurung: rake my_task\['arg1'\]
. Dari robots.thoughtbot.com/post/18129303042/…
Selain menjawab dengan kch (saya tidak menemukan cara untuk meninggalkan komentar itu, maaf):
Anda tidak harus menentukan variabel sebagai ENV
variabel sebelum rake
perintah. Anda bisa mengaturnya sebagai parameter baris perintah seperti biasa:
rake mytask var=foo
dan akses yang dari file rake Anda sebagai variabel ENV seperti:
p ENV['var'] # => "foo"
p
artinya?
Jika Anda ingin memberikan argumen bernama (misalnya dengan standar OptionParser
), Anda dapat menggunakan sesuatu seperti ini:
$ rake user:create -- --user test@example.com --pass 123
perhatikan --
, itu perlu untuk melewati argumen Rake standar. Harus bekerja dengan Rake 0.9.x , <= 10.3.x .
Rake yang lebih baru telah mengubah penguraiannya --
, dan sekarang Anda harus memastikan itu tidak lolos ke OptionParser#parse
metode, misalnya denganparser.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
pada akhirnya akan memastikan bahwa argumen tambahan tidak akan ditafsirkan sebagai tugas Rake.
Juga jalan pintas untuk argumen harus berfungsi:
rake user:create -- -u test@example.com -p 123
Ketika skrip rake terlihat seperti ini, mungkin sudah waktunya untuk mencari alat lain yang akan memungkinkan ini keluar dari kotak.
--option-names
. Saya hanya saran akan menggunakan exit
daripada abort
sebagai abort
akan meninggalkan Anda dengan kode kembali 1 ke shell. Jika tugas menyapu adalah bagian dari skrip tingkat yang lebih tinggi itu lebih umum untuk menganggap keluar tidak nol adalah beberapa jenis kesalahan.
--
? Suka menyampaikan rake
argumen ke tugas aktual atau sesuatu? Suka task :my_task, :*args do |t, args|
atau apalah?
{username}
sini. Di mana itu digunakan? Kenapa tidak ada di sana -u {username}
? Cheers
Saya telah menemukan jawaban dari dua situs web ini: Net Maniac dan Aimred .
Anda harus memiliki versi> 0.8 rake untuk menggunakan teknik ini
Deskripsi tugas menyapu normal adalah ini:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Untuk menyampaikan argumen, lakukan tiga hal:
Untuk mengakses argumen dalam skrip, gunakan 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
Untuk memanggil tugas ini dari baris perintah, berikan argumen di [] s
rake task_name['Hello',4]
akan menampilkan
Hello
Hello
Hello
Hello
dan jika Anda ingin memanggil tugas ini dari tugas lain, dan meneruskannya argumen, gunakan invoke
task :caller do
puts 'In Caller'
Rake::Task[:task_name].invoke('hi',2)
end
lalu perintahnya
rake caller
akan menampilkan
In Caller
hi
hi
Saya belum menemukan cara untuk meneruskan argumen sebagai bagian dari dependensi, karena kode berikut rusak:
task :caller => :task_name['hi',2]' do
puts 'In Caller'
end
'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
Pilihan lain yang umum digunakan adalah untuk melewatkan variabel lingkungan. Dalam kode Anda, Anda membacanya melalui ENV['VAR']
, dan dapat mengirimkannya tepat sebelum rake
perintah, seperti
$ VAR=foo rake mytask
rake blah -- --these --go --to --a-program
(perhatikan --
untuk memberi tahu rake bahwa switch-nya telah berakhir), lihat stackoverflow.com/questions/5086224/…
Saya tidak tahu bagaimana cara melewatkan argumen dan juga: lingkungan sampai saya menyelesaikannya:
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
Dan kemudian saya sebut seperti ini:
rake db:export['foo, /tmp/']
desc 'an updated version'
task :task_name, [:arg1, :arg2] => [:dependency1, :dependency2] do |t, args|
puts args[:arg1]
end
rake task_name[hello, world]
Saya hanya ingin bisa berlari:
$ rake some:task arg1 arg2
Sederhana bukan? (Nggak!)
Rake penafsiran arg1
dan arg2
sebagai tugas, dan mencoba menjalankannya. Jadi kita batalkan saja.
namespace :some do
task task: :environment do
arg1, arg2 = ARGV
# your task...
exit
end
end
Ambillah itu, kurung!
Penafian : Saya ingin dapat melakukan ini dalam proyek hewan peliharaan yang cukup kecil. Tidak dimaksudkan untuk penggunaan "dunia nyata" karena Anda kehilangan kemampuan untuk melakukan tugas menyapu (yaitu rake task1 task2 task3
). IMO tidak sepadan. Cukup gunakan yang jelek rake task[arg1,arg2]
.
_, arg1, arg2 = ARGV
sebagai argumen pertama yang dilihat sebagai nama tugas menyapu. Tapi itu exit
trik yang rapi.
rake task[arg1,arg2] && rake task2 && rake task3
Tidak yakin apakah itu kurang jelek dari itu rake task[arg1,arg2] task2 task3
. Mungkin kurang efisien.
_, *args = ARGV
sempurna untuk menangkap semua argumen selanjutnya! Terima kasih banyak!
Saya menggunakan argumen ruby biasa dalam file rake:
DB = ARGV[1]
kemudian saya mematikan tugas rake di bagian bawah file (karena rake akan mencari tugas berdasarkan nama argumen itu).
task :database_name1
task :database_name2
garis komando:
rake mytask db_name
ini terasa lebih bersih bagi saya daripada solusi var = foo ENV var dan args [blah, blah2].
rintisannya sedikit jenky, tetapi tidak terlalu buruk jika Anda hanya memiliki beberapa lingkungan yang merupakan pengaturan satu kali
dup
di akhir: db = ARGV [1] .dup
db = ARGV[1].dup unless ARGV[1].nil?
untuk mencegah pengecualian duping nol.
Cara menyampaikan argumen sudah benar dalam jawaban di atas. Namun untuk menjalankan tugas menyapu dengan argumen, ada sedikit teknis yang terlibat dalam versi rel yang lebih baru
Ini akan bekerja dengan rake "namespace: taskname ['argument1']"
Perhatikan kutipan terbalik dalam menjalankan tugas dari baris perintah.
Untuk meneruskan argumen ke tugas default, Anda dapat melakukan sesuatu seperti ini. Misalnya, katakan "versi" adalah argumen Anda:
task :default, [:version] => [:build]
task :build, :version do |t,args|
version = args[:version]
puts version ? "version is #{version}" : "no version passed"
end
Maka Anda dapat menyebutnya seperti ini:
$ rake
no version passed
atau
$ rake default[3.2.1]
version is 3.2.1
atau
$ rake build[3.2.1]
version is 3.2.1
Namun, saya belum menemukan cara untuk menghindari menentukan nama tugas (default atau build) saat menyampaikan argumen. Akan sangat senang mendengar jika ada yang tahu cara.
Saya suka sintaks "querystring" untuk argumen yang lewat, terutama ketika ada banyak argumen yang harus disampaikan.
Contoh:
rake "mytask[width=10&height=20]"
The "querystring" adalah:
width=10&height=20
Peringatan: perhatikan bahwa sintaksnya adalah rake "mytask[foo=bar]"
dan TIDAK rake mytask["foo=bar"]
Ketika diuraikan di dalam tugas menyapu menggunakan Rack::Utils.parse_nested_query
, kita mendapatkan Hash
:
=> {"width"=>"10", "height"=>"20"}
(Yang keren adalah Anda bisa melewati hash dan array, lebih lanjut di bawah)
Inilah cara mencapai ini:
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
Berikut adalah contoh yang lebih luas yang saya gunakan dengan Rails di blog saya permata menunda_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]"
Diurai dengan cara yang sama seperti di atas, dengan ketergantungan lingkungan (untuk memuat lingkungan 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
Memberi yang berikut di options
=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}
Jika Anda tidak dapat diganggu untuk mengingat apa posisi argumen untuk apa dan Anda ingin melakukan sesuatu seperti hash argumen ruby. Anda bisa menggunakan satu argumen untuk meneruskan string dan kemudian regex string itu menjadi hash opsi.
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
Dan di baris perintah Anda dapatkan.
$ 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
Sebagian besar metode yang dijelaskan di atas tidak bekerja untuk saya, mungkin mereka sudah usang dalam versi yang lebih baru. Panduan terbaru dapat ditemukan di sini: http://guides.rubyonrails.org/command_line.html#custom-rake-tasks
copy dan paste ans dari panduan ada di sini:
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
Panggil seperti ini
bin/rake "task_name[value 1]" # entire argument string should be quoted
Untuk menjalankan tugas menyapu dengan gaya argumen tradisional:
rake task arg1 arg2
Dan kemudian gunakan:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Tambahkan sepetak permata menyapu berikut:
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
Ketika melewati parameter, pilihan yang lebih baik adalah file input, dapatkah ini menjadi excel json atau apa pun yang Anda butuhkan dan dari sana baca struktur data dan variabel yang Anda perlukan dari itu termasuk nama variabel sebagaimana kebutuhan. Untuk membaca file dapat memiliki struktur berikut.
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