Converting having
Closed this issue · 11 comments
Not sure how to convert this clause from squeel:
having{`completion`.op(compl_string == 'complete' ? '=' : '<', 1.0)}
where 'compl_string is a local variable. Just replacing having with when_having and ticks with quotes doesn't work. Thanks.
Yeah, backticks don't work like that in baby squeel. Is that not a column? Ideally, you should avoid using a sql literal, but, if you absolutely must, I think you're looking for:
sql('completed')
No it's not a column, it's generated by an "...as('completed')" clause, is there anything better I can use? Anyway that seems to take care of the 'completed', but now I'm getting:
ActionView::Template::Error (Unsupported argument type: Float. Construct an Arel node instead.):
[" 1: = render @assignments", " 2: = render_now if controller.request.format.js?"] /usr/local/rvm/gems/ruby-2.4.1@global/gems/arel-7.1.4/lib/arel/visitors/to_sql.rb:756:in `unsupported'
/usr/local/rvm/gems/ruby-2.4.1@global/gems/arel-7.1.4/lib/arel/visitors/reduce.rb:13:in `visit'
/usr/local/rvm/gems/ruby-2.4.1@global/gems/arel-7.1.4/lib/arel/visitors/to_sql.rb:777:in `visit_Arel_Nodes_InfixOperation'
/usr/local/rvm/gems/ruby-2.4.1@global/gems/arel-7.1.4/lib/arel/visitors/reduce.rb:13:in `visit'
...
Looks like the float 1.0 doesn't work as is? Thanks.
Ok that works thanks. But I found it also works with an integer instead of the float (but I need a float since 'completion' is float). Why would it work with one and not with the other? Also when should I use 'sql' and when 'quoted'? I also found that quoted('completed') works too. Thanks.
I think Arel just doesn't know how to handle floats, and I think baby squeel would have to do some nasty stuff to get that to work without using quoted
.
The difference between quoted
and sql
can be seen here:
baby_squeel/lib/baby_squeel/dsl.rb
Lines 79 to 86 in c399008
The difference is that sql
just gives you literal sql and marks it as "safe" for the database.
[3] pry(main)> Arel.sql 'something'
=> "something"
ActiveRecord internally "quotes" values before they hit the database. Using baby_squeel's quoted
method basically does this:
[4] pry(main)> Arel.sql Post.connection.quote('something')
=> "'something'"
I wouldn't use quoted
to reference a column (or an alias). It's really only for values.
Ok it makes sense, thanks. I see that quoted
knows not to generate actual quote signs around floats. Although for identifiers it would be nice if there were a way to generate backticks. Is there any? Not that I really need it.
Here's another issue with converting a having
condition from squeel. In squeel I have something like:
Student.having{`team_role` < `team_size` - 1}
where team_role
and team_size
are aliases from a preceding select
. I tried to convert it to:
Student.when_having{sql('team_role') < sql('team_size') - 1}
but I'm getting an error:
NoMethodError: undefined method `-' for BabySqueel{"team_size"}:BabySqueel::Nodes::Node
Did you mean? -@
What's wrong? Thanks.
If you're just using a SQL literal anyway, there is absolutely no reason to use Baby Squeel. You're just making the query more complicated.
Just do this: having('team_role < team_size - 1')
Well, I use sql literals only because aliases don't work otherwise. I'd be glad to write them directly as:
Student.when_having{team_role < team_size - 1}
In squeel backticks were at least getting close.
Yes that works, thanks. Btw is there a similar solution for the issue with the 1.0
above? I have it in a few places, that's also something that works fine with squeel. I also have nil
in function calls in a number of places, that doesn't work either, although it was working fine with squeel, I guessing it's the same issue. Thanks.