How to use File.open inside a Rails Rake task? - ruby-on-rails

I need to create a recurring task that creates (or edits) product records from an external text file. From inside irb:
>> f = File.open(<filename>) # file in same directory path
No issues.
But when pasted into a Rake task file, the script always bombs "File not found". (Rails 3.1, Ubuntu.)
namespace :sap do
desc "uploads data from raw SAP file"
task :upload => :environment do
f = File.open("sap_pnlist_20111010a.csv")
records = f.readlines
records.each {|row|
... etc etc ...
}
end
end
Suggestions?

If the file is somewhere inside your Rails root, use
Rails.root.join('grandparent_dir', 'parent_dir', 'file.txt')
If the file is not in your Rails root, you must give it the full path.

Related

How to integrate my own scraper in Rails app?

I have just created a Rails app with a model app/models/post.rb and have written a scraper scrapers/base_scraper.rb (class BaseScraper) that collect data from the target site to the hash variable data. Now I want to insert values of data into the Post model. How to do it properly in Rails? I have heard smth about Rake but have no idea how to utilize it properly. Help me please!
Assuming that data stores just one post and that each of the key stored in the datahash are valid Post fields (column_name), you can do simply this:
Post.create(data)
If you want to launch the whole process from console, you can create a rake task under lib/tasks directory of your process with the following:
# scraper.rake
namespace :scraper do
desc "Run scraper"
task :run => :environment do
data = BaseScraper.your_collect_data_class_method
Post.create(data) if data
end
end
task :default => 'scraper:run'
And then run it from console as a rake task with rake scraper
Of course I also assume that scrapers dir is in your Rails load path.
If not, add it to your application.rbfile.
# application.rb
...
module YourApp
class Application < Rails::Application
...
config.autoload_paths += Dir["#{config.root}/scrapers/"]
...
end
end

Rails Generate Custom Rakefile

I'm working on a project that is migrating data from a customers old_busted DB into rails objects to be worked on later. Similarly, I need to convert these objects into a CSV and upload it to a neutral FTP (this is to allow a coworker to build the example pages through Sugar CRM). I've created rake files to do all of this, and it was successful. Now, I'm going to continue this process for each object that I create in rails (relative to the previous DB) and, best case, wanted these generated when I run rake generate scaffold <object>.
Here is my import rake:
desc "Import Clients from db"
task :get_busted_clients => [:environment] do
#old_clients = Busted::Client.all
#old_clients.each do |row|
#client = Client.new();
#client.client_id = row.NUMBER
#client.save
end
end
Here is my CSV convert/FTP upload rake:
desc "Exports db's to local CSV and uploads them to FTP"
task :export_clients_CSV => [:environment] do
# Required libraries for CSV read/write and NET/FTP IO #
require 'csv'
require 'net/ftp'
# Pull all Editor objects into clients for reading #
clients = Client.all
puts "Creating CSV file for <Clients> and updating column names..."
# Open a new CSV file that uses the column headers from Client #
CSV.open("clients.csv", "wb",
:write_headers => true, :headers => Client.column_names) do |csv|
puts "--Loading each entry..."
# Load all entries from Client into the CSV file row by row #
clients.each do |client|
# This line specifically puts the attributes in the rows WITH RESPECT TO#
# THE COLUMNS
csv << client.attributes.values_at(*Client.column_names)
end
puts "--Done loading each entry..."
end
puts "...Data populated. Finished bulding CSV. Closing File."
puts "------------------------"
# Upload CSV File to FTP server by requesting new FTP connection, assigning credentials
# and informing the client what file to look for and what to name it
puts "Uploading <Clients>..."
ftp = Net::FTP.new('192.168.xxx.xxx')
ftp.login(user = "user", passwd = "passwd")
ftp.puttextfile("clients.csv", "clients.csv")
ftp.quit()
puts "...Finished."
end
I ran rake generate g get_busted and put this in my get_busted_generator.rb:
class GetBustedGenerator < Rails::Generators::NamedBase
source_root File.expand_path('../templates', __FILE__)
def generate_get_busted
copy_file "getbusted.rake", "lib/tasks/#{file_name}.rake"
end
end
After that, I got lost. I can't find anything on templating a rake file or the syntax included to do so.
Rails has been a recent endeavor and I may be overlooking something in terms of design of the solution to my problem.
TL;DR: Is templating a rake file a bad thing? Solution alternatives? If not, whats the syntax for generating either script custom to the object (or point me in the direction, please).

Adding a custom seed file

I want to populate a new feature with dummy data, but don't want to use the db/seeds.rb file as it already has seeds other data irrelevant for this feature.
To run the default seeds.rb file, you run the command rake db:seed.
If I create a file in the db directory called seeds_feature_x.rb, what would the rake command look like to run (only) that file?
Start by creating a separate directory to hold your custom seeds – this example uses db/seeds. Then, create a custom task by adding a rakefile to your lib/tasks directory:
# lib/tasks/custom_seed.rake
namespace :db do
namespace :seed do
Dir[Rails.root.join('db', 'seeds', '*.rb')].each do |filename|
task_name = File.basename(filename, '.rb')
desc "Seed " + task_name + ", based on the file with the same name in `db/seeds/*.rb`"
task task_name.to_sym => :environment do
load(filename) if File.exist?(filename)
end
end
end
end
This rakefile accepts the name of a seed file in the db/seeds directory (excluding the .rb extension), then runs it as it would run seeds.rb. You can execute the rake task by issuing the following from the command line:
rake db:seed:file_name # Name of the file EXCLUDING the .rb extension
Update: Now it should also list the seed tasks when running rake --tasks or rake -T.
I tried out zeantsoi's answer but it didn't give me what I wanted, it did all files in a directory. Hacked away at it and got this.
namespace :db do
namespace :seed do
task :single => :environment do
filename = Dir[File.join(Rails.root, 'db', 'seeds', "#{ENV['SEED']}.seeds.rb")][0]
puts "Seeding #{filename}..."
load(filename) if File.exist?(filename)
end
end
end
And to use this do the following:
rake db:seed:single SEED=<seed_name_without_.seeds.rb>
This will look in the Rails.root/db/seeds folder for a file name without the .seeds.rb (it adds those for you).
Working example:
rake db:seed:single SEED=my_custom_seed
The above would seed the Rails.root/db/seeds/my_custom_seed.seeds.rb file
Too complicated!
I just wanted a simple task to execute every file under db/seeds directory without passing in any file names.
# lib/tasks/seed.rake
desc "Run all files in db/seeds directory"
namespace :db do
task seed: :environment do
Dir[File.join(Rails.root, 'db', 'seeds', '*.rb')].each do |filename|
puts "seeding - #{filename}. for reals, yo!"
load(filename)
end
end
end

Rake db:seed can't find .xml file

Total ruby on rails newbie here.
I'm trying to populate a database within a ruby on rails framework. This is what my seeds.rb file looks like:
f = File.open("db/courses.xml")
doc = Nokigiri::XML(f)
f.close
doc.css("course").each do |node|
children = node.children
Course.create(:name => children.css("name"),
:description => children.css("description"))
end
I haven't been able to test this code, because the rake db:seed command keeps saying "No such file or directoy --- courses.xml". Note that I've both tried "courses.xml" and "db/courses.xml" as paths.
The file courses.xml is in the same folder as the seeds.rb file.
Try specifying the path from the root of the application. Like this:
f = File.open(File.join(Rails.root, 'db', 'courses.xml'))

Create a script or task to modify database

I need to create a script that imports data from a file system source. How do I do that?
I already tried to create a rake task but there the models are not loaded. How do I get the whole rails environment into my task?
desc 'Do stuff with models'
task :do_stuff => :environment do
1000.times.each do |i|
Model.create :name => "model number #{i}"
end
end
You declare :environment as a dependency of your rake task. This loads up rails and all of your app code before it runs.

Resources