Importing a file into my app from a hosted account (godaddy) - ruby-on-rails

I have already built several Rake tasks to import a series of CSV files into my PostgreSQL database, but I've always had those tasks directed to a path on my local computer.
I need to have the tasks set up to access a secure on directory so my client can simply copy files into this directory, and when the Rake task is executed it automatically pulls from the online source.
This seems like it would be a simple adjustment in my code but I'm not sure how to make it work. If anyone has any suggested reading or can quickly help edit my code it would be appreciated.
Below is a copy of one of my Rake tasks:
require 'csv'
namespace :import_command_vehicles_csv do
task :create_command_vehicles => :environment do
puts "Import Command Vehicles"
csv_text = File.read('/Users/Ben/Sites/ror/LFD/command_vehicles.csv', :encoding => 'windows-1251:utf-8')
csv = CSV.parse(csv_text, :headers => true)
csv.each_with_index do |row,index|
row = row.to_hash.with_indifferent_access
CommandVehicle.create!(row.to_hash.symbolize_keys)
command_vehicle = CommandVehicle.last
if #report_timesheet_hash.key?(command_vehicle.report_nr)
command_vehicle.timesheet_id = "#{#report_timesheet_hash[command_vehicle.report_nr]}"
end
#command_vehicle.timesheet_id = #timesheet_id_array[index]
command_vehicle.save
end
end
end

You can create rake tast that can accept parameters and then you can pass whatever path you like.
Check out this link Set Multiple Environmental Variables On Invocation of Rake Task to see how to pass parameters via enviroment variables and this link http://viget.com/extend/protip-passing-parameters-to-your-rake-tasks to see bracket notation.

'/Users/Ben/Sites/ror/LFD/command_vehicles.csv' will only work on your local machine, unless you have an identical path to your resources on the remote host, which is hardly likely. As a result, you need to change the absolute path, to one that is relative to your file.
I have a folder hierarchy on my Desktop, stuck several folders down, like:
- test
| lib
| - test.rb
| config
| - config.yaml
And test.rb contains:
File.realpath('../config/config.yaml', File.dirname(__FILE__))
__FILE__ is a special variable that returns the absolute path to the script currently being interpreted. That makes it easy to find where something else is if you know where it exists relative to the current __FILE__.
The value returned by realpath will be the absolute path to the "config.yaml" file, based on its relative path from the current file. In other words, that would return something like:
/Users/ttm/Desktop/tests/junk/test/config/config.yaml
The nice thing about Rake is it's really using Ruby scripts, so you can take advantage of things like File.realpath. Also, remember that Rake's idea of the current-working directory is based on the location of the script being run, so everything it wants to access has to be relative to the script's location, or an absolute path, or you have to change Rake's idea of the current-working directory by using a chdir or cd.
Doing the later makes my head hurt eventually so I prefer to define some constants pointing to the required resources, and figuring out the real absolute path becomes easy doing it this way.
See "How can I get the name of the command called for usage prompts in Ruby?"
for more information.

Related

How to delete the directory in ruby on rails after its creation without page reload

I need to delete the directory after its creation but I am getting an error because the directory is still in use by ruby.exe or another ruby process is there any way that I can close the directory like closing the file so that it will delete after its creation. When i reload the page and then try to remove the directory then the directory successfully delete.
Here is the code which i am trying
if Dir.exists?("first/test")
FileUtils.rm_rf("first/test")
FileUtils.mkdir("first/test")
else
Dir.mkdir("first/test")
end
Test folder does contain sub directories and files.
The stream was not closing after writing files in rubyzip class
I have modified the code in rubyzip class like this
disk_file = File.open(diskFilePath, "rb")
io.get_output_stream(zipFilePath) { |f|
f.puts(disk_file.read())
}
disk_file.close
There are two main problems with your code, I think:
According to Ruby documentation, Dir.exists? is deprecated and should not be used. Use Dir.exist? (without the 's') instead;
You are trying to create a directory structure with FileUtils.mkdir or Dir.mkdir when, in fact, you need a 'stronger' method: FileUtils.mkdir_p.
Try this:
if Dir.exist?("first/test")
FileUtils.rm_rf("first/test")
FileUtils.mkdir_p("first/test")
else
FileUtils.mkdir_p("first/test")
end
And see the corresponding documentation.
I believe that doing
FileUtils.mkdir("first")
FileUtils.mkdir("first/test")
would work fine, although I haven't tested it, because the second dir ('test') would be create inside an existing one. But if you need to create a whole structure in a single command you'd need the -p flag using a bash command and the corresponding FileUtils.mkdir_p method.
Let me also point you that this if..else structure is not good this way. You want to create the directory structure in both if and else, and if the same command appears in both if and else, it must be taken out of the if..else, like this.
if Dir.exist?("first/test")
FileUtils.rm_rf("first/test")
end
FileUtils.mkdir_p("first/test")
I hope this helps.

Rake: Processing files in a specified source directory

In my Rails project I have a specific list of externally-supplied files I want to process using Rake. My goal is to be able to specify the source directory of these files as an argument like so:
rake foofiles:process[vendor/sources]
Currently I'm specifying the file names (and their relative paths within the source directory) using a FileList assigned to a constant:
REQUIRED_FILES = FileList[
'blah.csv',
'subdir/something.csv',
'subdir/monkeys/foo.bar',
...
]
How can I prepend each of these files with my source directory argument so that I can make a task that depends on those files existing in that directory? (ideally nothing would happen without all those files being present)
For example, if I used the rake command as typed above, I'd need my task to depend on vendor/sources/blah.csv, vendor/sources/subdir/something.csv, vendor/sources/subdir/monkeys/foo.bar etc.
Edit: Adding a prefix to each element in an array/list is relatively trivial, I'm more confused about how to structure my task(s) and their dependencies so I can actually access the source folder argument I've supplied, then use the new prepended file list as a dependency for the processing task that actually does the work.
The main invoked task is gonna have to look something like this if I want the syntax I used at the top:
namespace :foofiles do
task :process, [:source_directory] => [???, my_newly_prepended_file_list] do |t, args|
# Do stuff
end
end
But I don't know how to provide the :source_directory argument to a task that does the prepending, and then subsequently return the prepended file list to the :process task as a dependency.
Why not just keep an array of the suffixes, then append the argument to the start of each element in the array, then create the filelist?
suffixes = [
'blah.csv',
'subdir/something.csv',
'subdir/monkeys/foo.bar',
]
files = suffixes.map { |suffix| File.join(prefix, suffix) }
file_list = FileList[*files]
Where prefix is the argument passed in.
I ended up just using an environment variable, it's much easier to work with in my case than Rake's built-in argument implementation. This way I can work with the variable and build my FileList with the prepended path (in the way Cameron suggested in the other answer) outside a task block:
namespace :foofiles do
REQUIRED_FILES = [...]
source_directory = ENV['SOURCEDIR'] || 'vendor/sources'
source_files = FileList[REQUIRED_FILES.map { |relative_path| File.join source_directory, relative_path }]
# Note: FileList can take an array inside the square brackets without needing the splat (*) operator
task process: source_files do
...
end
end
So now I can call it from the terminal like this:
SOURCEDIR=some/folder rake foofiles:process

sandbox testing environments exist for TDD'ing command line application

I'm writing a command line command but want to TDD it. I'll be creating and deleting files and was wondering if there's a sandbox testing gem or something like that. I'm using ruby and rspec.
Depends on what you're trying to do, but I test most of my command line Ruby by mocking out the file system and STDIN/STDOUT. Using dependency injection I often end up with something along these lines:
describe Add do
it 'writes the result to standard out' do
console = mock('STDOUT')
console.should_receive(:puts).with('5')
Add.new(console).execute(3,2)
end
end
class Add
def initialize(out = STDOUT)
#out = out
end
def execute(command_line_args)
#out.puts(command_line_args.inject(:+))
end
end
Add.new.execute(ARGS)
By using default values I can inject in the test, but leave it out of the production code.
Hope that helps!
Brandon
The template generated by the newgem install_cucumber generator uses a pattern that I like quite a bit. Have a look at the support/env.rb and support/common.rb files it creates:
https://github.com/drnic/newgem/blob/master/rubygems_generators/install_cucumber/templates/features/support/env.rb.erb
https://github.com/drnic/newgem/blob/master/rubygems_generators/install_cucumber/templates/features/support/common.rb
Use of it in test looks like this:
in_tmp_folder do
# The current directory is now a generated tmp folder.
# If you stick to relative paths, everything you do in here should be safe
end
The files linked to above are for using this in cucumber tests, but it could easily be adapter to whatever framework you're using. The env.rb above deletes the tmp folder before each test starts.
You might also want to take a look at the sandbox gem.
gem install sandbox
Example usage is here: https://github.com/bdimcheff/sandbox

ActionMailer password security

Am I crazy, or is it a bad idea to keep my SMTP username and password for ActionMailer in the actual (development/production) config file? It seems like I should store it an encrypted place, or at the very minimum, exclude it from my Mercurial pushes.
Right now, I'm just removing the password from my source file before performing a push, but there's got to be a smarter way than the one I'm using. :)
Perhaps I should store it in my database as another user (which is already stored with encrypted passwords) and fetch it programatically?
Use an application configuration file that is not stored in your repository for storing sensitive information. Here is how I've done it:
Add an app_config.yml in your config directory. Its contents would look like this:
smtp_password: kl240jvfslkr32rKgjlk
some_other_password: 34hg9r0j0g402jg
and_so_on: lkn$#gJkjgsFLK4gaj
Add a preinitializer.rb in your config directory with the following contents:
require 'yaml'
APP_CONFIG = YAML.load(File.read(RAILS_ROOT + "/config/app_config.yml"))
Substitute your passwords for values in the APP_CONFIG variable, like so:
smtp_password = kl240jvfslkr32rKgjlk # old version
smtp_password = APP_CONFIG['smtp_password'] # new version
Make sure you don't include app_config.yml in your repository, though you may want to create an example file that is checked in, just to show a sample of what should be in it. When you deploy your application, make sure that app_config.yml is stored on the server. If you're using a standard Capistrano deployment, put the file in the shared folder and update your deployment task to create a symlink to it in the current release's directory.
Jimmy's answer is perfect (+1), I would also note that Github has recommended .gitignore files for every language and the Rails one is here Note that it includes config/*.yml so that no config/yml file is in the respository to begin with. Probably a good move.
Use Capistrano to ask for these things upon deploy:setup the same way you should be doing for your database stuff:
task :my_silly_task do
sendgrid_password = Capistrano::CLI.password_prompt("Sendgrid password: ")
require 'yaml'
spec = {... whatever yaml you need -- probably what Jimmy said...}
run "mkdir -p #{shared_path}/config"
put(spec.to_yaml, "#{shared_path}/config/mailer_config.yml")
end

Rails, Rake, moving a folder to a new location

I need to move a folder from a plugin to the main app/views. I guess using rake to do this with the following command is the easiest way:
require 'fileutils'
FileUtils.mv('/vendor/plugins/easy_addresses/lib/app/views', '/app/views/')
I'm just not sure where to tell script where to look and where to place the folder.
The file I want to move is in the following location: `vender/plugins/easy_addresses/lib/app/views/easy_addresses
easy_ addresses is the name of the folder in views that I want to move to my_app/app/views/
FileUtils.mv('/source/', '/destination/')
There is a constant which has the rails root, just prepend it to your pathes:
File.join(RAILS_ROOT, "app", "views")
Here RAILS_ROOT holds the location "where to look", and using File.join on the path components takes care of concatenating the components using the right path separator suitable for the used system.
In the result the above method call gives you the complete absolute path to "app/views" in your application.
Edit:
In Rails >= 3 you can use Rails.root.join('app', 'views').

Resources