Rails 3.1: 'where' with multiple conditions and 'not nil' verification - ruby-on-rails

I want to find records with multiple conditions and this is my code:
#calhappybd = Client.where(:user_id => current_user.id, "birth IS NOT NULL")
I'm trying to do this with squeel-gem, but when I try to use multiple conditions (where{(cond1)(cond2)}), but my current_user.id defined as simple string-data.

With squeel, you should be able to do something like
#calhappybd = Client.where{(user_id == current_user.id) & (birth != nil)}
Let know if you get the same error again...
UPDATED:
Modified the conditions above. Note the single ampersand and double equals. That works for me..
My configuration:
rails 3.1.0.rc6
squeel 0.8.8

Related

Active Record: AND not working?

I have this Code in Rails 4:
#dominik += Provision.where(teilhaber: 'DW' AND weberkunde: = false).sum(:betrag)*0.9
How can I put this right so that the AND (i mean both conditions shall be true (teilhaber: 'DW' and weberkunde: false) functions correctly.
this does not work either:
#dominik += Provision.where(teilhaber: 'DW').where(weberkunde: = false).sum(:betrag)*0.9 #and weberkunde: false
As you're using a hash
.where(teilhaber: 'DW', weberkunde: false)
Rails has an excellent guide for querying active record:
http://guides.rubyonrails.org/active_record_querying.html
In your case, the syntax for your where query is just a bit off. You have a few different options with the where method.
To use hash conditions:
Provision.where(teilhaber: 'DM', weberkund: false)
Or, you can also use a a SQL-esque syntax.
Provision.where("teilhaber = ? AND weberkund = ?", 'DM', 'false')

Ruby on Rails: Update Attribute

Google is seriously failing me right now. All I need to do is update one attribute, setting a user to admin, from the Heroku rails console.
I can't find a single simple answer. What I've been trying is:
Record.update_attribute(:roles_mask, "1")
Where record is the correct record.
'undefined method 'update attribute''
I can't just type Record.roles_mask = 1?
EDIT.
I used Record, and I shouldn't have done that in the example. What I've done is exactly this:
ian = User.where(:id => '5')
ian.update_attribute(:roles_mask, '1')
Error: undefined method 'update_attributes'
The problem is that using the .where function creates a relation, rather than finding the record itself. Do this:
ian = User.find(5)
ian.update_attribute(:roles_mask, '1')
Or if you want to use .where then you could do this:
ian = User.where(:id => 5)
ian.first.update_attribute(:roles_mask, '1')
EDIT
See this answer for details about why this is happening.
To use update_attribute (or update_attributes), you need to call that from an instance and not the class.
rails c> rec = Record.find(1)
rails c> rec.update_attribute(:att, 'value')
rails c> rec.update_attributes(att: 'value', att2: 'value2')
I would think that should take care of your issue.
Where clause return a array and you are trying to make update query on array, that's why you got error.
you should try to find out first record
ian = User.where(:id => 1).first
or
ian = User.find(1)
or
ian = User.find_by_id(1)
now your update query will work.
ian.update_attribute(:roles_mask, '1')

How to show excerpts from pg-search multisearch results

I've set up pg_search in my Rails app on Heroku:
#query = 'fast'
PgSearch.multisearch(#query) #=>
[#<PgSearch::Document searchable: ferrari, :content: 'this car is really fast'>,
#<PgSearch::Document searchable: viper, :content: 'a very fast car'>]
I'd like to display these results with excerpts from content to show where the match occurs. I can call excerpt(content, #query) to get exactly what I want when #query is only one word, but excerpt() only handles exact matches, so if:
#query = 'car fast'
PgSearch.multisearch(#query) #=>
[#<PgSearch::Document searchable: ferrari, :content: 'this car is really fast'>,
#<PgSearch::Document searchable: viper, :content: 'a very fast car'>]
then excerpt(content, #query) is nil because nowhere in content does the exact phrase 'car fast' appear.
I considered excerpt(content, #query.split(' ').first) to at least show something for multi-word queries, but there are still cases such as this:
#query = 'car?'
#results = PgSearch.multisearch(#query) #=>
[#<PgSearch::Document searchable: ferrari, :content: 'this car is really fast'>,
#<PgSearch::Document searchable: viper, :content: 'a very fast car'>]
excerpt(#results.first.content, #query) #=> nil
So, how do folks show excerpts from search results when using pg_search?
I'm the author and maintainer of pg_search.
Right now there isn't a built-in way to get excerpts along-side your results in pg_search, but there easily could be if I or someone else has the time to build it in.
PostgreSQL has a function ts_headline that you can call which returns a string excerpt as a column.
It might be possible to call something like this (I haven't tested it yet):
PgSearch.multisearch(#query).select(["ts_headline(pg_search_documents.content, plainto_tsquery(?)) AS excerpt", #query])
Then each of your results should have an excerpt method that returns something like what you want.
By the way, this is something that I eventually want to make automatic in pg_search. I just haven't had the time to delve too deeply into it yet.
FWIW— Following nertzy's example above, I was able to get this to work with the following:
PgSearch.multisearch(#query).select("ts_headline(pg_search_documents.content, plainto_tsquery('english', ''' ' || unaccent('#{#query}') || ' ''' || ':*')) AS excerpt")
I was having trouble getting plainto_tsquery(?) to work, as it was throwing a syntax error. My solution above was simply the result of doing
PgSearch.multisearch(#query).select(["ts_headline(pg_search_documents.content, plainto_tsquery(?)) AS excerpt", #query]).to_sql
and then plugging in the to_tsquery arguments for the new plainto_tsquery call—something I'm sure is not entirely sound, but seems to work.
If you interpolate the string, you will be subject to sql injection attacks.
Since the .select won't accept a parameterized statement like the .where does (Users.where("id = ?", params[:id])), you will need to sanitize explicitly.
sanitized = ActionController::Base.helpers.sanitize(params[:q])
#results = PgSearch.multisearch(params[:q])
.select(["ts_headline(pg_search_documents.content, plainto_tsquery('english', ''' ' || '#{sanitized}' || ' ''' || ':*')) AS excerpt"])
There's a much easier way, if you don't feel like digging through SQL - you can make use of built in pg_search gem functionality to display excerpts in a really simple and straightforward way:
In your controller:
#articles = Article.search(params[:search]).with_pg_search_highlight
In your view:
= raw(article.pg_search_highlight)
That should do it.

RoR3+Mongoid: How to compare fields of collection/table when querying?

I have a structure that has both :id and a :group_id fields. I wish to retrieve all the data which :id equals :group_id.
I am currently working with mongoid, but I think that the operation is done the same way as it would be done when using Rails3's ActiveRecord.
Anyways. I was trying to use Message.where(:group_id => :id), which should return, for instance, this: => #<Message _id: 4e38aa132748440a7e00007d, group_id: BSON::ObjectId('4e38aa132748440a7e00007d')>. But it does not work at all (it seems as if it really should not work, but how it should, then?)
How can I query mongoid (or active record) to get only the Messages where :id equals :group_id?
EDIT:
just to show that those values are really exactly the same:
ruby-1.9.2-p180 :088 > Message.first.id
=> BSON::ObjectId('4e38aa132748440a7e00007d')
ruby-1.9.2-p180 :089 > Message.first.group_id
=> BSON::ObjectId('4e38aa132748440a7e00007d')
EDIT2:
These do not work (they have at least one message (the example above) that match)):
ruby-1.9.2-p180 :091 > Message.where("group_id = id").count
=> 0
ruby-1.9.2-p180 :092 > Message.where("group_id == id").count
=> 0
EDIT3:
Here is an example of message that should be returned: http://cl.ly/3q1r20421S3P1921101D
EDIT4:
Another piece of weirdness:
ruby-1.9.2-p180 :034 > Message.where("this._id = this.group_id").each {
|m| puts "#{m.id} = #{m.group_id}" }
4e38aa132748440a7e00007d = 4e38aa132748440a7e00007d
4e38aa132748440a7e00007e = 4e38aa132748440a7e00007d
4e38aa562748440a7e000084 = 4e38aa562748440a7e000084
4e38aa562748440a7e000085 = 4e38aa562748440a7e000084
4e38ac312748440a7e000095 = 4e38ac312748440a7e000095
4e38ac312748440a7e000096 = 4e38ac312748440a7e000095
4e38ac312748440a7e000097 = 4e38ac312748440a7e000095
Why it returns those values, even though in some cases they are not equal? Aaaarghhhhh
EDIT5: Another piece of weirdness and a small inconclusive conclusion:
ruby-1.9.2-p180 :090 > Message.where("this.read == this.sender_deleted").each {
|m| puts "#{m.read.to_s},#{m.sender_deleted.to_s}" }
true,true
false,false
false,false
false,false
false,false
My query works with boolean values! Hence, it SEEMS it is not working only with BSON::ObjectId() object comparisons (I also could not retrieve messages by doing Message.where(:id => Message.first.id [edit: I managed to do this by using :_id instead of :id, but this did not help me on the remaining of my problems]). How can I compare these damn identifiers on the same object? I really need to, and I am afraid there is no elegant alternative (storing those exact same IDs as strings would be just too weird, please do not suggest it :/ ). In the end, this seems like a specific issue to Mongoid.
obs.: I tried all combinations that came to mind, regarding id vs. _id and = vs. ==. Is there any Hash-like query for accomplishing what I need? using something like .where(:_id => :group_id) (but not that, I mean the :group_id value, not a :group_id symbol).
Try this:
Message.where("this.group_id == this.id")
Mongoid usees MongoDB in the end, so anything which is not possible in mongodb can not be done using mongoid. The particular use case you are talking about, is not supported by mongodb as of now.
You cannot query a field against a field, you have to provide literal values to query against. I saw an issue on Mongodb Issue Tracker for supporting this, but couldn't locate it now.
The boolean value query you are mentioning, might just be a coincidence. That should also not work as expected.
Update
One can compare fields in mongodb using $where clause.
You have been missing the '$where' in Mongoid's where method
This worked for me:
Message.where('$where' => 'this.group_id == this.id')
Message.where("group_id = id")

Rails - how to search based on a boolean field? (MySQL error)

I'm running the following query
#projects = #company.projects.where("active = ?", true).order("created_at ASC")
and I'm getting the error:
`ActiveRecord::StatementInvalid: Mysql::ParseError: You have an error in your SQL...`
the error points to the = '1'.
I've tried many variations on my query but I cannot figure out the problem. How can I solve this?
Try:
#projects = #company.projects.where(:active => true)
(it also works with strings 'active').
You can also look at
http://guides.rubyonrails.org/active_record_querying.html#hash-conditions
for more details.
There is also a nice railscast about this which explains why you might have problems (I'm not allowed to post 2 links so you should search for it :) )
You don't need to use parameterized queries with literals, just do this:
#projects = #company.projects.where("active = 1").order("created_at ASC")

Resources