Is there no convenience method for !nil? - ruby

I think I would see my code better if I would ask myself object.not_nil? vs !object.nil?. So my question: Is there really no convenience method for !nil? to sugar things up? Is it in front of my eyes and I cannot see it or am I just missing an important point?

How about this?
not object.nil?
But the easier thing to do would be to check for the "truthiness" of by testing the variable itself. Since nil is implicitly false you can just check object.

You can introduce the sugar at an upper level. Instead of:
if not object.nil?
you can write:
unless object.nil?

What about this ?
if object
# sth
end
It is not the same as it will not be executed if object is false but depending on you code, it could be better.
Another solution (which is not the same either), as you tagged your question with ruby-on-rails-3 : using present? which will not execute the block for [] or {} unlike !object.nil?.
Again another one depending of the case : using unless which won't be really nice if your condition is more complex (with && and/or ||).
If your condition is of this form :
if !object.nil? && object.something?
# sth
end
You can use try, as you are using Rails, like this :
if object.try(:something?)
# sth
end
In all the other cases, !object.nil? or not object.nil? stays the best solution I guess.

When convenience around #nil? is discussed, Activesupport's methods #blank? and #present? shouldn't be forgotten either.

Not that you'd necessarily want to, but you can introduce not_nil? yourself:
class Object
def not_nil?
!self.nil?
end
end
then you can do things like:
nil.not_nil?
==> false
3.not_nil?
==> true
a = []
a.not_nil?
==> true

Related

Recursively check if nested elements exist

Just to give you a background, I'm using Ruby for creating automated tests along with Selenium, Cucumber, Capybara and SitePrism. I have some tests that need to check the text of a certain element on the page, for example:
def get_section_id
return section.top.course.section_id.text
end
However, I would like to check if all the parent elements exist before calling .text on the nested course_and_section_id element. For example, to check the text of this particular element I would do:
if(has_section? && section.has_top? && section.top.has_course? && section.top.course.has_section_id?)
return section.top.course.section_id.text
end
Is there any way to recursively check if something exists in Ruby like this? Something that could be called like: has_text?(section.top.course.section_id) maybe?
There is nothing builtin to ruby that would do this because the methods you're calling return the element, or raise an exception. If they returned the element or nil then the suggestion of Cary Swoveland to use &. would be the answer.
The critical thing to remember here is what you're actually trying to do. Since you're writing automated tests, you're (most likely) not trying to check whether or not the elements exist (tests should be predictable and repeatable so you should know the elements are going to exist) but rather just wait for the elements to exist before getting the text. This means what you really want is probably more like
def get_section_id
wait_until_section_visible
section.wait_until_top_visible
section.top.wait_until_course_visible
section.top.course.wait_until_section_id_visible
return section.top.course.section_id.text
end
You can write a helper method to make that easier, something like
def get_text_from_nested_element(*args)
args.reduce(self) do |scope, arg|
scope.send("wait_until_#{arg}_visible")
scope.send(arg)
end.text
end
which could be called as
def get_section_id
get_text_from_nested_element(:section, :top, :course, :section_id)
end
It sounds like you may want something like the following.
arr = [section, :top, :course, :section_id, :text]
arr.reduce { |e,m| e && e.respond_to?(m) && e.public_send(m) }
Because reduce has no argument the initial value of the memo e is section. If e becomes nil or false it will remain that value.
Whilst this is a bit outdated, the fact that &. won't work here when it is the most elegant perhaps gives rise for this being a useful feature
If you can raise it on GH with a sample page where this would be useful then we could look at getting it introduced
Luke

Ruby: "if !object.nil?" or "if object"

Are they the same when used in an if/else/end statement? What do you usually do? I'm wondering if there are any subtle differences or edge cases where object and !object.nil? would respond differently.
There are differences. For example:
false.nil?
# => false
So:
if !false.nil?
'foo'
end
# => "foo"
if false
'foo'
end
# => nil
As #tokland suggested, in most cases using !obj.nil? construction is unnecessary.
There is one and only one case in which !object.nil? and object evaluate to different results in a boolean context and that is if object is false. In all other situations the result is the same.
With this, I think we can answer your real question (which is: Is there any situation where I must use if !object.nil? instead of just if object when protecting against object being nil?):
No, you can always use if object if you want to check against nil.
if object tests if object isn't either nil or false.
!object.nil? tests if object isn't nil. (Rubydoc)
So when object is false, they have different values.
Well. if object will behave differently from if !object.nil? if object=false.
That's about it.
Objects can override nil? but they cannot be falsely unless they are nil or false. Personally I use nil? or ActiveSupport's present? so that I maintain that flexibility. I also think it reads a bit better.

Preferred way to write true AND false conditional in Ruby

I apologize if this question is answered somewhere but I'm not positive I'm phrasing it right for Google, and I haven't seen it in any style guides.
Since Ruby has multiple ways to show negativity in a conditional, what is the preferred way to write a conditional that is checking that one part is true and one part is false? Example:
if array && !array.include?('Bob')
#do stuff!
But you could also say:
if array
#do stuff! unless array.include?('Bob')
or:
if array && not array.include?('Bob')
#do stuff
or:
if !array.nil? && !array.include?('Bob')
or a wacky double unless:
unless array.nil?
#do stuff unless array.include?('Bob')
And several others. Any idea which is considered the most Rubyish? Sources to back your opinion up?
As far as documented guidelines, the only thing that i can think of is the Google guide that admonishes "don't use and and or; always use && and || instead.".
Other than that, it somewhat depends on the context. If all you have is code to be executed if one condition is true and the other false, then I would definitely put them in a single if with && !:
if array && !array.include?('Bob')
#do stuff!
On the other hand, you might have additonal code that gets executed if the first condition is true even if the second one is also true; in that case, the nested unless or if makes sense:
if array
do stuff! unless array.include? 'Bob'
do other stuff anyway
end
Does not improve readability, but still interesting.
If you use Rails you can use ActiveSupport try extension like this:
if array.try(:include?, 'Bob')
# Do stuff

Built-in way to determine whether a string is a Ruby reserved word?

Is there something built-in with Ruby to determine if a string is a reserved word? Something like "next".is_keyword??
The only way I can think of is loading an array with all the keywords you know about.
class String
def is_keyword?
%w{__FILE__ __LINE__ alias and begin BEGIN break case class def defined? do else elsif end END ensure false for if in module next nil not or redo rescue retry return self super then true undef unless until when while yield}.include? self
end
end
"foobar".is_keyword? # => false
"for".is_keyword? # => true
For reference:
I know this isn't a built-in way, it's just the only way I could think of. Don't downvote me for it.
The list I included is that of true keywords. public, protected and friends aren't really keywords, just the names of important methods which are called during the creation of modules or classes. You can think of it as elements of the Ruby DSL.
As far as I know, protected isn't really a reserved word. It's just the name of an important method.
http://wiki.rubyonrails.org/rails/pages/reservedwords lists reserved words you can't use (some of them only apply if you're using Rails or its dependencies), and method names that can cause problems.
If this doesn't fully answer your question, can you define more fully whether you're interested in method names or variable names, and whether you're worried about words that can't be used at all, or words that may cause other things to go wrong?
Use Ruby gem rubykeyword. It does more than identifying the keyword. string.keyword? tells you if its keyword or not. string.define gives a definition of the keyword. There is string.example too.
If you have a class where you want to implement a method called "protected", then before you define that method make an instance of that class and call
instance.methods
This will show you all the methods inherited for the class, and if "protected" is there then it is reserved by ruby.

Tips on understanding Ruby syntax, when to use ?, and unless

Is the keyword unless the same as if?
When do you use ??
I've seen:
if someobject?
I know it checks against nil correct?
Is the keyword 'unless' the same as 'if' ?
No, it's the opposite.
unless foo is the same as if !foo
if someobject?
I know it checks against nil correct?
No it calls a method named someobject?. I.e. the ? is just part of the method name.
? can be used in methodnames, but only as the last character. Conventionally it is used to name methods which return a boolean value (i.e. either true or false).
? can also be used as part of the conditional operator condition ? then_part : else_part, but that's not how it is used in your example.
unless is actually the opposite of if. unless condition is equivalent to if !condition.
Which one you use depends on what feels more natural to the intention you're expressing in code.
e.g.
unless file_exists?
# create file
end
vs.
if !file_exists?
# create file
end
Regarding ?, there is a convention for boolean methods in Ruby to end with a ?.
This statement:
unless conditional expression
Is the equivalent to:
if not (conditional expression)
In Ruby you can end your method names with a question mark which is normally used to show that it is a boolean method.
With Rails a check against nil would look like this:
someobject.nil?
This calls the nil?() method of the object, which returns true for NilObject and false for anything else.
I think the convention for ?-suffix is to use it when naming a method that returns a boolean value. It is not a special character, but is used to make the name of the method easier to understand, or at least I think that's what the intention was. It's to make it clear that the method is like asking a question: it shouldn't change anything, only return some kind of status...
There's also !-suffix that I think by convention means that the method may have side-effects or may modify the object it is called on (rather than return a modified copy). Either way, the ! is to make you think carefully about calling such a method and to make sure you understand what that method does.
I don't think anything enforces these conventions (I've never tried to break them) so of course you could abuse them horribly, but your fellow developers would not be happy working with your code.
for unless see here: http://railstips.org/blog/archives/2008/12/01/unless-the-abused-ruby-conditional/
if someobject?
The appending of a '?' here only means that it returns a boolean.

Resources