What does the fail keyword do in Ruby?
In Ruby, fail
is synonymous with raise
. The fail
keyword is a method of the Kernel
module which is included by the class Object
. The fail
method raises a runtime error just like the raise
keyword.
The fail
method has three overloads:
fail
: raises aRuntimeError
without an error message.fail(string)
: raises aRuntimeError
with the string argument as an error message:fail "Failed to open file"
fail(exception [, string [, array]])
: raises an exception of classexception
(first argument) with an optional error message (second argument) and callback information (third argument).Example: Assume you define a function which should fail if given a bad argument. It is better to raise an
ArgumentError
and not aRuntimeError
:fail ArgumentError, "Illegal String"
Another Example: You can pass the whole backtrace to the
fail
method so you can access the trace inside therescue
block:fail ArgumentError, "Illegal String", caller
caller
is a Kernel method which returns the backtrace as an array of strings in the formfile:line: in 'method'
.
With no arguments, raises the exception in $! or raises a RuntimeError
if $! is nil. With a single String argument, raises a RuntimeError
with the string as a message. Otherwise, the first parameter should be
the name of an Exception class (or an object that returns an Exception
object when sent an exception message). The optional second parameter
sets the message associated with the exception, and the third
parameter is an array of callback information. Exceptions are caught
by the rescue clause of begin...end blocks.
Source: Ruby Documentation on the Kernel Module.
Fail vs. raise in Ruby : Should we really believe the style guide?
use 'raise' for exceptions to be caught, and 'fail' for serious errors which are not meant to be handled
This is not what the official style guide or the link you provided say on the matter.
What is meant here is use raise
only in rescue
blocks. Aka use fail
when you want to say something is failing and use raise
when rethrowing an exception.
As for the "does it matter" part - it is not one of the most hardcore strictly followed rules, but you could make the same argument for any convention. You should follow in that order:
- Your project style guide
- Your company style guide
- The community style guide
Ideally, the three should be the same.
Update: As of this PR (December 2015), the convention is to always use raise
.
Need 'return' statement following 'fail' call in a Ruby method?
No, you don't need the return.
def do_something
puts "start"
fail NotAuthenticatedError
puts "this doesn't print"
end
That code will never get to the last line.
Check out:
what-does-the-fail-keyword-do-in-ruby
Why are tests failing in Ruby on Rails?
You're mixing up two different kinds of tests.
The first is functional controller tests in the form of ActionController::TestCase
which you probably have in your book. These are tests that create a mocked request object and pass it to an instance of the controller. The use of these is greatly discouraged outside of legacy apps since they tend to let tons of bugs through. In functional tests you would write post :create, params: { product: { ... }}
because you are actually calling the create method on the controller instance.
The second is integration tests in the form of ActionDispatch::IntegrationTest
where you send actual HTTP requests to your Rails application. This is the modern approach and it's just as fast as functional tests in modern versions of Rails which was not the case when the book was written.
In an integration test you pass a path or url:
post '/products', params: { product: ... }
A second issue is the mandatory separation the of keyword parameters that was introduced in Rails 5.
In previous versions of Rails you could call:
get '/foo', bar: 1, baz: 2
And Rails would treat any unknown keys (not params, headers, format, etc) as parameters which was the source of many bugs. In Rails 5+ you explicitly need to pass parameters in the params option.
get '/foo', params: { bar: 1, baz: 2 }
I would suggest you complement the book with some more modern sources or get a newer edition as quite a lot has changed since Rails 4 and following a book that old in Rails 6 is going to be painful.
Why would Ruby fail equality on 2 floats that appear the same?
Floating-point numbers cannot precisely represent all decimal numbers within their range. For example, 0.9 is not exactly 0.9, it's a number really close to 0.9 that winds up being printed as it in most cases. As you do floating-point calculations, these errors can accumulate and you wind up with something very close to the right number but not exactly equal to it. For example, 0.3 * 3 == 0.9
will return false
. This is the case in every computer language you will ever use — it's just how binary floating-point math works. See, for example, this question about Haskell.
To test for floating point equality, you generally want to test whether the number is within some tiny range of the target. So, for example:
def float_equal(a, b)
if a + 0.00001 > b and a - 0.00001 < b
true
else
false
end
end
You can also use the BigDecimal class in Ruby to represent arbitrary decimal numbers.
If this is a test case, you can use assert_in_delta
:
def test_some_object_total_is_calculated_correctly
assert_in_delta 22.23, some_object.total, 0.01
end
Why is yield not passing the result to block (Rails)?
In your controller you need to have a variable for the result.
def create
Command.run(params) do |result|
if result
render json: { message: 'Successfully processed request' }, status: :success
else
render json: { message: 'Encountered an error' }, status: :bad_request
end
return
end
render json: { message: 'Encountered an error' }, status: :bad_request
end
(EDIT)
Also, you are calling the class method which call the instance method. You have to pass the block from the calling code to the instance method you are calling.
def self.run(params, &block)
new.run(params, &block)
end
Why does this Ruby code using char.upcase! fail but char = char.upcase works?
This is due to the definition of upcase!
and downcase!
. Here's upcase!
Upcases the contents of str, returning nil if no changes were made. Note: case replacement is effective only in ASCII region.
Notice that it returns nil
if no changes were made. In this case, if the character you are iterating over is already in the correct case, it'll return nil
and effectively remove the character from the string as part of your map
function.
In your specific example, you'll notice every other character is being removed because it's already in lower case and downcase!
is returning nil
.
loop next if fail
You can continue beyond the first failed connection attempt by handling the exception raised by Net::Telnet::initialize
. You'll find you aren't getting the error you think you're getting:
begin
tn = Net::Telnet::new("Host" => "#{hostname}",
"Timeout" => false,
"Prompt" => /[$%#>] \z/n)
rescue => e
puts "Unable to connect to #{hostname}: #{e.message}"
next
end
Produces
Unable to connect to host1: getaddrinfo: nodename nor servname provided, or not known
That is, you're not actually providing a host name. The argument isn't called "Host"
, it's called "host"
, and case matters. Ruby options are also typically passed as symbols, not strings. Try this:
tn = Net::Telnet::new(:host => "#{hostname}",
:timeout => false,
:prompt => /[$%#>] \z/n)
Now you'll get the error you were expecting:
Unable to connect to host1: Connection refused - connect(2)
Rspec: How do I make my passing tests fail?
create_client
raises the ArgumentError
, because it expects three keyword arguments and you are passing only one: (maybe you should have tested your helper, too)
def create_client(access_token:, access_key:, environment:)
# intentionally left empty
end
create_client(access_key: nil)
# in `create_client': missing keywords: access_token, environment (ArgumentError)
You could use default values in your helper to overcome this:
def create_client(access_token: :foo, access_key: :bar, environment: :baz)
Contentstack::Client.new(access_token: access_token, access_key: access_key, environment: environment)
end
create_client(access_key: nil)
# in `validate_configuration!': You must specify an access_key (ArgumentError)
Finally, you could be more specific regarding the error message:
expect { ... }.to raise_error(ArgumentError, 'You must specify an access_key')
Related Topics
Given the Session Key and Secret, How to Decrypt Rails Cookies
Uninitialized Constant Rake::Dsl in Ruby Gem
Edit Each Line in a File in Ruby
How to Reverse Ruby's Include Function
How to Order Files by Last Modified Time in Ruby
Ror + Unable to Install Tiny_Tds
How to Resolve Ruby Error (Missing Psych)
How to Share Variables Across My .Rb Files
Rails Migration Changing Column to Use Postgres Arrays
Write CSV in Ruby 1.9 and CSV::Writer
Param Is Missing or the Value Is Empty: User Rails 4