regexp matching in rails app - ruby-on-rails

I have the following string that needs to be replaced by an empty character in rails. Followed many tutorials and docs. Please help me achieve this.
String:
/home/<someword>/dbdumps/backup.sql
To be replaced as:
backup

To get the file name from a path, I'd use File#basename
File.basename('/home/<someword>/dbdumps/backup.sql', '.sql')
#=> 'backup'

if "someword" is the only thing that changes you dont even need regex.
Assume
path = "/home/<someword>/dbdumps/backup.sql"
then
path.split("/").last.split(".").first
returns
=> "backup"

The easiest solution would be a gsub (string substitution) like so:
string = "home/<someword>/dbdumps/backup.sql"
new_string = string.gsub(%r{home/(.*)/dbdumps/backup.sql}, 'backup' )
This is a simple example of string substitution.

In a rails app i do a Net:SSH:start( ) and run ssh.exec!('ls /home//dbdumps/.sql'). I am ?sending the output to a string and then i have to display the list of the files. For that I am taking the output into a string and trying to do a gsub. Is this the right approach?
I would not consider it pretty (naive code, no error checking, loops with requests) but something like this could do the job for you. It depends if you want to end up with just the backup names or the full path.
ssh.exec!("ls -l /home/") do |channel, stream, data|
directories << data if stream == :stdout
end
directories.each do |dir|
ssh.exec!("ls -l /home/" + dir + "dbdumps") do |channel, stream, data|
backup_names << /home/" + dir + "/" + data if stream == :stdout
end
end
hope this helps

Related

Write a script in Ruby to rename all *.htm files to *.html

I need to write a script in Ruby to rename all *.htm files to *.html in a given
directory.
I've been given a script with some pieces missing.
I need to "METHOD" with the appropriate method name and "REGEX" with an appropriate
regular expression to match all the files that end in .htm.
Dir.METHOD("*.htm").each do |html_file|
FileUtils.METHOD html_file, "#{html_file.METHOD(/REGEX/,'.html')}"
end
Does anyone know what I should replace "METHOD" and "REGEX" with?
Dir.glob("*.htm") do |html_file|
FileUtils.mv(html_file, "#{File.basename(html_file, ".htm")}.html")
end
Dir.glob("*.htm").each do |html_file|
FileUtils.mv html_file, "#{html_file.sub(/.htm/,'.html')}"
end
Here's how I did it though it did not use a FileUtils method and I skipped ahead and did string manipulation before it was discussed in the lessons.
Dir.glob("*.htm") {|old_filename| #Save file names w/ .htm to old_
tmp_filename = old_filename.slice(0..-5) #Remove (.htm) the file extension
new_filename = tmp_filename + '.html' #Append the .html extension
puts new_filename #Display renamed file names
}

Mixing Ruby and bash commands -- mv returns "x and y are the same file"

So I have a Ruby script (using Ruby because we have a library of pre-existing code that I need to use). From within Ruby I am using backticks to call Linux commands, specifically in this case the "mv" command. I am trying to move one file to another location but I keep getting the error message that x and y are "the same file" even though they are very clearly NOT the same file.
Here is the code in Ruby:
#!/usr/local/rvm/rubies/ruby-2.1.1/bin/ruby
masterFiles=[]
masterFiles << "/mnt/datadrive/Data Capture/QualityControl/UH_HRA_SVY/Scans and DataOutput/Data/UH_HRA_SVY_DATA.txt"
masterFiles << "/mnt/datadrive/Data Capture/QualityControl/UH_HRA_SVY_SPAN/Scans and DataOutput/Data/UH_HRA_SVY_SPAN_DATA.txt"
tm=Time.new.strftime("%Y%m%d")
masterFiles.each do |mf|
if File.exist?(mf)
qmf=39.chr + mf + 39.chr
`cat #{qmf} >> /tmp/QM`
savename=39.chr + \
"/mnt/datadrive/Data Capture/QualityControl/UH_HRA_SVY/Scans and DataOutput/Data/DailyFiles/" + \
File.basename(mf).gsub(".txt","_"+tm) + ".txt" + 39.chr
`mv #{qmf} #{savename}`
end
end
The error that I get is this:
mv: `/mnt/datadrive/Data Capture/QualityControl/UH_HRA_SVY_SPAN/Scans
and DataOutput/Data/UH_HRA_SVY_SPAN_DATA.txt' and `/mnt/datadrive/Data
Capture/QualityControl/UH_HRA_SVY/Scans and
DataOutput/Data/DailyFiles/UH_HRA_SVY_SPAN_DATA_20140530.txt' are the
same file
If I change this line:
`mv #{qmf} #{savename}`
To this:
puts "mv #{qmf} #{savename}"
And then run the output, it works as expected.
I am pretty sure that this has to do with spaces in the path. I have tried every combination of double-quoting, triple-quoting, quadruple-quoting, and back-slashing I can think of to resolve this but no go. I have also tried using FileUtils.mv but get what is basically the same error worded differently.
Can anybody help ? Thanks a lot.
p.s. I realize it's entirely possible that I could be going about this in an entirely wrong-headed way, so feel free to point that out if so. However, I am trying to use the tools which I already have some knowledge of (cat, mv, etc) instead of re-inventing the wheel.
You could use FileUtils.mv
I often do aliases like so:
require 'fileutils'
def mv(from, to)
FileUtils.mv(from, to)
end
And inside the mv() method I do additional safeguards, i.e. if the file does not exist, if there is a lack of permissions and so forth.
If you then still have problems with filenames that have ' ' blank characters, try to put the file into a "" quote like:
your_target_location = "foo/bar bla"

Rails detect changes to files programatically

I would like to write a method that programatically detects whether any of the files in my rails app have been changed. Is it possible do do something like an MD5 of the whole app and store that in a session variable?
This is mostly for having some fun with cache manifest. I already have a dynamically generated cache and it works well in production. But in my dev environment, I would like the id of that cache to update whenever I change anything in the app directory (as opposed to every 10 seconds, which is how I have it setup right now).
Update
File.ctime(".") would be perfect, except that "." is not marked as having changed when deeper directory files have changed.
Does it make sense to iterate through all directories in "." and add together the ctimes for each?
Have you considered using Guard.
You can programatically do anything whenever a file in your project changes.
There is a nice railscast about it
There is a simple ruby gem called filewatcher. This is the most advanced example:
require 'filewatcher'
FileWatcher.new(["README.rdoc"]).watch() do |filename, event|
if(event == :changed)
puts "File updated: " + filename
end
if(event == :delete)
puts "File deleted: " + filename
end
if(event == :new)
puts "New file: " + filename
end
end
File.ctime is the key. Iterate through all files and create a unique id based on the sum of all their ctimes:
cache_id = 0
Dir.glob('./**/*') do |this_file|
ignore_files = ['.', '..', "log"]
ignore_files.each do |ig|
next if this_file == ig
end
cache_id += File.ctime(this_file).to_i if File.directory?(this_file)
end
Works like a charm, page only re-caches when it needs to, even in development.

Ruby Net::FTP, extract filename from ftp.list()

I'm using the following code to try and get all files from ftp using Ruby.
files = ftp.list()
files.each do |file|
ftp.gettextfile(file)
end
The problem is ftp.list returns a whole line of information, not just the filename e.g.
-rw-r--r-- 1 ftp ftp 0 May 31 11:18 brett.txt
How do I extract the filname from this string?
Many thanks
You can use the nlst public method like this
files = ftp.nlst("*.zip")|ftp.nlst("*.txt")|ftp.nlst("*.xml")
#optionally exclude falsely matched files
exclude = /\.old|temp/
#exclude files with 'old' or 'temp' in the name
files = files.reject{ |e| exclude.match e } #remove files matching the exclude regex
files.each do |file|
#do something with each file here
end
If you want to process the output of ftp.list you may find net-ftp-list useful.
However, list appears to be useful, as you can pass in a matching pattern, which it doesn't appear that nlst supports. I just did a quick-and-dirty hack to make list output work:
ftp.list("*.zip") do |zipfile|
zipfile = zipfile.split(/\s+/).last
# ... do something with the file
end

Reading the first line of a file in Ruby

I want to read only the first line of a file using Ruby in the fastest, simplest, most idiomatic way possible. What's the best approach?
(Specifically: I want to read the git commit UUID out of the REVISION file in my latest Capistrano-deployed Rails directory, and then output that to my tag. This will let me see at an http-glance what version is deployed to my server. If there's an entirely different & better way to do this, please let me know.)
This will read exactly one line and ensure that the file is properly closed immediately after.
strVar = File.open('somefile.txt') {|f| f.readline}
# or, in Ruby 1.8.7 and above: #
strVar = File.open('somefile.txt', &:readline)
puts strVar
Here's a concise idiomatic way to do it that properly opens the file for reading and closes it afterwards.
File.open('path.txt', &:gets)
If you want an empty file to cause an exception use this instead.
File.open('path.txt', &:readline)
Also, here's a quick & dirty implementation of head that would work for your purposes and in many other instances where you want to read a few more lines.
# Reads a set number of lines from the top.
# Usage: File.head('path.txt')
class File
def self.head(path, n = 1)
open(path) do |f|
lines = []
n.times do
line = f.gets || break
lines << line
end
lines
end
end
end
You can try this:
File.foreach('path_to_file').first
How to read the first line in a ruby file:
commit_hash = File.open("filename.txt").first
Alternatively you could just do a git-log from inside your application:
commit_hash = `git log -1 --pretty=format:"%H"`
The %H tells the format to print the full commit hash. There are also modules which allow you to access your local git repo from inside a Rails app in a more ruby-ish manner although I have never used them.
first_line = open("filename").gets
I think the jkupferman suggestion of investigating the git --pretty options makes the most sense, however yet another approach would be the head command e.g.
ruby -e 'puts `head -n 1 filename`' #(backtick before `head` and after `filename`)
Improving on the answer posted by #Chuck, I think it might be worthwhile to point out that if the file you are reading is empty, an EOFError exception will be thrown. Catch and ignore the exception:
def readit(filename)
text = ""
begin
text = File.open(filename, &:readline)
rescue EOFError
end
text
end
first_line = File.readlines('file_path').first.chomp

Resources