RoR: Why is this if-statement failing? - ruby-on-rails

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.

Related

Open policy agent satisfy condition for all array items

Trying to wrap my head around this issue for a while - I have a JSON input which contains an array, say something like this:
{
"array" : [
{"foo": "bar"},
{"foo": "buzz"},
{"misbehaving": "object"}
]
}
My goal is to verify that all of the objects in the array satisfy the condition of having a field named foo (actual use-case is to make sure that all resources in cloud deployment have tags). My issue is that standard rego expressions are evaluated as "at least" and not "all", which means that expressions like:
all_have_foo_field {
input.array.foo
}
Are always returning true, even though some objects do not satisfy this. I've looked at this, but evaluating a regex returns true or false while my policy checks if field exists, meaning if it does not I get a 'var_is_unsafe' error.
Any ideas?
There are two ways to say "all fields of elements in X must match these conditions" (FOR ALL).
TLDR:
all_have_foo_field {
# use negation and a helper rule
not any_missing_foo_field
}
any_missing_foo_field {
some i
input.array[i]
not input.array[i].foo
}
OR
all_have_foo_field {
# use a comprehension
having_foo := {i | input.array[i].foo}
count(having_foo) == count(input.array)
}
The approach depends on the us case. If you want to know what elements do not satisfy the conditions, the comprehension is nice because you can use set arithmetic, e.g., {i | input.array[i]} - {i | input.array[i].foo} produces the set of array indices that do not have the field "foo". You probably want to assign these expressions to local variables for readability. See this section in the docs for more detail: https://www.openpolicyagent.org/docs/latest/policy-language/#universal-quantification-for-all.
In this case (as opposed to the answer you linked to) we don't have to use regex or anything like that since references to missing/undefined fields results in undefined and undefined propagates outward to the expression, query, rule, etc. This is covered to some extent in the Introduction.
All we have to do then is just refer to the field in question. Note, technically not input.array[i].foo would be TRUE if the "foo" field value false however in many cases undefined and false can be treated as interchangeable (they're not quite the same--false is a valid JSON value whereas undefined represents the lack of a value.) If you need to only match undefined then you have to assign the result of the reference to a local variable. In the comprehension case we can write:
# the set will contain all values i where field "foo" exists regardless
{i | _ = input.array[i].foo}
In the negation case we need an additional helper rule since not _ = input.array[i].foo would be "unsafe". We can write:
exists(value, key) { value[key] = _ }`
And now not exists(input[i], "foo") is only TRUE when the field "foo" is missing.
Note, differentiating between undefined and false is often not worth it--I recommend only doing so when necessary.

Break strings into substrings based on delimiters, with empty substrings

I am using LUA to create a table within a table, and am running into an issue. I need to also populate the NIL values that appear, but can not seem to get it right.
String being manipulated:
PatID = '07-26-27~L73F11341687Per^^^SCI^SP~N7N558300000Acc^'
for word in PatID:gmatch("[^\~w]+") do table.insert(PatIDTable,word) end
local _, PatIDCount = string.gsub(PatID,"~","")
PatIDTableB = {}
for i=1, PatIDCount+1 do
PatIDTableB[i] = {}
end
for j=1, #PatIDTable do
for word in PatIDTable[j]:gmatch("[^\^]+") do
table.insert(PatIDTableB[j], word)
end
end
This currently produces this output:
table
[1]=table
[1]='07-26-27'
[2]=table
[1]='L73F11341687Per'
[2]='SCI'
[3]='SP'
[3]=table
[1]='N7N558300000Acc'
But I need it to produce:
table
[1]=table
[1]='07-26-27'
[2]=table
[1]='L73F11341687Per'
[2]=''
[3]=''
[4]='SCI'
[5]='SP'
[3]=table
[1]='N7N558300000Acc'
[2]=''
EDIT:
I think I may have done a bad job explaining what it is I am looking for. It is not necessarily that I want the karats to be considered "NIL" or "empty", but rather, that they signify that a new string is to be started.
They are, I guess for lack of a better explanation, position identifiers.
So, for example:
L73F11341687Per^^^SCI^SP
actually translates to:
1. L73F11341687Per
2.
3.
4. SCI
5. SP
If I were to have
L73F11341687Per^12ABC^^SCI^SP
Then the positions are:
1. L73F11341687Per
2. 12ABC
3.
4. SCI
5. SP
And in turn, the table would be:
table
[1]=table
[1]='07-26-27'
[2]=table
[1]='L73F11341687Per'
[2]='12ABC'
[3]=''
[4]='SCI'
[5]='SP'
[3]=table
[1]='N7N558300000Acc'
[2]=''
Hopefully this sheds a little more light on what I'm trying to do.
Now that we've cleared up what the question is about, here's the issue.
Your gmatch pattern will return all of the matching substrings in the given string. However, your gmatch pattern uses "+". That means "one or more", which therefore cannot match an empty string. If it encounters a ^ character, it just skips it.
But, if you just tried :gmatch("[^\^]*"), which allows empty matches, the problem is that it would effectively turn every ^ character into an empty match. Which is not what you want.
What you want is to eat the ^ at the end of a substring. But, if you try :gmatch("([^\^])\^"), you'll find that it won't return the last string. That's because the last string doesn't end with ^, so it isn't a valid match.
The closest you can get with gmatch is this pattern: "([^\^]*)\^?". This has the downside of putting an empty string at the end. However, you can just remove that easily enough, since one will always be placed there.
local s0 = '07-26-27~L73F11341687Per^^^SCI^SP~N7N558300000Acc^'
local tt = {}
for s1 in (s0..'~'):gmatch'(.-)~' do
local t = {}
for s2 in (s1..'^'):gmatch'(.-)^' do
table.insert(t, s2)
end
table.insert(tt, t)
end

How to check if a value is empty in Lua?

What is the proper way to make a conditional which checks of something is or is not empty in Lua? if x == "" and f x ~= "" does not seem to work.
Lua is a dynamically type-based language.
Any variable can hold one of the following types: nil, boolean, number, string, table, function, thread, or userdata.
Any variable in a table (including _G, the table where globals reside) without a value gives a value of nil when indexed. When you set a table variable to nil, it essentially "undeclares" it (removing the entry from memory entirely).
When a local variable is declared, if it is not assigned immediately it is given a value of nil. Unlike table variable, when you set a local variable to nil, it does not "undeclare" it (it just has a value of nil).
In Lua, an empty string ("") is still a "value" - it's simply a string of size zero.
I recently ran across this problem as well. LuaSQL was returning empty strings if a database value was 'blank' (not null). A hacky approach, but here's how I solved it:
if (string.len(x) >= 1) then
...
end
I'm going to make an assumption that the OP means "how do you tell when a variable is unassigned".
Example:
local x
The variable x is "empty", it is initialized to "nil". (Not the text "nil", but an enumerated value that indicates that the variable is unassigned. In Lua that is defined as nil, in some other languages it is defined as NULL.)
Now assign x a value.
Example:
x=""
Now x is not nil.
Another example:
x=0
x is not nil.
Try running this code, it should make the situation clear to you.
local x
if x==nil then print("x is nil") end
x=0
if x==nil then print( "This line won't be written") end
x=""
if x==nil then print( "and this line won't be written") end
The first if statement will evaulate to true and the print statement will be called. The 2nd and 3rd if statements are false and the print statements will not be executed.
In conclusion, use "==nil" to check to see if a variable is "empty" (which is more properly said "nil").
You probably have spaces, newlines or other non-visible characters in your string. So you think it is "empty", but it isn't. This typically happens when you are taking input from the user, and has to type "enter" to finish - the "enter" ends up in the string.
What you need is a function that tells you whether the string is "blank" - either empty, or a list of spaces/tabs/newlines. Here's one way to do it:
function isBlank(x)
return not not tostring(x):find("^%s*$")
end
Usage:
if isBlank(x) then
-- ...
end

Ruby or ROR - arguments of function separated by '||'

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.

Conditional Regular Expression testing of a CSV

I am doing some client side validation in ASP.NET MVC and I found myself trying to do conditional validation on a set of items (ie, if the checkbox is checked then validate and visa versa). This was problematic, to say the least.
To get around this, I figured that I could "cheat" by having a hidden element that would contain all of the information for each set, thus the idea of a CSV string containing this information.
I already use a custom [HiddenRequired] attribute to validate if the hidden input contains a value, with success, but I thought as I will need to validate each piece of data in the csv, that a regular expression would solve this.
My regular expression work is extremely weak and after a good 2 hours I've almost given up.
This is an example of the csv string:
true,3,24,over,0.5
to explain:
true denotes if I should validate the rest. I need to conditionally switch in the regex using this
3 and 24 are integers and will only ever fall in the range 0-24.
over is a string and will either be over or under
0.5 is a decimal value, of unknown precision.
In the validation, all values should be present and at least of the correct type
Is there someone who can either provide such a regex or at least provide some hints, i'm really stuck!
Try this regex:
#"^(true,([01]?\d|2[0-4]),([01]?\d|2[0-4]),(over|under),\d+\.?\d+|false.*)$"
I'll try to explain it using comments. Feel free to ask if anything is unclear. =)
#"
^ # start of line
(
true, # literal true
([01]?\d # Either 0, 1, or nothing followed by a digit
| # or
2[0-4]), # 20 - 24
([01]?\d|2[0-4]), # again
(over|under), # over or under
\d+\.?\d+ # any number of digits, optional dot, any number of digits
| #... OR ...
false.* # false followed by anything
)
$ # end of line
");
I would probably use a Split(',') and validate elements of the resulting array instead of using a regex. Also you should watch out for the \, case (the comma is part of the value).

Resources