Understanding query method where in ActiveRecord - ruby-on-rails

I want to return the count of users that that have a boolean value, show, not set to true. show is a boolean but is initialized to nil.
Because of this I'm getting some results that I did not expected. For example,
[{show: nil}].where.not(show: true).count -> 0
[{show: nil}].where(show: [nil, false]).count -> 1
Shouldn't this query's return the same thing?

This is a general misunderstanding of NULL (which is not uncommon by the way).
NULL is not comparable, it is neither true or false, nor equal or not equal, nor less than or greater than, etc., NULL cannot even be compared to NULL. e.g. NULL = NULL is false but NULL != NULL is also false.
Your First case (.where.not(show: true)) is show != true (or NOT(show =true)) which is the equivalent of show = false.
Your second example (.where(show: [nil, false])) is show IS NULL OR show = false. While this syntax show: [x,y] usually results in an IN() clause Arel is smart enough to realize that one of these values is nil and converts the SQL generation accordingly because show IN (NULL,false) would be equivalent to show = NULL OR show = false (this is how IN() works) but as mentioned NULL = NULL is false thus why IS NULL and IS NOT NULL exist.
The result of your query is because there are no rows where show = false but there is one row where show IS NULL.

Related

Back4app, filter query based on null value or undefined value

In database seems we have two types of non existing values:
(undefined) and (null)
If I do query
if paidDateDoesNotExist == true {
query.whereKeyDoesNotExist("paidDate")
}
looks like it returns only undefined but no null records which is seems correct.
If I do query
if paidDateDoesNotExist == true {
query.whereKey("paidDate", equalTo: NSNull())
}
it returns the all undefined and null records.
So for some cases I need to clear value from client code. Let's say I have paidDate column and I want to clear paidDate which was set to some Date already.
in my client code I just simple assign NSNull() to PFObject
like pfObject["paidDate"] = NSNull()
in this cases query query.whereKeyDoesNotExist("paidDate") will not work.
So the thing I would like to understand - do I need to assign pfObject["paidDate"] = (undefined) value somehow or I just need to use another query which is uses NSNull() as filter.
Which is more fun when I use similar query form the admin panel, admin panel returns records which are equal to null only ignoring undefined records. But for client code query:
if paidDateDoesNotExist == true {
query.whereKey("paidDate", equalTo: NSNull())
}
returns undefined records as well as null records.

How to make where condition include nil value

I find ActiveRecord, funnel value is not "input" value
and I make where condition
here is my code
#calls = Call.searchable.where.not(funnel: "input")
these command work good, but result is also except nil value
I wanna only funnel is not 'input'
how to add OR condition in where statement
SQL Statement is
select * from call where is_visible = 1 and (funnel != 'input or funnel is null)
The blow code should help you.
#calls = Call.searchable.where("funnel != 'input' or funnel is null")
This will also work if values are dynamic
Call.searchable.where("funnel != ? OR funnel is ?”,#value1, nil)

Grails: Comparing two unsaved domain class objects always returns false

I need to compare several domain class objects while they are still unsaved, however, I always keep getting a false result from the comparison. Turns out even the following comparison will return false:
new DomainClass().equals(new DomainClass())
Since both are brand new objects they should both have identical data and should be equal to each other. Unfortunately the equals method (or the == operator) returns false. Is there another correct way of performing this comparison?
Your code same with this:
a = new DomainClass();
b = new DomainClass();
a.equals(b)
So clearly the test must return false as far as a and b are not referencing same object.
If you want value based comparing:
Iterate over the fields and compare them one by one
Or check here for a more formal way of doing it.
you can use 'spaceship operator' (<=>) which work like compareTo()
or you can override equals() method in your DomainClass that make able to use this code
new DomainClass().equals(new DomainClass())
to override equals() you can use #EqualsAndHashCode annotation
this annotation automatically generate equals() and hashcode() methods
So, you class will look like this:
#EqualsAndHashCode
class DomainClass(){
String field1
String filed2
etc
}
and your generated equals method will look like this:
public boolean equals(java.lang.Object other)
if (other == null) return false
if (this.is(other)) return true
if (!(other instanceof DomainClass)) return false
if (!other.canEqual(this)) return false
if (field1 != other.field1) return false
if (field2 != other.field2) return false
// etc
return true
}
For more details look at this http://groovy.codehaus.org/api/groovy/transform/EqualsAndHashCode.html

Validation test evaluates BigDecimal 0.0 to null

I am using Grails 2.4.3
I have a property named value of type BigDecimal which is defined like this:
#BindUsing({ obj, source ->
if (source['value']) {
source['value']?.toBigDecimal()
} else {
null
}
})
BigDecimal value
Now if I use this value in a constraint, I get the following strange behaviour:
if (obj.value)
evaluates to false if value is set to 0.0
It evaluates to true for any other value (e.g. 0.1)
0.0 is actually stored as 0.0 in the database table, but the validator obviously thinks it is null.
Or is there maybe a problem using "value" as the name for a property?
Actually the issue is how Groovy evaluates truth. The documentation has the following example:
assert !0 //yeah, 0s are false, like in Perl
assert 1 //this is also true for all other number types
Numbers, 0.0 in your case, evaluate to false when they are zero. If you are trying to check for null values, then you should be checking for null values in this case.
if (obj.value == null)

LINQ query with omitted user input

so I have a form with several fields which are criteria for searching in a database.
I want to formulate a query using LINQ like so:
var Coll = (from obj in table where value1 = criteria1 && value2 = criteria2...)
and so on.
My problem is, I don't want to write it using If statements to check if every field has been filled in, nor do I want to make separate methods for the various search cases (criteria 1 and criteria 5 input; criteria 2 and criteria 3 input ... etc.)
So my question is: How can I achieve this without writing an excessive amount of code? If I just write in the query with comparison, will it screw up the return values if the user inputs only SOME values?
Thanks for your help.
Yes, it will screw up.
I would go with the ifs, I don't see what's wrong with them:
var query = table;
if(criteria1 != null)
query = query.Where(x => x.Value1 == criteria1);
if(criteria2 != null)
query = query.Where(x => x.Value2 == criteria2);
If you have a lot of criteria you could use expressions, a dictionary and a loop to cut down on the repetitive code.
In an ASP.NET MVC app, chances are your user input is coming from a form which is being POSTed to your server. In that case, you can make use of strongly-typed views, using a viewmodel with [Required] on the criteria that MUST be provided. Then you wrap your method in if (ModelState.IsValid) { ... } and you've excluded all the cases where the user hasn't given you something they need.
Beyond that, if you can collect your criteria into a list, you can filter it. So, you could do something like this:
filterBy = userValues.Where(v => v != null);
var Coll = (from obj in table where filterBy.Contains(value1) select obj);
You can make this more complex by having a Dictionary (or Lookup for non-unique keys) that contains a user-entered value along with some label (an enum, perhaps) that tells you which field they're filtering by, and then you can group them by that label to separate out the filters for each field, and then filter as above. You could even have a custom SearchFilter object that contains other info, so you can have filters with AND, NOT and OR conditions...
Failing that, you can remember that until you trigger evaluation of an IQueryable, it doesn't hit the database, so you can just do this:
var Coll = (from obj in table where value1 == requiredCriteria select obj);
if(criteria1 != null)
{
query = query.Where(x => x.Value1 == criteria1);
}
//etc...
if(criteria5 != null)
{
query = query.Where(x => x.Value5 == criteria5);
}
return query.ToList();
That first line applies any criteria that MUST be there; if there aren't any mandatory ones then it could just be var Coll = table;.
That will add any criteria that are provided will be applied, any that aren't will be ignored, you catch all the possible combinations, and only one query is made at the end when you .ToList() it.
As I understand of your question you want to centralize multiple if for the sake of readability; if I were right the following would be one of some possible solutions
Func<object, object, bool> CheckValueWithAnd = (x, y) => x == null ? true : x==y;
var query = from obj in table
where CheckValue(obj.value1, criteria1) &&
CheckValue(obj.value2, criteria2) &&
...
select obj;
It ls flexible because in different situations or scenarios you can change the function in the way that fulfill your expectation and you do not need to have multiple if.
If you want to use OR operand in your expression you need to have second function
Func<object, object, bool> CheckValueWithOr = (x, y) => x == null ? false : x==y;

Resources