Tôi có một nhiệm vụ cào cần chèn một giá trị vào nhiều cơ sở dữ liệu.
Tôi muốn chuyển giá trị này vào tác vụ cào từ dòng lệnh hoặc từ một tác vụ cào khác .
Tôi có thể làm cái này như thế nào?
Tôi có một nhiệm vụ cào cần chèn một giá trị vào nhiều cơ sở dữ liệu.
Tôi muốn chuyển giá trị này vào tác vụ cào từ dòng lệnh hoặc từ một tác vụ cào khác .
Tôi có thể làm cái này như thế nào?
Câu trả lời:
tùy chọn và phụ thuộc cần phải nằm trong mảng:
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
Sau đó
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"}
LƯU Ý: biến
task
là đối tượng tác vụ, không hữu ích lắm trừ khi bạn biết / quan tâm đến nội bộ Rake.
RAILS LƯU Ý:
Nếu chạy tác vụ từ đường ray, tốt nhất là tải trước môi trường bằng cách thêm
=> [:environment]
đó là cách để thiết lập các tác vụ phụ thuộc .
task :work, [:option, :foo, :bar] => [:environment] do |task, args|
puts "work", args
end
rake thing:work[1, 2, 3]
vì nó sẽ không hoạt động và bạn sẽ gặp lỗiDon't know how to build task
rake thing:work'[1,2,3]'
rake thing:work\[1,2,3\]
hoặc thế nàyrake 'thing:work[1,2,3]'
:environment
biểu tượng khỏi nhiệm vụ của mình. các ứng dụng đường ray có một: nhiệm vụ môi trường ...
t
có nghĩa là task
, tại sao không chỉ sử dụng task
làm tên param?
Bạn có thể chỉ định các đối số chính thức trong rake bằng cách thêm các đối số ký hiệu vào lệnh gọi tác vụ. Ví dụ:
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
Sau đó, từ dòng lệnh:
> cào my_task [1, sai] Các đối số là: {: arg1 => "1" ,: arg2 => "false"} của lớp Rake :: TaskArgument arg1 là: '1' của Chuỗi lớp arg2 là: 'false' của Chuỗi lớp > cào "my_task [1, 2]" Các đối số là: {: arg1 => "1" ,: arg2 => "2"} > rake invoke_my_task Các đối số là: {: arg1 => "1" ,: arg2 => "2"} > rake invoke_my_task_2 Các đối số là: {: arg1 => 3 ,: arg2 => 4} > rake with_prere condition [5,6] Các đối số là: {: arg1 => "5" ,: arg2 => "6"} > cào với_defaults Các đối số có mặc định là: {: arg1 =>: default_1 ,: arg2 =>: default_2} > rake with_defaults ['x', 'y'] Các đối số có giá trị mặc định là: {: arg1 => "x" ,: arg2 => "y"}
Như đã minh họa trong ví dụ thứ hai, nếu bạn muốn sử dụng khoảng trắng, các trích dẫn xung quanh tên đích là cần thiết để giữ cho shell không bị tách ra khỏi các đối số tại khoảng trắng.
Nhìn vào mã trong rake.rb , có vẻ như rake không phân tích các chuỗi nhiệm vụ để trích xuất các đối số cho các điều kiện tiên quyết, vì vậy bạn không thể làm được task :t1 => "dep[1,2]"
. Cách duy nhất để xác định các đối số khác nhau cho một điều kiện tiên quyết sẽ là gọi nó một cách rõ ràng trong hành động tác vụ phụ thuộc, như trong :invoke_my_task
và :invoke_my_task_2
.
Lưu ý rằng một số shell (như zsh) yêu cầu bạn thoát dấu ngoặc: rake my_task\['arg1'\]
WARNING: 'task :t, arg, :needs => [deps]' is deprecated. Please use 'task :t, [args] => [deps]' instead.
zsh: no matches found: ...
), vì vậy bạn cần thoát dấu ngoặc : rake my_task\['arg1'\]
. Từ robot
Ngoài việc trả lời bằng kch (tôi không tìm thấy cách để lại nhận xét cho điều đó, xin lỗi):
Bạn không phải chỉ định biến là ENV
biến trước rake
lệnh. Bạn chỉ có thể đặt chúng như các tham số dòng lệnh thông thường như thế:
rake mytask var=foo
và truy cập những người từ tệp rake của bạn dưới dạng các biến ENV như sau:
p ENV['var'] # => "foo"
p
có nghĩa là gì?
Nếu bạn muốn truyền các đối số có tên (ví dụ với tiêu chuẩn OptionParser
), bạn có thể sử dụng một cái gì đó như thế này:
$ rake user:create -- --user test@example.com --pass 123
lưu ý --
rằng, điều đó là cần thiết để bỏ qua các đối số Rake tiêu chuẩn. Nên làm việc với Rake 0.9.x , <= 10.3.x .
Rake mới hơn đã thay đổi phân tích cú pháp --
và bây giờ bạn phải đảm bảo rằng nó không được truyền cho OptionParser#parse
phương thức, ví dụ như vớiparser.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
ở cuối sẽ đảm bảo rằng các đối số phụ sẽ không được hiểu là nhiệm vụ Rake.
Ngoài ra các phím tắt cho các đối số nên hoạt động:
rake user:create -- -u test@example.com -p 123
Khi các kịch bản cào trông như thế này, có lẽ đã đến lúc tìm kiếm một công cụ khác cho phép điều này vượt ra ngoài.
--option-names
. Đề nghị duy nhất của tôi sẽ là sử dụng exit
thay abort
vì abort
sẽ để lại cho bạn mã trả về 1 cho trình bao. Nếu tác vụ cào là một phần của tập lệnh cấp cao hơn, thì phổ biến hơn là giả sử lối thoát khác không là một loại lỗi.
--
? Giống như chuyển các rake
đối số cho nhiệm vụ thực tế hoặc một cái gì đó? Thích task :my_task, :*args do |t, args|
hay sao?
{username}
ở đây để làm. Nó được sử dụng ở đâu? Tại sao nó không ở đó -u {username}
? Chúc mừng
10.4.1
và hoàn nguyên 10.4.2
. github.com/ruby/rake/commit/
Tôi đã tìm thấy câu trả lời từ hai trang web này: Net Maniac và Aimred .
Bạn cần có phiên bản> 0,8 cào để sử dụng kỹ thuật này
Mô tả nhiệm vụ cào bình thường là thế này:
desc 'Task Description'
task :task_name => [:depends_on_taskA, :depends_on_taskB] do
#interesting things
end
Để vượt qua các đối số, làm ba điều:
Để truy cập các đối số trong tập lệnh, sử dụng 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
Để gọi tác vụ này từ dòng lệnh, hãy truyền cho nó các đối số trong [] s
rake task_name['Hello',4]
sẽ xuất
Hello
Hello
Hello
Hello
và nếu bạn muốn gọi tác vụ này từ một tác vụ khác và truyền nó vào đối số, hãy sử dụng lệnh gọi
task :caller do
puts 'In Caller'
Rake::Task[:task_name].invoke('hi',2)
end
sau đó là lệnh
rake caller
sẽ xuất
In Caller
hi
hi
Tôi đã không tìm thấy một cách để vượt qua các đối số như là một phần của sự phụ thuộc, khi đoạn mã sau bị phá vỡ:
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.
Một tùy chọn khác thường được sử dụng là để vượt qua các biến môi trường. Trong mã của bạn, bạn đọc chúng thông qua ENV['VAR']
và có thể chuyển chúng ngay trước rake
lệnh, như
$ VAR=foo rake mytask
rake blah -- --these --go --to --a-program
(lưu ý --
để nói với rake rằng các công tắc của nó đã kết thúc), xem stackoverflow.com/questions/5086224/ Lỗi
Tôi không thể tìm ra cách vượt qua args và cả môi trường: cho đến khi tôi tìm ra cách này:
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
Và sau đó tôi gọi như thế này:
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]
Tôi chỉ muốn có thể chạy:
$ rake some:task arg1 arg2
Đơn giản phải không? (Không!)
Rake phiên dịch arg1
và arg2
như các nhiệm vụ, và cố gắng chạy chúng. Vì vậy, chúng tôi chỉ phá thai trước khi nó làm.
namespace :some do
task task: :environment do
arg1, arg2 = ARGV
# your task...
exit
end
end
Lấy đó, ngoặc!
Disclaimer : Tôi muốn có thể làm điều này trong một dự án thú cưng nhỏ. Không dành cho sử dụng "thế giới thực" vì bạn mất khả năng xâu chuỗi các tác vụ cào (tức là rake task1 task2 task3
). IMO không đáng Chỉ dùng cái xấu xí rake task[arg1,arg2]
.
_, arg1, arg2 = ARGV
như là đối số đầu tiên được coi là tên của nhiệm vụ cào. Nhưng đó exit
là một mẹo gọn gàng.
rake task[arg1,arg2] && rake task2 && rake task3
Không chắc chắn nếu điều đó ít xấu xí hơn rake task[arg1,arg2] task2 task3
. Có lẽ ít hiệu quả hơn mặc dù.
_, *args = ARGV
là hoàn hảo để nắm bắt tất cả các đối số tiếp theo! Cảm ơn đống!
Tôi sử dụng một đối số ruby thông thường trong tệp cào:
DB = ARGV[1]
sau đó tôi loại bỏ các tác vụ cào ở dưới cùng của tệp (vì rake sẽ tìm kiếm một tác vụ dựa trên tên đối số đó).
task :database_name1
task :database_name2
dòng lệnh:
rake mytask db_name
điều này cảm thấy sạch sẽ hơn với tôi so với var = foo ENV var và tác vụ tranh luận [blah, blah2].
còn sơ khai là một chút vui nhộn, nhưng không quá tệ nếu bạn chỉ có một vài môi trường là thiết lập một lần
dup
ở cuối: db = ARGV [1] .dup
db = ARGV[1].dup unless ARGV[1].nil?
để ngăn chặn ngoại lệ của một con số không.
Các cách để vượt qua đối số là chính xác trong câu trả lời ở trên. Tuy nhiên, để chạy tác vụ cào với các đối số, có một kỹ thuật nhỏ liên quan đến phiên bản mới hơn của đường ray
Nó sẽ hoạt động với rake "không gian tên: taskname ['argument1']"
Lưu ý các trích dẫn ngược trong khi chạy tác vụ từ dòng lệnh.
Để truyền đối số cho tác vụ mặc định, bạn có thể làm một cái gì đó như thế này. Ví dụ: nói "phiên bản" là đối số của bạn:
task :default, [:version] => [:build]
task :build, :version do |t,args|
version = args[:version]
puts version ? "version is #{version}" : "no version passed"
end
Sau đó, bạn có thể gọi nó như vậy:
$ rake
no version passed
hoặc là
$ rake default[3.2.1]
version is 3.2.1
hoặc là
$ rake build[3.2.1]
version is 3.2.1
Tuy nhiên, tôi chưa tìm được cách nào để tránh chỉ định tên tác vụ (mặc định hoặc bản dựng) trong khi truyền các đối số. Rất thích nghe nếu có ai biết một cách.
Tôi thích cú pháp "chuỗi truy vấn" để truyền đối số, đặc biệt là khi có rất nhiều đối số được truyền.
Thí dụ:
rake "mytask[width=10&height=20]"
"Chuỗi truy vấn" là:
width=10&height=20
Cảnh báo: lưu ý rằng cú pháp là rake "mytask[foo=bar]"
và KHÔNG rake mytask["foo=bar"]
Khi phân tích cú pháp bên trong tác vụ cào bằng Rack::Utils.parse_nested_query
, chúng ta nhận được Hash
:
=> {"width"=>"10", "height"=>"20"}
(Điều thú vị là bạn có thể vượt qua băm và mảng, bên dưới)
Đây là cách để đạt được điều này:
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
Đây là một ví dụ mở rộng hơn mà tôi đang sử dụng với Rails trong đá quý delay_job_active_record_threaded của mình :
bundle exec rake "dj:start[ebooks[workers_number]=16&ebooks[worker_timeout]=60&albums[workers_number]=32&albums[worker_timeout]=120]"
Phân tích cú pháp theo cách tương tự như trên, với sự phụ thuộc môi trường (để tải môi trường 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
Đưa ra những điều sau đây trong options
=> {"ebooks"=>{"workers_number"=>"16", "worker_timeout"=>"60"}, "albums"=>{"workers_number"=>"32", "worker_timeout"=>"120"}}
Nếu bạn không thể bận tâm để nhớ vị trí đối số là gì và bạn muốn làm gì đó như hàm băm đối số ruby. Bạn có thể sử dụng một đối số để truyền vào một chuỗi và sau đó regex chuỗi đó thành hàm băm tùy chọn.
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
Và trên dòng lệnh bạn nhận được.
$ 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
Hầu hết các phương pháp được mô tả ở trên không hiệu quả với tôi, có thể chúng không được dùng trong các phiên bản mới hơn. Hướng dẫn cập nhật có thể được tìm thấy ở đây: http://guides.rubyonrails.org/command_line.html#custom-rake-t task
một bản sao và dán ans từ hướng dẫn có ở đây:
task :task_name, [:arg_1] => [:pre_1, :pre_2] do |t, args|
# You can use args from here
end
Gọi nó như thế này
bin/rake "task_name[value 1]" # entire argument string should be quoted
Để chạy các tác vụ cào với kiểu đối số truyền thống:
rake task arg1 arg2
Và sau đó sử dụng:
task :task do |_, args|
puts "This is argument 1: #{args.first}"
end
Thêm bản vá sau của đá quý cào:
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
Trong khi truyền tham số, tùy chọn tốt hơn là một tệp đầu vào, đây có thể là excel một json hoặc bất cứ thứ gì bạn cần và từ đó đọc cấu trúc dữ liệu và các biến bạn cần từ đó bao gồm tên biến là cần thiết. Để đọc một tập tin có thể có cấu trúc sau.
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