def respond_to?(method, include_private = false)
super || #subject.respond_to?(method, include_private)
end
|| is an or operator, so what does || between methods mean?
Will it always call super unless super returns nil then evaluate #subject.respond_to because of short-circuiting for the || operator?
Edit: I think my question is not a duplicate because I know how the '||' operator work from other programming languages. I know what short-circuiting is. I just have never seen it used with just two methods without if statements involve.
The || operator means the same regardless of how complex the expressions are on each side of it.
A || B means:
evaluate A
if A == false or A == nil
evaluate B
return the value of B as the value of the A || B expression
otherwise return the value of A as the value of the A || B expression
Related
I commonly need to use this kind of methods where I have to check if an object exists and if this object returns a specific value or a behavior. Is that a better way to write this code?
def set_current_theme
if current_tenant && current_tenant.has_custom_domain?
#theme = Theme.last || Theme.create
end
end
At a first glance, I would just add one conditional: if current_tenant.has_custom_domain? and that should be enough. But the result is generally that there is no such method (in this case has_custom_domain?) for nil class.
Shorter (and i think better) way is to use &. (it's shorthand for try!) like this.
if current_tenant&.has_custom_domain?
#theme = Theme.last || Theme.create
end
What does &. (ampersand dot) mean in Ruby?
I would suggest early return (so called guard clause) instead of :if statement, because you don't have :else clause:
def set_current_theme
return unless current_tenant&.has_custom_domain?
#theme = Theme.last || Theme.create
end
I'm trying to substitute an expression unless the expression is one of two values.
def substitute_string (string)
string.gsub('abc', 'xyz') unless string == ('dabc' || 'eabc')
end
substitute_string('jjjjjabc')
=> 'jjjjjxyz'
substitute_string('dabc')
=> 'dabc'
substitute_string('eabc')
=> 'exyz'
I expected substitute_string('eabc') to return ('eabc') since I stated that in the unless block, which I passed two values.
I don't understand why this doesn't work, and what I can do to make 'eabc' return 'eabc'.
('dabc' || 'eabc') is a boolean expression that evaluates to true and returns 'dabc'.
Use two or's:
unless string == 'dabc' || string == 'eabc'
Or use =~ (regex pattern match)
unless string =~ /(dabc|eabc)/
Since you indicated you're using Rails, you can also use in? like this:
unless string.in? ['dabc', 'eabc']
It is because (1) 'dabc' || 'eabc' is equivalent to 'dabc', and nowhere in your code does 'eabc' appear in a meaningful way, and because (2) it only returns nil when the condition is met according to the way you used unless.
def substitute_string(string)
case string
when 'dabc', 'eabc' then string
else string.gsub('abc', 'xyz')
end
end
Apart from the fun of obscure technicalities about what is returned when and in what situations, I don't see a lot of merit in not being more explicit with the return. The very fact that this issue was brought and subsequently debated on SO is exactly why writing code (working code to be sure) in this obscure fashion will lead to confusion for developers interpreting this code, and leads to buggy software.
The only benefit I see to this is that it's on one line.
def substitute_string(string)
string.gsub('abc', 'xyz') unless ['dabc', 'eabc'].include?(string)
end
I personally would prefer the following as it makes it clear what your intentions are:
def substitute_string(string)
return string if ['dabc', 'eabc'].include?(string)
string.gsub('abc', 'xyz')
end
'dabc' || 'eabc' will always equal true since it just means condition or condition where condition is a string. Since a string is not nil or false it evaluates to true. You could check whether the string is in an array values instead:
def substitute_string(string)
string.gsub('abc', 'xyz') unless ['dabc', 'eabc'].include?(string)
end
How do i reduce the following code to one line in Ruby?
unless(current_facebook_user.nil?)
unless(current_facebook_user.client.nil?)
unless(current_facebook_user.client.default_params.nil?)
val = current_facebook_user.client.default_params
end
end
end
You can using the try() method from active_support/core_ext/object/try.rb introduced since Rails 2.3.2
val = current_facebook_user.try(:client).try(:default_params)
Method Try
Or directly using Safe navigation operator introduced since Ruby 2.3.0
val = current_facebook_user&.client&.default_params
documented here
more on Safe navigation operator
Use || operator in one unless: val = ... unless cond1 || cond2 || cond3
Or use && on negations of the conditions in if: val = ... if !cond1 && !cond2
You may not need the third check, as if .default_params is nil, val will be evaluated nil too (if it started nil, this is no problem; if it was already populated, you might want to keep the third guard there :-)
val = current_facebook_user.client.default_params if current_facebook_user && current_facebook_user.client && current_facebook_user.client.default_params
val = current_facebook_user.client.default_params unless current_facebook_user.nil? or current_facebook_user.client.nil? or current_facebook_user.client.default_params.nil?
I'm trying to skip over calculating some numbers when the result would be an attempt to insert NaN into the DB. My code is as follows:
unless #X = 0 || #Y = 0 || Z= 0 #Don't execute below code if any of the three values = 0
#Do some stuff with #X, #Y and #Z
end
I know that X,Y and Z are positive integers, as they should be, however this statement is not triggering the code block in the unless clause. Am I blatantly misusing the || operator?
You're using = the assignment operator. You want to be using == the equality operator. Your code should look like this:
unless #X == 0 || #Y == 0 || #Z == 0
...
end
You should be using a double equals (==) for comparison in an if or unless clause, not a single equals (=).
Especially when you want to compare with zero, there is a built in command in ruby which is faster than doing == 0.
unless #x.zero? or #y.zero? or #z.zero?
...
end
You can use either || or or here.
Currently I have the following 2 lines of code
errors.add_to_base I18n.t :error_message if value != 1
return false if !errors.blank?
Is it possible to condense this into 1 line of code? I need to do this in multiple places with different error message and condition. Also, "return false" is to stop the flow of an ActiveRecord lifecycle.
Hmm. If you know errors.blank? will be true unless the first condition fires then:
(errors.add_to_base I18n.t :error_message; return) if value != 1
Update: Aha, you are willing to define a method. How about a Proc object? It's better than a method here in that if the Proc block returns then the invocation will return from the surrounding method.
test = Proc.new do |cond, msg|
errors.add_to_base I18n.t msg if cond
return unless errors.blank?
end
# ...
test.call value != 1, :error_message
Note that you don't need to return false as a plain return will return nil and that will be good enough unless some sadist is doing something like f().class == NilClass. :-)
You can take advantage of how the boolean logic operators work and do something like this:
value != 1 && errors.add_to_base I18n.t :error_message && return false
Not very clear, I wouldn't recommend using it. Also if errors.add_to_base returns something that's "falseish" the return false wouldn't happen.
Remember: "Always code as if the person who will maintain your code is a violent psychopath who knows where you live”