squeel
squeel copied to clipboard
#where returns WhereChain when block returns an association's sifter (Rails 4)
Example to reproduce:
class User < ActiveRecord::Base
sifter(:anonymous) { email == nil }
end
class Post < ActiveRecord::Base
belongs_to :user
end
This code will fail:
> Post.joins(:user).where{user.sifter(:anonymous)}.to_sql
undefined method `to_sql' for #<ActiveRecord::QueryMethods::WhereChain:0x00000005996c18>
But this code won't:
> Post.joins(:user).where{user.sifter(:anonymous) & `1 = 1`}.to_sql
=> "SELECT `posts`.* FROM `posts` INNER JOIN `posts`.`user_id` = `users`.`id` WHERE ((`users`.`email` IS NULL AND 1 = 1))"
This won't either:
> User.where{sifter(:anonymous)}.to_sql
=> "SELECT `users`.* FROM `users` WHERE (`users`.`email` IS NULL)"
All these pieces of code used to work on Rails 3.2. Haven't debugged it, if you need more information please let me know.
+1
Running into the same issue with Rails 4.
@section = current_business.sections.find(params[:section_id])
@products = @section.products.where{ kind.eq(my{ params[:kind] }) }
In jbuilder.
json.array! @products do |product|
json.partial!('product', product: product)
end
Error:
undefined method `map' for #<ActiveRecord::QueryMethods::WhereChain:0x007fcd09b54c70>
Never saw this in Rail 3.2
+1
Same for me with the following request:
User.where(id > 10).update_all(updated_at: Date.current)
Error:
NoMethodError - undefined method `update_all' for #<ActiveRecord::QueryMethods::WhereChain:0x0000010a9656a8>:
@benebrice Could you try:
User.where{ id > 10 }.update_all(updated_at: Date.current)
Notice that where is using a block.
@anthonator I tried that too. Same error. Thank you for trying.
This is weird, though not the same bug I reported...
@benebrice Are you using AR 4.1? I think that's the error I saw before I started making changes.
@chewi I'm using Rails 4.0.2. Maybe that's the problem.
@benebrice Nah, that version should work fine. It's 4.1 that's broken.
@chewi It seems that a lot of methods cannot work with results coming from a "where" request. I have just tried an "includes" :
NoMethodError - undefined method `includes' for #<ActiveRecord::QueryMethods::WhereChain:0x00000111028ef8>:
And a "collect" :
NoMethodError - undefined method `collect' for #<ActiveRecord::QueryMethods::WhereChain:0x00000103f6c788>:
Obviously, these methods are not used on empty results.
Edit : doc of WhereChain.Does it means that no more methods can be applied of where results ?!
Edit 2 : "includes" method seems work if you do it like : Model.includes(...).where(...) and not Model.where(...).includes(...)
It was completely my mistake. The gem squeel was missing... Just add it. Bundle install. And everything was ok. I hope this huge mistake will help someone else.
Regards.
Clarification for followups: the above comments are not related with the actual issue posted and therefore this issue should not be closed yet.
Thanks
Just ran into the original issue reported here myself. It's hard to see what's going on because there's a lot of voodoo in Squeel but it's definitely not calling visit_Squeel_Nodes_Sifter when it should. This may be a symptom rather than a cause though.
I don't know if this problem exists right now because I tested #315 and found it fixed. Could you please try the latest master branch? Thank you very much.
Maybe It could be closed, if anyone reports this again, I will reopen, thank you every one :)
@bigxiang sorry for the delay, but I tested it and it still fails with the latest 1.2.1 and master.
Please note that most of the comments here, including #315 are not the bug I'm experiencing.
My bug report is very specific: using an association's sifter in a where block, without any other condition (such as adding & 1 = 1``) causes the #where to return a ActiveRecord::QueryMethods::WhereChain.
Thanks for your support
@fahad86, that's not a valid SQL. Whatever goes inside squeel must be a valid SQL with a squeel format. Your example: where{exists(Building.new_buildings.where{city_id == cities.I'd})}
@bigxiang can this issue be reopened?
@odedniv Thanks for replying, I will reopen it, sorry to delay the response. I am too busy recently :)
I have the same problem with Rails 4.1.6 - exactly as @odedniv described it. (tested agaist latest master as well as latest stable)
Yep, this is actually happens also on 4.2. @marcusg my usual fix is to add & 1=1`` in the end =/
@odedniv Yes, I'll use this workaround, thanks!
I'm having the same error on Rails 4.2.
This code:
query.where do
client.sift(:has_phone_number)
end
Throws:
NoMethodError: private method `load' called for #<ActiveRecord::QueryMethods::WhereChain:0x000001111f1c58>`
Changing it to:
query.where do
client.sift(:has_phone_number) & `1=1`
end
Fixes the problem.
Horrible hack, but it does work for now.
I met same problem with Rails 4.2.3. This problem is fixed after upgrading to master (and arel are also upgraded to 6.0.3 from 6.0.0)
@ernie why don't you release latest master?
I don't know if this is relevant or not but the problem is due to this function here:
https://github.com/rails/rails/pull/21504
Hey, so that PR was merged which should fix this bug.. For anyone who can't update.. here is a monkey patch:
module ActiveRecord::QueryMethods
def where(opts = :chain, *rest)
if :chain == opts
WhereChain.new(spawn)
elsif opts.blank?
self
else
spawn.where!(opts, *rest)
end
end
end
I didn't find that the ActiveRecord::QueryMethods#where monkey patch fixed this bug in our use case, but 1=1 did.