Is there a difference between Ruby's Hash "value?" and "has_value?" - ruby

I'm looking at Hash docs for has_value? and value?. However the link for value? leads to duplicate information about has_value?.
value? seems to work identically to has_value? (Ruby 3.02).
Does this mean value? is becoming deprecated or is this a documentation error?

You can check if they are identical by comparing their method objects:
Hash.instance_method(:value?) == Hash.instance_method(:has_value?)
#=> true
UnboundMethod#== returns true if the methods refer to the same implementation.
Does this mean value? is becoming deprecated or is this a documentation error?
It seems to be a documentation error. The docs from the official website are more explicit regarding the alias:
https://docs.ruby-lang.org/en/3.0.0/Hash.html#method-i-has_value-3F
has_value?(value) → true or false
Returns true if value is a value in self, otherwise false.
Also aliased as: value?
However, the entry for value? doesn't have a heading: (the bold value?(value) → true or false part is missing)
https://docs.ruby-lang.org/en/3.0.0/Hash.html#method-i-value-3F
Returns true if value is a value in self, otherwise false.
Alias for: has_value?

Related

Why does `defined?` return a string or nil?

In ruby, why would defined? return a string? Most other ruby methods ending with a ? return a boolean.
Was this a hack to support a feature request, or was there intentional misuse of ruby convention, and why?
Examples:
defined?(super)
=> "super"
defined?(nil)
=> "nil"
defined?(Object)
=> "constant"
No, it was neither a hack nor a misuse of Ruby convention. As matz writes in ruby-talk 7986:
The '?' methods ... return either
(a) true or false
(b) non-false informative value or nil
defined? falls into (b).
Also, as commenters have pointed out, defined? is not a method. Matz expands in ruby-talk 1637:
[defined? is] a control structure. Not everything is a message send in Ruby, e.g. control structures, variables, blocks are not objects. defined? is among these things.
As sawa points out defined? is not actually a method.
If it were, the Ruby source code docs states this is allowed for methods that end in a question mark.
Methods that end with a question mark by convention return boolean. But they may not always return just true or false. Often they will may return an object to indicate a true value (or “truthy” value).
ref: https://github.com/ruby/ruby/blob/c8b3f1b470e343e7408ab5883f046b1056d94ccc/doc/syntax/methods.rdoc

What are the options to Capybara's have_selector?

I got this error in RSpec. Are there any docs for have_selector that explain each key in the options hash and what exactly it does?
invalid keys :content, should be one of :text, :visible, :between, :count, :maximum, :minimum, :exact, :match, :wait
capybara provides this method to rspec. capybara's docs don't make it easy to find the answer to your question, so let's follow the source:
have_selector is in Capybara::RSpecMatchers. It delegates to the nested class HaveSelector, which delegates to the method assert_selector.
assert_selector is in Capybara::Node::Matchers. (So is a method has_selector?, although that's not what rspec calls.) assert_selector's rdoc documents the :count option. It also says "It also accepts all options that Finders#all accepts, such as :text and :visible." Clicking through to Finders#all finally gets us to the documentation of all the options:
Options Hash (options):
text (String, Regexp) — Only find elements which contain this text or match this regexp
visible (Boolean) — Only find elements that are visible on the page. Setting this to false finds - invisible and visible elements.
count (Integer) — Exact number of matches that are expected to be found
maximum (Integer) — Maximum number of matches that are expected to be found
minimum (Integer) — Minimum number of matches that are expected to be found
between (Range) — Number of matches found must be within the given range
exact (Boolean) — Control whether is expressions in the given XPath match exactly or partially

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.

Ruby's 'is_a?' is returning false for built-in types, what's happening?

I've only been learning the deep parts of Ruby for a few months so apologies if this is a bit of a dumb question. I'm attempting to recursively iterate through an Array that may contain nested Arrays and as such I need to check the type of the current element. I have the following code as a small test:
arr = [ 1..2, [3..4, [5..6]], [7..8, [9..10]] ]
arr.each do |node|
p node.class
p node.instance_of? Array
end
When I run it, I get the following output:
Range
false
Array
false
Array
false
I expected the last two to return True, given I have an Array containing a Range and two nested Arrays.
What's even weirder, is if I write the following:
node.class.name == "Array"
It returns True, as it should.
What's happening here?
Ruby Version: MRI 1.9.3-p194
Note: I eventually realised that this was occurring due to the way I namespace my code using modules to avoid code-collision, like so, but also verify object identity in a naughty way:
module MyProg
class MyClass
attr_reader :my_array
def initialize(size)
#my_array = Array.new(size)
end
end
end
MyProg::MyClass.new
Doing this isolates your code but has the downfall of causing all class lookups to be resolved starting from under your namespace. This means that in the above example, my_array.class would actually resolve to MyProg::Array instead of the global Array class.
If you namespace like this and you still want to use this method, you can remedy it by using the double-colon global identifier before the class to force Ruby to begin lookup from the global namespace:
arr.is_a? ::Array
arr.is_a? ::String
Given Ruby's Duck Typing abilities however (and for better code maintenance later on), you should really be testing the behaviour of the object as-per Peter's suggestion below. As such I'm marking his answer as correct for some excellent help given to a learner!
I wrote another answer, but one major question is - why are you doing this? Why not, instead, just call flatten on the array so you just get the entries? Or, check for the behavior of the objects instead. You might need to give more detail about what you require.
You really mean is_a?, which is a more general test to see if the node is of type Array, rather than a specific instance of the specific Array class that you mention. See here for more details. But if you just use is_a? everything will make sense.
I ran your code and got these results.
Range
false
Array
true
Array
true
I'm running ruby 1.9.3p125

In ruby, is truthiness idiomatic for a method name ending with a question mark?

Is it normal for methods with a question mark to return something that's truthy (for example, a number) to indicate that something is true, or should true itself be returned?
Are there any examples of truthiness being used in the Ruby standard library or by Rails, for example?
Background: Someone wrote a String#int? method in an answer to a separate question, which returned an integer to represent true, and nil to represent false. Another user was surprised at not returning a boolean.
Adding a ? to a method name in Ruby is idiomatic that the method will return true or false. Object#nil? is a good example. In fact, Object has a lot of good examples of truthiness checks.
It is usual for methods ending with ? to return either true or false but it is not systematic and no core method will assume it.
An example in the core classes is Numeric#nonzero? which never returns true or false.
42.nonzero? # => 42
The library Set has add? and delete? too. I wish Enumerable#one? returned nil or false to distinguish cases where the count is zero from when it is greater than one.
A similar example are the comparison operators (<, >, ...), which usually return only true or false. Here again exceptions exist for Module's operators that will return nil instead when the two modules are not related:
Array > Enumerable # => false
Array > Fixnum # => nil
There are two answers to your question, and both are valid:
Technically, anything returning a false or nil value acts as a false boolean when doing a conditional test, just as a non-nil or true value acts as a true. So, the method in question will work correctly for most times you'd want to know if something is an integer.
But stylistically a method that ends with '?' should return either a Boolean true or false and only those.
The method in question doesn't really play nicely with our expectations and fails the POLS ("principle of least surprise") because you can reasonably expect a Boolean value being returned, and get an integer or a nil. THAT could lead to unpleasant surprises in code when it fails with an unexpected nil or a Fixnum value.
So, while it's a valid method, it's not a good method, and I would have brought it up in a code review. And that leads to a separate discussion of how subtle things like that can enhance or hurt code maintenance, but that's an entirely different discussion.
I renamed the method in question to remove the ?, which was really not important to the question being answered. Scanning through the core functions that end in ?s, the only ones I spotted that returned data or nil were the add? and delete? methods on Set.

Resources