Ruby method arguments - ruby

I need to check the third parameter of a method:
def NFS(configsHash, optionsHash, backupType)
I want to use an if statement to check the path where backupType is to be saved. Something like:
If #{backupType} == "dir/file/path/name/time"
STDOUT.puts("Backup will be saved to current folder.")
else
STDOUT.puts("Putting into backup folder")
STDOUT.puts(mkdir #{backups})
But I haven't been able to get the syntax right. Any suggestions?

You can also go with this:
case backupType
when "dir/file/path/name/time"
puts("Backup will be saved to current folder.")
else
puts("Putting into backup folder")
puts(Dir.mkdir backups)
end

if backupType == "dir/file/path/name/time"
puts "Backup will be saved to current folder."
else
puts "Putting into backup folder"
Dir.mkdir "path/goes/here"
end
Notice that STDOUT has been dropped off. That is redundant. If you do STDOUT.puts.object_id and puts.object_id you will see they refer to the same things. Also, notice that it is Dir.mkdir; not just mkdir; it needs to be called on the Dir class.
Modified to be a little more idiomatic. I also dropped the puts from in from of the Dir.mkdir; as I assume that is not really what you intended.

# Assuming that backupType is a string
if backupType == "dir/file/path/name/time"
print "Backup will be saved to current folder."
else
print "Putting into backup folder"
# This part below is tricky since I don't know what the backups variable is referring to
print Dir.mkdir backups
end
#fotanus in the comments makes great suggestions on naming conventions, but to ensure consistency I've kept the names the same for the answer.

Related

Nested directory searching

I'm trying to make a program that searches through hopefully every directory, sub directory, sub sub directory and so on in C:\. I feel like I can take care of that part, but there's also the issue of the folder names. There may be case issues like a folder named FOO not being dected when my program searches for Foo or a giant if/else or case statement for multiple search criteria.
My questions are: 1. is there a way to ignore letter case? and 2. is there a way to make a more efficient statement for searching?
My current code:
#foldersniffer by Touka, ©2015
base = Dir.entries("C:\\")
trees = Dir.entries("#{base}")
trees.each do |tree|
if Dir.exist?("Foo")
puts "Found Folder \"Foo\" in C:\\"
elsif Dir.exist?("Bar")
puts "Found Folder \"Bar\" in C:\\"
else
puts "No folders found"
end
end
sleep
any help is appreciated.
edit: it's trying to scan files like bootmgr and it's giving me errors... I'm not sure how to fix that.
Consider using Dir.glob(...) and regular expressions for case insensitive matching:
Dir.glob('c:\\**\*') do |filename|
if filename =~ /c:\\(foo|bar)($|\\)/i
puts "Found #{filename}"
end
end
Case sensitivity for the Dir.glob argument is likely not relevant on Windows systems:
Note that this pattern is not a regexp, it’s closer to a shell glob. See File.fnmatch for the meaning of the flags parameter. Note that case sensitivity depends on your system (so File::FNM_CASEFOLD is ignored), as does the order in which the results are returned.
I am not expert enough to say for sure but I would look into File::FNM_CASEFOLD
https://lostechies.com/derickbailey/2011/04/14/case-insensitive-dir-glob-in-ruby-really-it-has-to-be-that-cryptic/

Read file after writing in same script (Ruby the Hard Way ex16)

Here is my code:
filename = ARGV.first
puts "We're gong to erase #{filename}"
puts "If you don't want that, hit CTRL-C (^C)."
puts "If you do want that, hit RETURN."
$stdin.gets
puts "Opening the file..."
target = open(filename, 'w')
puts "Truncating the file. Goodbye!"
target.truncate(0)
puts "Now I'm going to ask you for three lines."
print "line 1: "
line1 = $stdin.gets.chomp
print "line 2: "
line2 = $stdin.gets.chomp
print "line 3: "
line3 = $stdin.gets.chomp
puts "I'm going to write these to the file."
target.write(line1)
target.write("\n")
target.write(line2)
target.write("\n")
target.write(line3)
target.write("\n")
print target.read
puts "And finally, we close it."
target.close
I'm trying to get it to write and then read. It works if I do target.close and then target = open(filename) again at the bottom of the script. Is there another way?
I saw this post about python explaining you need to close a file after writing to it. Does this same thing apply to Ruby? Do I need to use flush?
Also should I be using parentheses after read and close? The example does not.
There's two ways to approach this. You can, as you've done, open the file for writing, write to it, close the file, and reopen it for reading. This is fine. Closing the file will flush it to disk and reopening it will put you back at the beginning of the file.
Alternatively you can open a file for both reading and writing and manually move around within the file, like a cursor in an editor. The options to do this are defined in IO.new.
The problem with your code is this.
target.write("\n")
print target.read
At this point you've been writing to the file. The target file pointer is pointing at the end of the file, like a cursor in an editor. When you target.read it's going to read the end of the file, so you get nothing. You'd have to go back to the beginning of the file first with rewind.
target.write("\n")
target.rewind
print target.read
You'll also have to open the file for reading and writing. w+ can do that, and truncate the file for you.
puts "Opening the file..."
target = File.open(filename, 'w+')
This is an advanced technique most often useful for when you want to hold a lock on a file during the whole reading and writing process to make sure nobody else can work on the file while you are. Generally you do this when you're reading and then writing. For example, if you had a counter in a file you want to read and then increment and make sure nobody can write between.
def read_and_update_counter
value = 0
# Open for reading and writing, create the file if it doesn't exist
File.open("counter", File::RDWR|File::CREAT, 0644) {|f|
# Get an exclusive lock to prevent anyone else from using the
# file while we're updating it (as long as they also try to flock)
f.flock(File::LOCK_EX)
# read the value
value = f.read.to_i
# go back to the beginning of the file
f.rewind
# Increment and write the new value
f.write("#{value + 1}\n")
# Flush the changes to the file out of the in-memory IO cache
# and to disk.
f.flush
# Get rid of any other garbage that might be at the end of the file
f.truncate(f.pos)
}
# File.open automatically closes the file for us
return value
end
3.times { puts read_and_update_counter }

Having trouble in getting input from user in Ruby

I have a method which check if the file exists, If the file does not exist then it should call another method which prompts the questions. Below is the sample code.
def readFile1()
flag = false
begin
#ssh.exec!("cd #{##home_dir}")
puts "\nChecking if file exists on #{#hostname}\n"
if #ssh.exec!("sh -c '[ -f "#{file_name}" ]; echo $?'").to_i == 0
flag = true
puts "File exists on #{#hostname}"
display()
else
puts "File does not exist. Please answer following questions."
prompt()
end
rescue => e
puts "readFile1 failed... #{e}"
end
return exists
end
def prompt()
puts "\nDo you want to enter the new file location? [y/n]"
ans = gets.chomp
puts "New location is #{ans}"
end
When I am calling readFile method, if the file does not exists, it prints Do you want to enter the new file location? [y/n] and does not wait for the user to enter the value but immediately prints the rescue block and quits. Below is the Output if file does not exists.
Checking if file exists on LNXAPP
File does not exist. Please answer following questions.
Do you want to enter the new file location? [y/n]
readFile1 failed... No such file or directory - LNXAPP
I want the user to enter the values for the questions but it's not happening.Need help in fixing this.
Your code is not ideal.
You should check if the file exists via:
if File.exist? location_of_your_file_goes_here
The begin/rescue is then not required, because
you already check before whether the file exists.
Also two spaces should be better than one tab,
at least when you display on a site such as here.
Reason is simple - it makes your code easier
to read for others.
You also don't need the flag variable if I am
right - try to omit it and use solely File.exist?
there.
Also you wrote:
"When I am calling readFile method"
But you have no method called readFile().
Your method is called readFile1().
I know that you probably know this too, but
you must be very specific so that the ruby
parser understands precisely what you mean,
and that what you describe with words also
matches to the code you use.
Another issue I see with your code is that
you do this:
return exists
but what is "exists" here? A variable?
A method? It has not been defined elsewhere
in your code.
Try to make your code as simple and as logical
as possible.

after opening a file check if the file was modified on close

I am wondering if I am doing it the correct way.
def checkout
clone = system( "svn export #{file} tmp/" )
open_file = system( "start tmp/#{#file}" )
end
Now, I am able to open the file I want with the default editor but how to record if the file was modified before close.
Should I create a Process and do Process.wait or something?
Thanks for your help
Use File::mtime method for the same.
Returns the modification time for the named file as a Time object.
file_time_before_opening = File.mtime('your file/path')
# do file operation as you like
file_time_after_closing = File.mtime('your file/path')
# now compare file_time_before_opening and file_time_after_closing to know
# if it is modified or not.
If you mean you are using start in Windows, use /wait or /w option to make it wait until the editor termination.
Use IO::read to check file content modification. (before, after the editor execution).
before = IO.read('tmp/#{#file}', {mode: 'rb'})
system("start /wait tmp/#{#file}")
after = IO.read('tmp/#{#file}', {mode: 'rb'})
# Check the file content modification.
if before != after:
# File changed!
If you're editing a huge file, IO::read will consume memroy accordingly. Use File::mtime as Arup Rakshit suggested, if there's such huge file in your repository. (cons: false positive alarm for save without modification)

How to get superuser privileges in Ruby?

So, I've been working on a Ruby script that blocks reddit during my school hours (useful stuff). Here's the code:
require 'fileutils'
puts "-----------------------------------"
puts "Welcome to the hosts file modifier!"
puts "-----------------------------------"
puts "Option A: Use modified hosts"
puts "Option B: Use original hosts"
puts "Option C: Do nothing"
puts "Please enter your choice: "
input = gets.chomp.downcase
t = Time.now
# Time.now is used is conjunction with function 'original', in option 'b'
def modified
# This function copies the modified (redditblocking) hosts file from Documents to /etc
puts "Moving original hosts file out of /etc"
FileUtils.mv('/etc/hosts', '/Users/(usernameobscured)/Documents/OriginalHosts/hosts')
puts "Done. Now copying modified hosts to /etc"
FileUtils.cp('/Users/(usernameobscured)/Documents/ModifiedHosts/hosts', '/etc/hosts')
puts "Done"
end
def original
# This function deletes the modified hosts file from /etc (since we have a copy in Documents)
# and then moves the original hosts file back to /etc
puts "Deleting modified hosts file from /etc"
FileUtils.rm_rf('etc/hosts')
puts "Done. Now copying original hosts to /etc"
FileUtils.mv('/Users/(usernameobscured)/Documents/OriginalHosts/hosts', '/etc/hosts')
puts "Done"
end
def nothing
# This does... nothing. Literally.
puts "Doing nothing"
end
if input == 'a'
modified
end
if input == 'b'
# Here's when using Time.now becomes helpful: if the hour of the day is less than 5PM,
# then the original hosts file can't be moved back (don't wanna be on reddit during school hours!)
if t.hour > 17
original
elsif t.hour < 17
puts "Too early to use original hosts file. Come back at 5PM"
end
end
if input == 'c'
# Nothing...
nothing
end
As you can see, it moves a modified hosts file from my Documents folder to /etc. The problem I'm having though, as per OS X/Unix security measures, is that I have to run the script via sudo or logged in as root. This is a minor nuisance, however, it's one that I believe can be fixed within the code. How can I get superuser privileges, OR write access to /etc temporarily, via my ruby script, so that I can simply run the script without sudo/root?
Per Unix security model, it is not possible to gain root access without some sort of external intervention (setuid set to the executable, running as root user). Otherwise we would have a gaping security hole.
I am not clear what is exactly your issue of using sudo or rvmsudo or against setting the script setuid (it is possible to configure sudo to not require password for narrowly defined set of commands).
I would just suggest making the various versions of host files group writable by a group that you are member of.
According to this site : http://ruby.about.com/od/rubyversionmanager/qt/Rvm-And-Sudo.htm
you can start executing the script using the rvmsudo command. In your terminal window or shell script:
rvmsudo ruby blockreddit.rb

Resources