A set of rake tasks of a .rake file are structured as follows
task :process_data => :environment do
CSV.foreach("scores.tsv", :col_sep => "\t", headers: true) do |row|
begin
[...]
repeated_method_a
ad-hoc_method
repeated_method_b
rescue StandardError => e
end
end
end
How should this rake file be structured to process sub-methods, such as:
def repeated_method_a
do_its_thing
end
You can simply add it under your task in the same file, so you have this:
task :process_data => :environment do
CSV.foreach("scores.tsv", :col_sep => "\t", headers: true) do |row|
begin
[...]
repeated_method_a
ad-hoc_method
repeated_method_b
rescue StandardError => e
end
end
end
def repeated_method_a
do_its_thing
end
Related
I'm trying to import users avatar from a CSV and attach to the users with ActiveStorage.
I've created a rake task for this, but it's not working (and do not throws any error). In my CSV there are only 2 fields: email and avatar (avatar is the url to the file, that is on another server).
This is the task:
require 'csv'
namespace :import do
desc "Import avatars to users from CSV"
task avatars: :environment do
filename = File.join Rails.root, "avatars.csv"
CSV.foreach(filename, headers: true, col_sep: ";", header_converters: :symbol) do |row|
User.find_by(email: row[:email]) do |u|
u.avatar.attach(URI.parse(row[:avatar]).open)
end
end
end
end
Any advice?
Thanks for your help.
Have you tried to catch the any exception and print the problem in the console?
Something like that:
require 'csv'
namespace :import do
desc "Import avatars to users from CSV"
task avatars: :environment do
begin
filename = File.join Rails.root, "avatars.csv"
CSV.foreach(filename, headers: true, col_sep: ";", header_converters: :symbol) do |row|
User.find_by(email: row[:email]) do |u|
u.avatar.attach(URI.parse(row[:avatar]).open)
end
end
rescue StandardError => e
logger = Logger.new(STDOUT)
logger.error e.message
logger.error e.backtrace.join("\n")
end
end
end
Also, are you sure you have users with that email?
I want to import users with a CSV file so I put this code in lib/task/import.rake :
require 'csv'
task :import => :environment do
CSV.foreach('db/test.csv', :headers => true) do |row|
UserManager::User.create!(row.hash)
end
end
Here is my CSV test file :
surname;name;email;password;password_confirmation
test;test;test#exemple.fr;pass;pass
And when I run rake import I get this error :
When assigning attributes, you must pass a hash as an argument.
Why did I get this error ?
To sum up the comment of Pavan and the solution of gunn, your code should be:
require 'csv'
task :import => :environment do
CSV.foreach('db/test.csv', :headers => true, col_sep: ';') do |row|
UserManager::User.create!(row.to_hash)
end
end
Those variables aren't comma separated, they're semicolon separated. So:
CSV.foreach('db/test.csv', headers: true, col_sep: ";")
I think it should be
require 'csv'
task :import => :environment do
CSV.foreach('db/test.csv', :headers => true) do |row|
UserManager::User.create!(row.to_hash)
end
end
row.hash will return an integer
Use this
require 'csv'
CSV.foreach(file.path, headers: false) do |row|
user_hash = {}
user_hash = {"surname"=> name,"last_name"=> last_name } #key value
User.create!(user_hash)
end
end
Try this ............
require 'csv'
#file with full path
file = "#{Rails.root}/public/file_name.csv"
#Reading file
user_file = CSV.read(file, :headers => true)
#Creating User
user = UserManager::User.where(:email => user_file['email']).first_or_create
if user.present?
user.name = user_file['email']
#Same other data ......
user.save!
end
Hope this will work for you.
I have a rake task like this:
task :update_all => :environment do
codes = get_all_codes
codes.each{ |code| find_or_create_from_my_data(code) }
end
Sometimes the update fails, so I want to know with which code failed.
For that I wrote like this:
task :update_all => :environment do
begin
codes = get_all_codes
#code
codes.each{ |code| #code = code; find_or_create_from_my_data(code) }
rescue
p #code
end
end
It works fine, but I think it's a bit redundant. How can I write more effectively?
the e.message will display for you which code failed and why
task :update_all => :environment do
codes = get_all_codes
codes.each{ |code| find_or_create_from_my_data(code) }
rescue => e
puts "(#{e.message})"
end
How about this:
task :update_all => :environment do
get_all_codes.each do |code|
begin
find_or_create_from_my_data(code)
rescue
p code
end
end
end
This way, even if one code fails, it will print it out and move on to the other ones instead of aborting early.
I have a rake task and CSV files that I need to process; they are located in sub-directory of the lib\tasks directory:
\foo
one.csv
two.csv
...
foo.rake
The task:
task foo: :environment do
# for each file in directory
Dir.foreach("./*.csv") do |file| # not valid
# process CSV file's content
CSV.foreach(file, {:headers => true, :col_sep => ";"}) do |row|
...
end
end # Dir
end # task
How do I references files that are relative to the rake task?
I got to thinking about this more and I think combining File.join and Dir.glob will allow you to process all your csv files:
require "csv"
foo_dir = File.join(Rails.root, "lib", "tasks", "foo")
task foo: :environment do
# for each file in directory
Dir.glob(foo_dir + "/*.csv") do |csv_file|
# process CSV file's content
CSV.foreach(csv_file, {:headers => true, :col_sep => ";"}) do |row|
#...
end
end # Dir
end # task
EDIT: As #craig pointed out in the comment below, this can be accomplished more succinctly by using File.dirname and __FILE__:
require "csv"
task foo: :environment do
# for each file in directory
Dir.glob(File.dirname(__FILE__) + "/*.csv").each do |file|
# process CSV file's content
CSV.foreach(csv_file, {:headers => true, :col_sep => ";"}) do |row|
#...
end
end # Dir
end # task
How do i find out if the database exists from within a rake task?
that is, i'd like to do something like:
task :drop_and_create => :environment do
Rails.env = "development"
if (db_exists?)
Rake::Task["db:drop"].invoke
end
Rake::Task["db:create"].invoke
#more stuff...
end
how do i write the db_exists? condition?
How about instead doing a begin/rescue:
task :drop_and_create => :environment do
Rails.env = "development"
if (db_exists?)
begin
Rake::Task["db:drop"].invoke
rescue Exception => e
logger.debug("Error:#{e}")
Rake::Task["db:create"].invoke
#more stuff...
end
task :drop_and_create => :environment do
Rails.env = "development"
Rake::Task["db:reset"].invoke
#more stuff...
end