When to use a new variable vs string interpolation? - ruby

I wrote a script that I decided to refactor so I could add functionality to it as my coworkers think of it. I only saved four lines in the effort, but the main change is I removed both methods and reduced the number of called variables in favor of string interpolation/manipulation. Is there a preference for this? Is it better to declare a new variable just to use once, or is it more DRY to just make minor tweaks to the string when you need to use it? For example here is the original code:
def validate_directory(dir)
puts "Enter the full directory path of the flv files." unless dir
input = dir || gets.chomp
input.gsub!('\\', '/')
input += '/' unless input[-1..-1] == '/'
until File.directory?(input) && Dir.glob("#{input}*.flv") != []
puts "That directory either doesn't exist or contains no .flv files. \nEnter the full directory path of the flv files."
input = $stdin.gets.chomp
input.gsub!('\\', '/')
input += '/' unless input[-1..-1] == '/'
end
dir = input
end
def output(flv, location)
title = flv.dup.gsub!(".flv", ".html")
vid = flv.dup
vid.slice!(0..6)
body = $EMBED.gsub("sample.flv", vid)
htmlOutput = File.open(title, "w")
htmlOutput.write(body)
htmlOutput.close
linkList = File.open("#{location}List of Links.txt", "a")
linkList.write($BASE + vid.gsub(".flv", ".html") + "\n")
linkList.close
puts "Files created successfully."
end
dir = ARGV[0].dup unless ARGV.empty?
folder = validate_directory(dir)
files = folder.clone + "*.flv"
flvs = Dir.glob("#{files}")
File.delete("#{folder}List of Links.txt") if File.exists?("#{folder}List of Links.txt")
flvs.each { |flv| output(flv, folder) }
And the new stuff:
flash_folder = ARGV[0].dup unless ARGV.empty?
if !flash_folder
puts "Enter the full directory path of the flv files."
flash_folder = gets.chomp
end
flash_folder.gsub!('\\', '/')
flash_folder += '/' unless flash_folder[-1..-1] == '/'
until File.directory?(flash_folder) && Dir.glob("#{flash_folder}*.flv") != []
puts "That directory either doesn't exist or contains no .flv files. \nEnter the full directory path of the flv files."
flash_folder = $stdin.gets.chomp
flash_folder.gsub!('\\', '/')
flash_folder += '/' unless flash_folder[-1..-1] == '/'
end
flash_files = Dir.glob("#{flash_folder}*.flv")
File.delete("#{flash_folder}List of Links.txt") if File.exists?("#{flash_folder}List of Links.txt")
flash_files.each do |flv|
html_output = File.open("#{flv.gsub(".flv", ".html")}", "w")
html_output.write("#{embed_code.gsub("sample.flv", flv.slice(7..flv.length))}")
html_output.close
link_list = File.open("#{flash_folder}List of Links.txt", "a")
link_list.write("#{flash_url}#{flv.slice(2..flv.length).gsub(".flv", ".html")}\n")
link_list.close
end
puts "Finished."

Related

RUBY - How to copy files to a specific directory if the file does not exist

I think this is a pretty simple question, but I'm stuck.
I'm trying to write a script to look in the first directory, then check a second directory to see if there are matching files. If the files do match, I need to copy the files from the second directory to a third directory, only if they do not already exist in the third directory.
Here's a copy of what I have so far. The code still overwrites the files in the third directory even if they already exist. What am I doing wrong?
Thanks!
#!/usr/bin/ruby
require 'FileUtils'
library_path_1 = ARGV[0]
library_path_2 = ARGV[1]
library_path_3 = ARGV[2]
dir_1 = Dir.glob(library_path_1 + "/**/*").select{ |x| File.file? x }
dir_2 = Dir.glob(library_path_2 + "/**/*").select{ |x| File.file? x }
destination = Dir.glob(library_path_3 + "/**/*").select{ |x| File.file? x }
dir_1.each do |filename|
dir_2.each do |path|
destination.each do |existing_file|
existing_file = File.basename(existing_file)
if path.include?(File.basename(filename))
FileUtils.cp(path, library_path_3) unless File.exists?(existing_file)
end
end
end
end
bn = dir1.map { |fn| File.basename fn } - destination.map { |fn| File.basename fn }
dir2.each { |fn| FileUtils.cp(fn, library_path_3) if bn.include? File.basename(fn) }
dir_1.each do |file|
filename = File.basename(file)
if exists_in_dir2?(filename) && exists_in_dir3?(filename) == false
copy_to_destination(filename)
end
end
def copy_to_destination(filename)
File.copy(filename, "#{library_path_3}/{filename}")
end
def exists_in_dir2?(filename)
dir_2.each do |path|
path.include?("#{filename}")
end
end
def exists_in_dir3?(filename)
destination.each do |existing_file|
File.exist?("#{filename}")
end
end
It seems you are validating files by its just file names, but you have to check them by full name, like this:
existing_file = File.basename(existing_file)
if path.include?(File.basename(filename))
FileUtils.cp(path, library_path_3) unless File.exist?(File.join(library_path_3, existing_file))
end
Here's the final script that is working based on #Cary Swoveland's answer. Thanks all!
require 'FileUtils'
library_path_1 = ARGV[0]
library_path_2 = ARGV[1]
library_path_3 = ARGV[2]
# check the managed media folder for files, look in original capture scratch for all files in managed media.
# if files in managed media exist in original capture scratch, copy them to the destination folder.
managed_media_folder = Dir.glob(library_path_1 + "/**/*").select{ |x| File.file? x }
original_capture_scratch = Dir.glob(library_path_2 + "/**/*").select{ |x| File.file? x }
destination = Dir.glob(library_path_3 + "/**/*").select{ |x| File.file? x }
bn = managed_media_folder.map { |fn| File.basename fn } - destination.map { |fn| File.basename fn }
original_capture_scratch.each do |fn|
if bn.include? File.basename(fn)
puts fn
FileUtils.cp(fn, library_path_3)
end
end

Check if some files in array exist in directory

I wrote the following code to rename some files in a directory (from 'rb' to 'origin'):
original_files = ['test1.rb', 'test2.rb']
ruby_block "Rename file" do
block do
for filename in original_files
newname = filename.split(".")[0] + '.origin'
::File.rename("C:\\Test\\#{filename}", "C:\\Test\\#{newname}")
end
end
end
When I run it for the second time, I get an error that these files don't exist, which is expected.
How can I check if these files exist or not like this:
if ::File.exist?("C:\\Test\\*.origin")
Chef::Log.info("########## Your files are already renamed ############")
else
my_code
end
or in another way (maybe to check it in loop)?
This is my solution after numerous attempts:
origin_files = ['test1.rb', 'test2.rb']
dir_path = "C:\\Test"
ruby_block "Rename file" do
block do
for filename in origin_files
newname = filename.split(".")[0] + '.origin'
if ::File.exist?("#{dir_path}\\#{newname}")
Chef::Log.info("### Your file: #{newname} already renamed ###")
else
::File.rename("#{dir_path}\\#{filename}", "#{dir_path}\\#{newname}")
end
end
end
end
you can check this files like this code
files = ["test1.rb", "test2.rb"]
path = "C:/test"
files.each { |file_name|
base_name = File.basename(file_name, ".rb")
new_name = base_name + ".origin"
if File.exists?(File.join(path, new_name))
Chef::Log.info("########## Your file #{base_name} are already renamed ############")
elsif File.exists?(File.join(path, file_name))
File.rename(File.join(path, file_name), File.join(path, new_name))
Chef::Log.info("########## Your file #{base_name} was renamed ############")
else
Chef::Log.info("########## Your file #{file_name} not exist ############")
end
}
You can use Chef guard for this purpose. It automatically logs the event during the chef-client run as
ruby_block xxx (skipped due to not_if)
Here is the example:
origin_files = ['test1.rb', 'test2.rb']
dir_path = "C:\\Test"
origin_files.each do | old_file |
base_name = File.basename(old_file, ".rb")
newfile = base_name + ".origin"
ruby_block "rename #{old_file}" do
block do
File.rename(File.join(dir_path, old_file), File.join(dir_path, newfile))
end
not_if { File.exist?("#{dir_path}\\#{newfile}") }
end
end

Appending a parameter's value in parameters.yml when deploying symfony application

First of all I've never used ruby and capifony so this question might be very easy for some of you but not for me. I tried to find examples related to my question but couldn't find any or I'm too new to ruby to miss!
When deploying my Symfony app, the value of a particular key in my parameters file should be dynamically appended so, rather than using exact generic value coming from distribution file below:
parameters_prod.yml.dist
parameters:
my_prefix: my_value_prefix_
Straight after deployment, parameters.yml should read like below:
parameters.yml
parameters:
my_prefix: my_value_prefix_8235647895
8235647895 part above is going to be timestamp.
How can I do this?
My current deploy.rb
namespace :mytest do
desc "Upload the parameters.yml"
task :upload_parameters do
origin_file = parameters_dir + "/" + parameters_file if parameters_dir && parameters_file
origin_file_append = parameters_dir + "/" + parameters_file_append if parameters_dir && parameters_file_append
if origin_file && File.exists?(origin_file)
relative_path = "app/config/parameters.yml"
files = [origin_file]
files << origin_file_append if origin_file_append && File.exists?(origin_file_append)
tmp_origin_file = origin_file + '.tmp'
File.open(tmp_origin_file, 'w') do |fo|
files.each do |file|
File.foreach(file) do |li|
fo.puts li
end
end
end
if shared_files && shared_files.include?(relative_path)
destination_file = shared_path + "/" + relative_path
else
destination_file = latest_release + "/" + relative_path
end
try_sudo "mkdir -p #{File.dirname(destination_file)}"
top.upload(tmp_origin_file, destination_file)
File.delete(tmp_origin_file)
end
end
end

Modifying files in a zip archive

I want to modify all of the files in a zip archive of XML files. When I tried to do this though, it tells me that the file doesn't exist. If I comment out the replace call though this works. What am I doing wrong?
Zip::ZipFile.open(temp_file.path) do |zipfile|
for i in 0..(zipfile.entries.count - 1)
entry = zipfile.entries[i]
if entry.name
if entry.name.split("/").last == "patient_manifest.txt"
next
end
end
next if entry.directory?
data = zipfile.read(entry.name)
doc = Nokogiri::XML(data)
doc.root.add_namespace_definition('cda', 'urn:hl7-org:v3')
doc.root.add_namespace_definition('sdtc', 'urn:hl7-org:sdtc')
patient_role_element = doc.at_xpath('/cda:ClinicalDocument/cda:recordTarget/cda:patientRole')
patient_element = patient_role_element.at_xpath('./cda:patient')
first = patient_element.at_xpath('cda:name/cda:given').text
last = patient_element.at_xpath('cda:name/cda:family').text
id_node = patient_role_element.at_xpath('./cda:id')
id_node['extension'] = id_node['extension'] + first + last
xml_file = Tempfile.new('foo')
begin
xml_file.write(doc.to_xml)
zipfile.replace(entry, xml_file.path)
ensure
xml_file.close
xml_file.unlink # deletes the temp file
end
end
end

Ruby file full path

I am writing a program where I cycle through all files in sub-folders of a target folder and do stuff with what's writen in it. So my local folder looks like that
Folder
--Subfolder
---File
---File
---File
--Subfolder
---File
.
.
.
So I have a each loop to cycle through all subfolders and for each subfolder I am calling a method that basically do the same thing but in the subfolder and call for each file another method (parsing it a file argument which I obtained through a Dir.foreach(folder){ |file| method(file)} command).
So it looks like this :
Dir.foreach(Dir.pwd){ |folder| call_method(folder) }
def call_method(folder) Dir.foreach(folder){|file| reading_method(file) } end
That last called method (reading_method) should open called a C method and parse as an argument the full path of the file (so that the C program can open it) so I'm using File.absolute_path(file) in the reading_method but instead of returning C:/folder/subfolder/file as I want it to, it returns C:/folder/file skipping the subfolder (and thus the C program fail to execute).
Is there a way to get the full path of that file ?
Thanks for your help
EDIT : Here is the full code as asked
## Module
module GBK_Reader
PATH = "Z:/Folder/"
SAFETY = true
SAFETY_COUNT = 10
end
## Methods definitions
def read_file(file)
path = File.absolute_path(file)
c_string = `C:/Code/GBK_Reader/bin/Debug/GBK_Reader.exe #{path}`
return c_string.split(/ /).collect!{|spec| spec.to_i}
end
def read_folder(folder)
Dir.foreach(folder){ |file|
next if File.extname(file) != ".gbk"
temp = read_file(file)
#$bacteria_specs[0] += temp[0]
#$bacteria_specs[1] += temp[1]
}
return $bacteria_specs
end
## Main
# Look for folder
Dir.chdir(GBK_Reader::PATH)
puts "Directory found"
# Cycle through all sub-folders
$high_gc = {} #Hash to store high GC content bacterias
$count = 0
puts "Array variable set"
Dir.foreach(Dir.pwd){ |file|
next if file == "." || file == ".."
break if $count >= GBK_Reader::SAFETY_COUNT
$count += 1 if GBK_Reader::SAFETY
$bacteria_specs = [0.00, 0.00, 0.00]
$path = File.expand_path(file)
if File.directory?(file)
# Cycle through all .gbk files in sub-folder and call C program
read_folder(file)
else
# Call C program to directly evaluate GC content
c_string = read_file(file) if File.extname(file) == ".gbk"
$bacteria_specs[0] = c_string[0].to_i
$bacteria_specs[1] = c_string[1].to_i
end
# Evaluate GC content and store suitable entries
$bacteria_specs[2] = ($bacteria_specs[0]/$bacteria_specs[1])*100.00
$high_gc[file] = $bacteria_specs if $bacteria_specs[2] > 60
}
# Display suitable entries
puts "\n\n\n"
puts $high_gc
gets.chomp
Ok, I may have found something but it seems ugly so if anyone has a better solution by all means go ahead.
I edited my read_folder method to parse the full path to the read_file method as follow :
def read_folder(folder)
Dir.foreach(folder){ |file|
next if File.extname(file) != ".gbk"
path = File.absolute_path(folder)+'/'+File.basename(file)
temp = read_file(path)
$bacteria_specs[0] += temp[0]
$bacteria_specs[1] += temp[1]
}
return $bacteria_specs
end
And I do get the path I expect. (though my calling the C program still fails so I'll have to check somewhere else :D)

Resources