Does not equal conditional - ruby-on-rails

I want to have a where clause with an equal and does not equal condition:
#user = User.where(:user_id => current_user.id, :author_id != current_user.id).nil? ? (render :something) : (render :somethingelse)
The above does not work:
syntax error, unexpected ')',
expecting tASSOC ...d, :user_id !=
current_user.id).nil? ? (render
:index) : (re...
If I change the second condition from != to => it will work, however.
How do I have both conditions in one where clase? Thank you

Here's how you would use Arel to generate the query "select * from users where user_id = ? and author_id != ?":
users = User.arel_table
User.where(users[:user_id]. eq(current_user.id).and(
users[:author_id].not_eq(current_user.id)))
Using Arel isn't as concise as using Hash conditions for simple conditions, but it's a lot more powerful!
Here's a link to the full list of predications (eq, not_eq, gt, lt, etc.) available with Arel.

I believe, it should be:
#user = User.where(['user_id = ? AND author_id <> ?', current_user.id, current_user.id])
render(#user ? :something : :somethingelse)

Rails 4 has this all figured out
Model.where.not(:colname => nil)
#=> returns all records whose :colname values are not nil

The syntax error is due to you attempting to use != instead of =>. The where method does not support inequality with hashed arguments, so your not equal will need to be written using array arguments.
User.where(:user_id => current_user.id).where(['users.author_id <> ?', current_user.id])

http://guides.rubyonrails.org/active_record_querying.html#hash-conditions
Only equality, range and subset checking are possible with Hash conditions.
You'll need to either drop down to straight SQL or invert and arel query, see Is there a way to invert an ActiveRecord::Relation query?

Not sure if you're aware, the not equal condition typically does not match (author_id) NULL values. You'll have to do an OR author_id IS NULL if you want that.
#users = User.where("user_id = ? AND (author_id != ? OR author_id IS NULL)",
current_user.id, current_user.id)
render(#users.present? ? :something : :somethingelse)
Also note that I'm using #users.present? because where finder returns an ActiveRecord::Relation array.

Related

simple Or statement

I am trying to do a simple or statement in a controller
This generates one set of trips that I am interested in displaying and is working fine.
#trips = Trip.where(:userid => #friends)
However, i would like to add another set of trips; trips whose userid == current_user.id
#trips = Trip.where(:userid => current_user.id)
Trying to combine these two i tried...
#trips = Trip.where(:conditions => ['userid= ? OR userid=?', #friends, current_user.id])
Any idea where the bust is? Thanks in advance.
Simply pass an array to get the equivalent of the SQL WHERE ... IN clause.
Trip.where(userid: [#friends, current_user.id])
See the ActiveRecord Rails Guide, 2.3.3 Subset Conditions
Is #friends an array? ActiveRecord will convert your where statement into a SQL IN clause when you generate it with the hash syntax. When you build your OR statement in raw SQL, you need to do the IN manually.
#trips = Trip.where('userid IN ? OR userid = ?', #friends, current_user.id)
Also, your column is called userid ? Typicaly it would be called user_id - is this a typo or do you just have an abnormal database?

Find records where an attribute is present

I have a User model with the attributes username, email and name.
username and email are required upon signup, but not name.
What would be the query to find all users that have filled out name (i.e. it is no nil)?
The query should be at least Rails 3.2 and 4.0 compatible.
I'm thinking something in the lines of:
User.where(name: present?)
[UPDATED 13/5/2022]
To get all records where an attribute is not present in SQL, we would write
WHERE attr IS NULL or attr = ''
an easy mistake to make is then to negate this and write
WHERE attr is not null and attr != ''
However in SQL this equates to writing
WHERE attr != ''
since the NULL value is always ignored when using the equality operator.
So this translates to rails as follows:
User.where.not(name: '')
[MY OLD ANSWER]
An empty value in a database gets a special value NULL. Testing whether is set uses the special comparator IS NULL or IS NOT NULL.
Then there still remains the possibility that an empty string was filled in, so a complete test would be
#users = User.where("name is NOT NULL and name != ''")
[UPDATED for rails 4+]
Since rails 4 we can write:
User.where.not(name: [nil, ""])
which will generate the same query. Awesome :)
present?
present? is essentially not nil and not empty?:
class Object
def present?
!blank?
end
def blank?
respond_to?(:empty?) ? !!empty? : !self
end
end
ActiveRecord condition
In Rails 4, not conditions can be done without raw sql code.
# Both lines lead to the same result:
User.where.not(name: [nil, ""])
User.where.not(name: nil).where.not(name: "")
Since there is no raw sql code, you don't have to worry about if they work with every database adapter. In fact, this works fine for both, mysql and postgres.
to_sql
You can see how they translate to sql queries if you append .to_sql, for example in the rails console.
# rails console
User.where.not(name: [nil, ""]).to_sql
# => "SELECT \"users\".* FROM \"users\" WHERE (NOT ((\"users\".\"name\" = '' OR \"users\".\"name\" IS NULL)))"
User.where.not(name: nil).where.not(name: "").to_sql
# => "SELECT \"users\".* FROM \"users\" WHERE (\"users\".\"name\" IS NOT NULL) AND (\"users\".\"name\" != '')"
Further Reading
[1] Rails 4 guide "ActiveRecord Query Interface"
[2] Definition of present? on github
NOT SQL queries can be built by where.not
#users = User.where.not(name: nil)
Try this:
User.where("name IS NOT NULL AND name != ?", "")
I edited my answer as per #nathavanda comments, which his answer in my opinion should be the accepted one.
You can simply do this:
User.where.not(name: '')
Because of the nature of not, it won't include records where name is nil nor empty string. See this article for more details about not and nil

Rails: rewrite a find_all_by() with a .where method

I'm using a gem that doesnt work on the arrays from the find_all_by() method, but does with the .where(); however, I don't know how to write it in a way that produces the same result.
For instance, how could I rewrite:
Post.find_all_by_poster(#user.id , :conditions => ['title IS NOT NULL OR name !=?', 'Bob' ])
My attempt:
Post.where("poster = ? AND title !=? OR name !=?", #user.id, 'NULL', 'Bob')
Any ideas? I'm having trouble satisfying the same conditions. Thanks for your help!
You still need to use IS NOT NULL instead of passing in NULL as a separate parameter:
Post.where("poster = ? and (title is not null or name != ?)", #user.id, 'Bob')

What is the proper syntax for `!current_user`

I am writing this statement here :
where :commentable_id => comments.map(&:id), :user_id => !current_user
The problem is it's returning only a user with the id of 0. Assuming this is a non-user, or more specifically a !user.
In this case, I am just trying to say anybody but the current user.
How would you write that?
Using "not #{current_user.id} returns :
SELECT "comments".* FROM "comments" WHERE ("comments"."user_id" = 0)
Right, I've written this in the other answer I gave.
The problem is that hashes in conditions are only good for making == or IN comparisons in SQL. You cannot do bigger or smaller comparisons or not-equals. You have to write a snippet of SQL yourself.
where(:commentable_id => comments.map(&:id)).where("user_id != ?", current_user.id)
You approach doesn't work, because it will send the results of !current_user to the SQL generator (which is the ARel gem). According to Ruby logic, any object that isn't nil or false is considered to be true. When you place a "bang" (exclamation mark) before it, it will make if false. And ARel will try to convert false in to whatever database understands as false. Most databases don't understand booleans and they use different other methods for that. SQLite uses 't' and 'f', and MySQL uses 1 and 0 (I believe).
where :commentable_id => comments.map(&:id), :user_id => "<> #{current_user.id}"
This will do it.

Not Null in "count" or "find" function in rails

I'm trying to find the not null elements in a database
#genus_counts = Table.count(:all, :conditions=> {:col1 => params[:gm], :col2 => nil}, :without => {:col3 => nil})
It's not recognising "without" function. I am in doubt to apply it as array value.
#genus_counts = Table.count(:all, :conditions=> {:col1 => params[:gm], :col3 != nil :col2 => nil})
It's not recognising "!=" operator.... Kindly suggest me and correct above statement. I am in doubt to apply it as array value.
#genus_counts is a local variable, I can't apply it as array. Kindly tell me the suggestion to bring this output to view.erb.html
--
With Regards
Palani Kannan. K
You should do something like (as answered before)(inside your controller) :
#genus_count = Table.count(:all, :conditions => ['col3 is not null and col2 is null and col1 = ?', params[:gm])
then #genus_count will contain the count you want. Since #genus_count is an instance variable of your controller, you can just refer to it inside your view like this:
The wanted count = <%= #genus_count %>
Hope this helps!
as in
http://guides.rubyonrails.org/active_record_querying.html#conditions
you can use something similar to this form instead:
"orders_count = ? AND locked = ?", params[:orders], false
so you can use
" ... col3 IS NOT null ... "
The hash format of specifying conditions such as :conditions=> {:col1 => params[:gm], :col2 => nil} can only be used to specify conditions that are all = joined with AND.
It's nice to read so use that format when applicable, but when you need an OR, or a comparator other than =, you'll need to use a slightly different format:
:conditions => ["col1 = ? AND col3 != ? AND col2 = ?", params[:gm], nil, nil]
This format takes an array, the first element of which is an sql fragment, and the remaining parameters are sql sanitized (preventing sql injection attack, and converting nil to 'NULL' etc) and inserted into the sql fragment replacing the ? (in order of appearance).

Resources