Postgresql WHERE clause adds '' around? - ruby-on-rails

This morning I switched to postgresql and now my where selects dont work anymore.
What I am trying to do is super simple:
shirt_ids = "1,5,6" # String generated by javascript
Shirt.where("id in (?)", shirt_ids)
This gives me :
PG::Error: ERROR: invalid input syntax for integer: "1,5,6"
LINE 1: SELECT "shirts".* FROM "shirts" WHERE (id in ('1,5,6'))
This works though:
Shirt.where("id in (#{shirt_ids})")
But as everybody knows is unsafe.
Im using:
pg (0.13.2 x86-mingw32)
rails (3.2.2)
Postgresql database is the newest version, I installed it this morning.
Thank you for your help.
^

I believe Postgres is expecting an array, rather than a string for the IN function. If you convert your string to an array, it should work:
shirt_ids = "1,5,6"
Shirt.where('id in (?)', shirt_ids.split(','))
Also, you can do this, which looks a bit cleaner:
Shirt.where(:id => shirt_ids.split(','))

Related

postgres - operator does not exist: double precision ~~ unknown

ActionView::Template::Error (PG::UndefinedFunction: ERROR: operator
does not exist: double precision ~~ unknown
2016-04-10T23:45:59.506005+00:00 app[web.1]: LINE 1: ... =
"trackers"."category_id" WHERE (categories.tag LIKE '1.%'...
this is the error i get when i try to run this line of code here
Tracker.group(:category_id).joins(:category).where('categories.tag LIKE ? AND user_id = ?', "#{tag.to_i}.%", current_user.id)
tag is of type float, and i typecast it to an integer in order to check for tags 1.1, 1.2, 1.3 etc
so in the example above I type cast tag with value 1.0 to be 1, so i can search for tags that are like 1.1, 1.2 etc
I am using postgres on heroku that gives this error. locally i use sqlite3 and it works just fine.
how can i overcome this?
Since you're in rails, sort out the dynamic-ness in rails first then send that to the ORM. The syntax you provided already accepts any parameters (eg: WHERE tag between ? and ?), so before you request the data from the ORM, sort out in rails the high and lows. The query is already setup for something to be dynamic.

Postgres throws error when running import from activerecord-import gem

I switched to Postgres in development and now following error breaks a test case:
PG::Error: ERROR: column "id" of relation "assets_content_nodes" does not exist
: SELECT pg_get_serial_sequence($1, $2)
Same error happens in development and production environments but it is not a show stopper and does not affect the import.
assets_content_nodes is a join table and I'd rather not add the 'id' column.
Any ideas why this may be happening?
This is fixed in activerecord-import -v0.3.1 (or possibly an earlier version, but it was broken in 0.2.11 and earlier). You no longer need an id column on a table to do an import.
You might also try Upsert.
If you're importing pets:
require 'csv'
require 'upsert'
u = Upsert.new Pet.connection, Pet.table_name
CSV.foreach('pets.csv', headers: :first_row) do |row|
selector = { name: row['name'] }
setter = row
u.row selector, setter
end
My tests show it's 20–30% faster than activerecord-import. Since it's "upserting," it's generally OK if the process gets interrupted and you just start over from the beginning.

JSON encoding/decoding with unicode in rails

I upgraded downgraded to rails 2.3.17 due to the security bugs, but now I can't decode json strings that I have saved down to a DB if they have unicode in them :(. Is there a way to process the string such that it decodes properly?
e = ActiveSupport::JSON.encode({'a' => "Hello Unicode \u2019"})
ActiveSupport::JSON.decode(e)
gives me
RangeError: 8217 out of char range
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:314:in `unquote'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:251:in `strtok'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:215:in `tok'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:178:in `lex'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:46:in `decode'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/backends/okjson.rb:612:in `decode'
from /app/vendor/bundle/ruby/1.9.1/gems/activesupport-2.3.17/lib/active_support/json/decoding.rb:14:in `decode'
from (irb):30
from /usr/local/bin/irb:12:in `<main>'
I can't change the first line since it's coming from the DB like that.
This used to work.
You can change the backend JSON provider in ActiveSupport.
Add ActiveSupport::JSON.backend = "JSONGem" into an application initialiser (I added it to application.rb). This fixed the unicode parsing issues I had after I upgraded activesupport to 3.0.20.
See the vulnerability notice which caused this update - It mentions that this workaround should apply to 2.3.16 as well.
From rails console:
> ActiveSupport::VERSION::STRING
=> "3.0.20"
> ActiveSupport::JSON.decode('{"test":"string\u2019"}')
RangeError: 8217 out of char range
> ActiveSupport::JSON.backend = "JSONGem"
> ActiveSupport::JSON.decode('{"test":"string\u2019"}')
 => {"test"=>"string’"}
The JSON gem will handle this correctly.
As a note, the gem is much more strict than the other JSON parsers out there. For example:
{ 'test' : 'value' }
This is not valid JSON even though it looks okay.
For whatever reason the non-UTF-8 savvy JSON parser shipped as part of the 2.3.16 patch which is really sloppy on the part of the maintainer.
Switch to 2.3.15 which should be fine because that's when the fixes landed.
Curse the developer who started this project in rails
Begin work on porting to python post haste

Rails - PostGIS + postgis_adapter Geometry Problem

I use postgis_adapter alongside with PostgreSQL 9.0.4, PostGIS 1.5.2 and Rails 3.1.0 on Ruby 1.9.2.
As described in the the postgis_adapter README, I tried to perform
Model.create(:geom => Point.from_x_y(10,20))
Postgres responds with
ERROR: parse error - invalid geometry
HINT: You must specify a valid OGC WKT geometry type such as POINT, LINESTRING or POLYGON
The created GeoRuby Object looks like this:
#<GeoRuby::SimpleFeatures::Point:0x0000010420a620 #srid=4326, #with_z=false, #with_m=false, #y=20, #x=10, #z=0.0, #m=0.0>
Hopefully someone got an idea.
Executive summary: it may work if you change it to:
Model.create(:the_name_of_your_geo_column => Point.from_x_y(10,20))
Longer version, with a high probability of Ruby howlers: I've barely written a word of rb but saw one too many great projects this week to continue in a state of ignorance. Working through the error messages in irb (starting from 0 in the language but very familiar with PostGIS):
ActiveRecord::Base.establish_connection(:adapter=>'postgresql',:database=>'moveable')
pt = TablePoint.new(:data => "Hello!",:geom => Point.from_x_y(1,2))
NameError: uninitialized constant Point
So, require 'postgis_adapter', but then:
PGError: ERROR: relation "table_points" does not exist
This must be that awesome naming convention in ActiveRecord that I've heard about. So create a table called table_points because I don't know what the database model/sync methods are.
moveable=> create table table_points(data text, geo_something geometry);
Notice here I used geometry rather than geography because my first instinct as to your problem was that the modeling methods in the database adapter layer created point types. Not at all, actually. Then again in irb,
pt = TablePoint.new(:geom => Point.from_x_y(1,2))
ActiveRecord::UnknownAttributeError: unknown attribute: geom
No attribute named geom? Just to see what would happen, again in psql:
moveable=> alter table table_points add column geom geometry;
ALTER TABLE
Then:
irb(main):014:0> pt = TablePoint.new(:geom => Point.from_x_y(10,20))
=> #<TablePoint data: nil, geo_something: nil, geom: #<GeoRuby::SimpleFeatures::Point:0x1022555f0 #y=20, #with_m=false, #x=10, #m=0.0, #with_z=false, #z=0.0, #srid=-1>>
irb(main):015:0> pt.save
=> true
Unbelievable! What if I did:
pt = TablePoint.new(:data => 'is this even possible?', :geom => Point.from_x_y(38,121), :geo_something => Point.from_x_y(37,120))
=> #<TablePoint data: "is this even possible?", geo_something: #<GeoRuby::SimpleFeatures::Point:0x102041098 #y=120, #with_m=false, #x=37, #m=0.0, #with_z=false, #z=0.0, #srid=-1>, geom: #<GeoRuby::SimpleFeatures::Point:0x1020410c0 #y=121, #with_m=false, #x=38, #m=0.0, #with_z=false, #z=0.0, #srid=-1>>
irb(main):023:0> pt.save
=> true
Even more unbelievable!
moveable=> select * from table_points;
data | geo_something | geom
--------+-----------------+--------
| | 0101000000000
| 010100000000000 |
| 010100000000000 |
...ble? | 00005E400000000 | 010000405E40
(4 rows)
I hesitate to post this as an answer because of fundamental lack of familiarity with Ruby but the above works (mindbendingly, to me), and you may be able to adapt it to your case.
My knowledge of Rails and Ruby is very limited, but try instead:
class Model < ActiveRecord::Base
end
pt = Model.new(:geom => Point.from_x_y(10,20))
pt.save
Adding a Spatial Reference System Identifier (SRID) fixed this problem for me:
Model.create(:geom => Point.from_x_y(10,20, 4326))
If you're using Google Maps, 4326 is the right SRID. Other maps and vendors might use something else.
I ran into a similar problem using spatial_adapter when upgrading a working app from Rails-3.0 to 3.1. It seems newer versions of ActiveRecord type cast your record to a GeoRuby object during insert. The activerecord-postgis-adapter correctly handles the type cast of your geometry column (presumably to EWKT). I spent a lot of time chasing this today and Aaron Patterson's response in this post was very helpful.
To fix your problem, upgrade your Gemfile and database.yml to use activerecord-postgis-adapter.

Ruby 1.9.x undefined method ^ for string

i found a ruby encryption library which is using this function.
def process(text)
0.upto(text.length-1) {|i| text[i] = text[i] ^ round}
text
end
in ruby 1.9.x it throws an error - undefined method ^' for "\x1A":String__
is there any work around in ruby 1.9.x?
after googling i came to know that "In Ruby 1.9 string[index] returns character not code of the character (like it was in 1.8)." (https://rails.lighthouseapp.com/projects/8994/tickets/3144-undefined-method-for-string-ror-234)
Thanks in advance
Try text[i].ord ^ round. See Getting an ASCII character code in Ruby using `?` (question mark) fails for more info.

Resources