Ruby or ROR - arguments of function separated by '||' - ruby-on-rails

I've just encountered an interesting piece of code. I'd like to determine if it's a ruby standard or a rails convention.
redirect_to(session[:return_to] || users_path)
This prevents redirect_to :back from causing errors in some cases. In c++ something like that would mean a function with one bool argument. But here it seems to work another way - it takes that argument which isn't a nil I suppose. Can someone explain it to me and show an example definition of such a function, which takes arguments separated by '||'?
Bye

Boolean operators such as || and && return the last evaluated statement.
An example,
puts "hi" && "no"
The above will print "no" since both strings are considered 'truthy' and "no" was the last value called.
In this case the programmer is taking advantage of the short circuit nature of the || operator. So another example,
puts "hi" || "no"
The above will output "hi" since "hi" is considered truthy and or is short circuited "hi" was the last value called from the expression and will be returned.
You will see this kind of construct a lot in ruby, especially with ifs.
a = if true
"A will be set to this string"
else
"This will never happen"
end
puts a #=> A will be set to this string
Edit: As nick mentioned, it is important to note that only nil and false are treated as "falsy". Some interesting examples
a = nil || "hi"
puts a #=> "hi"
a = false || "hi"
puts a #=> "hi"
In these two cases the first argument is "falsy" so the "hi" is evaluated and returned (and then assigned to a)
a = Object.new || "hi"
puts a #=> <Object:0x10832420>
In this case (and for any other value as the first argument) Object.new is "true" and thus "hi" is never evaluated. In your particular example, the author was most likely testing for the presence (not nil) of session[:return_to]. This can be very useful but always remember that it may not work properly if false is a valid value.

This is called Short-Circuit Evaluation and it is common in many programming languages
In plain English, your statement says
"redirect to session[:return_to] if it is present, if not, redirect to users_path"

It calls redirect_to(session[:return_to]) if session[:return_to] is truthy (e.g. not nil or false).
If session[:return_to] is falsy, then it calls redirect_to(users_path).
See http://en.wikibooks.org/wiki/Ruby_Programming/Syntax/Operators#Logical_Or.

The logical OR is short-circuited, meaning that if the left-hand side is "true", or non-nil, then the value of the entire expression is the left-hand side, and the right-hand side is never considered. So if session[:return_to] is non-nil, it is the value of the expression. If it is nil, though, then the value of the expression is the value of the right-hand side, i.e. the value of user_path.
You can even write things like x || x = "foo", in which case x only gets reassigned if it was nil to begin with, but won't be touched if it is non-nil.
As for the function, it just takes a string, and it doesn't care what you plug in to the argument.

Related

Dynamic condition in ruby on rails

I have the following condition:
if "FIX_STRING 0,0,DYNAMIC_STRING" == "FIX_STRING #{integer_from_0_to_5},#{integer_from_0_to_5},#{DYNAMIC_STRING}"
true
else
false
end
How to make it dynamically like this?
if "FIX_STRING 0,0,DYNAMIC_STRING" == "FIX_STRING #{/0|1|2|3|4|5/},#{/0|1|2|3|4|5/},#{/A|B|C|D/}"
true
else
false
end
You're on the right track here, but you've got a very peculiar coding style. The first thing to point out is that a comparison like == already returns a boolean value of true or false, there's no reason for the if which then returns exactly the same thing.
The second thing is that you're comparing a string to another string, so they have to match exactly. Close enough does not count. If you evaluate your other string you get a mess:
"FIX_STRING (?-mix:0|1|2|3|4|5),(?-mix:0|1|2|3|4|5),(?-mix:A|B|C|D)"
Finally, if you're trying to test a string versus a regular expression, you do this:
PATTERN = /\AFIX_STRING [0-5],[0-5],[A-D]\z/
You can test this sort of thing on Rubular to get it right. Here [0-5] means anything in that range. It's short-hand for what you had.
Then you can test arbitrary strings versus this pattern:
"FIX_STRING 3,4,D".match(PATTERN)
# => #<MatchData "FIX_STRING 3,4,D">
So that matched.
Newer versions of Ruby have a match? method that only tests matches, it doesn't return what matched, which you might want to make use of if you're running on 2.3 or later. It's faster than the plain match method, though that only really matters if you're doing a lot of matches inside loops.

Ruby on Rails: Checking for valid regex does not work properly, high false rate

In my application I've got a procedure which should check if an input is valid or not. You can set up a regex for this input.
But in my case it returns false instead of true. And I can't find the problem.
My code looks like this:
gaps.each_index do | i |
if gaps[i].first.starts_with? "~"
# regular expression
begin
regex = gaps[i].first[1..-1]
# a pipe is used to seperate the regex from the solution-string
if regex.include? "|"
puts "REGEX FOUND ------------------------------------------"
regex = regex.split("|")[0..-2].join("|")
end
reg = Regexp.new(regex, true)
unless reg.match(data[i])
puts "REGEX WRONGGGG -------------------"
#wrong_indexes << i
end
rescue
end
else
# normal string
if data[i].nil? || data[i].strip != gaps[i].first.strip
#wrong_indexes << i
end
end
An example would be:
[[~berlin|berlin]]
The left one before the pipe is the regex and the right one next to the pipe is the correct solution.
This easy input should return true, but it doesn't.
Does anyone see the problem?
Thank you all
EDIT
Somewhere in this lines must be the problem:
if regex.include? "|"
puts "REGEX FOUND ------------------------------------------"
regex = regex.split("|")[0..-2].join("|")
end
reg = Regexp.new(regex, true)
unless reg.match(data[i])
Update: Result without ~
The whole point is that you are initializing regex using the Regexp constructor
Constructs a new regular expression from pattern, which can be either a String or a Regexp (in which case that regexp’s options are propagated, and new options may not be specified (a change as of Ruby 1.8).
However, when you pass the regex (obtained with regex.split("|")[0..-2].join("|")) to the constructor, it is a string, and reg = Regexp.new(regex, true) is getting ~berlin (or /berlin/i) as a literal string pattern. Thus, it actually is searching for something you do not expect.
See, regex= "[[/berlin/i|berlin]]" only finds a *literal /berlin/i text (see demo).
Also, you need to get the pattern from the [[...]], so strip these brackets with regex = regex.gsub(/\A\[+|\]+\z/, '').split("|")[0..-2].join("|").
Note you do not need to specify the case insensitive options, since you already pass true as the second parameter to Regexp.new, it is already case-insensitive.
If you are performing whole word lookup, add word boundaries: regex= "[[\\bberlin\\b|berlin]]" (see demo).

What does the operator ?= mean?

I have a hamlc (known as Haml + Inline CoffeeScript) which has a line like
- #variable1 ?= #object1.element[0]
I wonder if this means: if #object1.element[0] has a value then store it inside #variable1.
I cannot find any info about hamlc. Also, if what I understand is right, what if I want to add an else condition?
The ?= operator is known as the existential operator in CoffeeScript.
From the docs:
It's a little difficult to check for the existence of a variable in JavaScript. if (variable) ... comes close, but fails for zero, the empty string, and false. CoffeeScript's existential operator ? returns true unless a variable is null or undefined, which makes it analogous to Ruby's nil?
That means that the way it works is, using your example:
#variable1 ?= #object1.element[0]
If #variable1 is null or undefined, assign #object1.element[0] to it.
what if I want to add the condition for "else" ?
#variable1 =
if #variable1?
#object1.element[0]
else
# your else clause here

RoR: Why is this if-statement failing?

Why is the second if statement failing in the following code block? The output from the console indicates that the private parameter is 0, so it should be passing? The private parameter is from a checkbox in the new form, that I'm using to set a boolean field in the model.
if (((params[:note])[:text]) != "")
logger.debug("passed first test")
logger.debug(((params[:note])[:private]))
if (((params[:note])[:private]) == 0)
logger.debug("passed second test")
end
end
console output
passed first test
0
Completed in 61ms (DB: 1) | 302 Found [http://localhost/notes]
Thanks for reading.
Form fields are submitted as strings so params[:notes][:private] will actually contain "0" not 0.
You could use either params[:notes][:private] == "0" or params[:notes][:private].to_i == 0 to get the comparison you're after.
If you want to treat non-integer values (including empty strings and missing values) differently from 0, you should not use String#to_i. I would recommend checking the String value in these cases.
You can use Object#inspect (as mentioned by #sepp2k) and Object#class when debugging to get a better idea of what types things are. When using script/console, I find ap (or pp) to be rather handy.
A side note: In Ruby you don't need so many parentheses. Here's the your example after a little bit of cleanup:
unless params[:note][:text].blank?
logger.debug "passed first test"
logger.debug params[:note][:private].inspect
if params[:note][:private].to_i == 0
logger.debug "passed second test"
end
end
In cases where two expressions print the same, but aren't equal, you usually have different types. For example "0", :"0" and 0 both print as 0, but aren't actually equal to each other.
logger.debug(params[:note][:private].inspect) should give you more meaningful output, indicating the type of the object as well as the contents (i.e. if it's a string it's surrounded by quotes, if it's a symbol it starts with a colon, etc.).
The values in params are generally strings, so the value of params[:note][:private] is very probably "0", not 0.

Exclamation mark used with assert method in its parameters

Okay this has been lingering in my head for quite a while now.
In ruby on rails unit testing there is an exclamation mark with the assert method. Here is an example
test "No empty values to be inserted" do
product = Produce.new
assert !product.save
end
Let me know the function of the exclamation mark. Quick replies appreciated. Thanks.
! is Logical negation.
If product.save is truthy (that is, neither nil nor false), !product.save returns false.
If product.save is falsy (that is, either nil or false), !product.save returns true.
Therefore, assert !product.save means that product.save must return falsy for the test to pass.

Resources