Why can't I 'break' out of this Ruby block? - ruby

I have this Ruby block:
status = ''
build.parse do |entry|
puts "parsing an item"
puts entry.title
if entry.title =~ /FAILURE/ then
puts "failure"
status = "FAILURE"
else
status = "SUCCESS"
end
puts status
break entry if status == "FAILURE"
end
For some unknown reason to me I can't seem to break out of it? I realise the block is a little weird it's semi-copied from here:
http://macruby.labs.oreilly.com/ch03.html#_xml_parsing
Honestly my Ruby is poor but I'm trying to write a little mac app that involves some RSS parsing.
The regex matches and status gets set to "FAILURE" but it doesn't break out the block/loop. Am I doing something obviously wrong?
Cheers,
Adam

you dont need the 'then' in your if block
#entries = ["this is a FAILURE", "this is a success"]
status = ''
#entries.each do |entry|
if entry =~ /FAILURE/
puts "failure"
status = "failure"
else
status = "success"
end
puts "status == #{status}"
break if status == "failure"
end
as a side note, it would be more idiomatic to write this as:
status = #entries.any?{|e| e =~ /FAILURE/} ? 'failure' : 'succes'
when you are dealing with enumerable objects, like arrays it is nice to use the tools built into Ruby.
http://apidock.com/ruby/Enumerable/any%3F

Try break if status == "FAILURE"

Related

Ruby: void value expression while using if else with break

I am new to Ruby language. I am working on integrating the Danger to add checks on GitHub PR. One of the use case is to check if modified files in my PR contains particular change. I have added below code in DangerFile
filesArray = ["Resources/Config.plist", "Resources/Deployment.plist"]
def modified_files_contains_change(files, change)
does_contain_required_changes = false
for file in files do
message "diff in #{file}"
diff = git.diff_for_file(file)
patch_contains_change = diff.patch =~ #{change}
if diff && patch_contains_change
does_contain_required_changes = true
else
does_contain_required_changes = false
break
end
end
message "Does contain changes in all files => #{does_contain_required_changes}"
does_contain_required_changes
end
if modified_files_contains_change(files, change)
warn "Some useful warning message goes here"
end
While running this on my CI, I am getting below error
[!] Invalid `Dangerfile` file: void value expression.
# from Dangerfile:33
# -------------------------------------------
# does_contain_required_changes = false
> break
# end
# end
# -------------------------------------------
I tried searching but didn't understand the what's going wrong. Can someone please help me understand what is the exact issue? Thanks in advance.
=~ #{change} is read as just =~ because # starts an inline comment. =~ expects a regular expression on one of sides. To fix the issue, change the line below:
patch_contains_change = diff.patch =~ #{change}
to:
patch_contains_change = diff.patch =~ Regexp.new(change)
This assumes you are passing a string as change.
Also, this would be more or less rubyish way to accomplish the task:
def modified_files_contains_change(files, change)
does_contain_required_changes =
files.all? do |file|
message "diff in #{file}"
# break will immediately exit the `all?` unless diff is present
break false unless diff = git.diff_for_file(file)
diff.patch =~ Regexp.new(change)
end
message "Does contain changes in all files => #{does_contain_required_changes}"
does_contain_required_changes
end
To return a file where we found an issue:
def modified_files_contains_change(files, change)
problematic_file =
files.detect do |file|
message "diff in #{file}"
(diff = git.diff_for_file(file)).nil? || diff.patch !~ Regexp.new(change)
end
does_contain_required_changes = problematic_file.nil?
if does_contain_required_changes
message "All good!"
else
message "We have issues with file #{problematic_file}"
end
does_contain_required_changes
end

Ruby conditional issue?

I have this code:
def name_of_client
puts "Hello sir/madam; please enter your name: "
name = gets.chomp.upcase
puts "Welcome to the Great Bank, #{name}. Would you like to enter your seriously insecure account? (Y/N)"
end
def get_response
answer = gets
if answer == "Y" || answer == "y"
puts 'Sure thing... '
elsif answer == "N" || answer== "n"
puts "Logging you out now. "
end
end
name_of_client
get_response
Why are the strings not printed when I type "Y" or "N"?
gets adds a new line to the answer variable. use gets.chomp or gets.strip instead. In future, I would recommend using the pry gem as shown below which pauses execution just like debugger does in javascript. To install pry open your terminal window (assuming you're running linux or macOS) and run gem install pry. You can then use it as shown below.
require "pry"
def get_response
answer = gets.strip
binding.pry
if answer == "Y" || answer == "y"
puts 'Sure thing... '
elsif answer == "N" || answer== "n"
puts "Logging you out now. "
end
end
get_response

Deleting a row from a CSV file with Ruby

I've seen similar answers to this question but I think I need something more specific to my code. Basically I've called the row from the CSV file but now I need to delete the called row. Sounds simple as I write this yet here I am asking you all for help. I know there is a lot of code here but I figured the more there is the more easier you will be able to understand the context. Apologies if there is too much noise in the code.
def delete_user_menu
puts "============================================"
delete_users_active_list
puts " "
puts "Please type in the name of the user you wish to eradicate: "
print "> "
eradicate(gets.chomp)
end
def eradicate(delete_input)
delete_row = delete_authentication(delete_input)
if delete_row
puts "Are you sure you want to delete #{delete_input} from the database?"
puts "[y]es or [n]o"
print "> "
delete_answer = gets.chomp
if delete_answer == "y"
delete_user
after_deletion_menu
elsif delete_answer == "n"
puts "Close call! Taking you back to main menu."
sleep 2
admin_main_menu
else
puts "Input not recognised. Please try again."
eradicate(delete_input)
end
else
puts "User not recognized. Please try again."
sleep 1
delete_user_menu
end
end
def delete_user
# this is where the delete user function needs to go
after_deletion_menu
end
def after_deletion_menu
puts " "
puts "User deleted! What would you like to do now?"
puts "1. Delete another user"
puts "2. Back to main menu"
print "> "
after_deletion_choice = gets.chomp
if after_deletion_choice == "1"
delete_user_menu
elsif after_deletion_choice == "2"
admin_main_menu
else
puts "Input not recognized. Please try again."
after_deletion_menu
end
end
def delete_users_active_list
CSV.foreach("./users.csv", headers: true) do |row|
username = row['username']
puts "~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~"
puts "Username: #{username}"
end
end
def delete_authentication(username)
CSV.open('users.csv', headers: true).find { |row| row['username'] == username }
end
I've had a look at this question How to remove a row from a CSV with Ruby
but I don't fully understand the answers, hence why I'm here. Any help is much appreciated.
I looked at the link. First, they are reading the entire csv file into table:
table = CSV.table(#csvfile)
then deleting the row from table:
table.delete_if do |row|
row[:foo] == 'true'
end
Finally, they are completely replacing the original file with the new table minus the row:
File.open(#csvfile, 'w') do |f|
f.write(table.to_csv)
end
This is generally how you have to do this kind of operation when you are dealing with a file. It's not like a database.
EDIT - in your case:
delete_user(delete_input)
...
def delete_user(user)
...
table.delete_if { |row| row[:username] == user }
...

Recursion in Ruby isnt working like I think it should

I don't understand why this method isn't working. when I put in a value that should pass the if statement it doesn't work.
def getBase
puts "What is the base URL for the test?"
x = gets
if (x.include? 'http://') && ((x.split('.').at(x.split('.').length - 1).length) == 3)
return x
else
puts "That is in the incorrect format."
puts "Please format your url like this"
puts "http://example.com"
getBase
end
end
input 'http://test.com'
result: statement repeats and does not exit recursion
When you get input with gets it includes the newline \n at the end (from the user hitting return). So your x is actually "http://test.com\n".
To get rid of this use String#chomp:
x = gets.chomp
That should do it.
If the purpose is to enforce correct URL format and/or make sure it's an HTTP URL, why don't you use a tool designed to do that? Ruby's URI class is your friend:
require 'uri'
URI.parse('http://foo.bar').is_a?(URI::HTTP)
=> true
URI.parse('ftp://foo.bar').is_a?(URI::HTTP)
=> false
URI.parse('file://foo.bar').is_a?(URI::HTTP)
=> false
URI.parse('foo.bar').is_a?(URI::HTTP)
=> false
I'd write the code more like this:
require 'uri'
def get_base
loop do
puts "What is the base URL for the test?"
x = gets.chomp
begin
uri = URI.parse(x)
return uri.to_s if uri.is_a?(URI::HTTP)
rescue URI::InvalidURIError
end
puts "That is in the incorrect format."
puts "Please format your URL like this:"
puts
puts " http://example.com"
end
end
puts "Got: #{ get_base() }"

ruby at_exit exit status

Can i determine selves process exit status in at_exit block?
at_exit do
if this_process_status.success?
print 'Success'
else
print 'Failure'
end
end
using idea from tadman
at_exit do
if $!.nil? || ($!.is_a?(SystemExit) && $!.success?)
print 'success'
else
code = $!.is_a?(SystemExit) ? $!.status : 1
print "failure with code #{code}"
end
end
or without Perlisms:
require 'English'
at_exit do
if $ERROR_INFO.nil? || ($ERROR_INFO.is_a?(SystemExit) && $ERROR_INFO.success?)
print 'success'
else
code = $ERROR_INFO.is_a?(SystemExit) ? $ERROR_INFO.status : 1
print "failure with code #{code}"
end
end
Although the documentation on this is really thin, $! is set to be the last exception that occurs, and after an exit() call this is a SystemExit exception. Putting those two together you get this:
at_exit do
if ($!.success?)
print 'Success'
else
print 'Failure'
end
end

Resources