From 349ef51dd73bd878693358b20ba71f26f6c0e195 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sat, 11 Mar 2017 23:59:47 +0800 Subject: [PATCH 01/18] setup postgresql for travis --- .travis.yml | 5 ++++- test/test_helper.rb | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/.travis.yml b/.travis.yml index 599af63..b1d5e03 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,12 +4,15 @@ rvm: - 2.3 sudo: required dist: trusty +services: + - postgresql before_install: - gem install bundler - gem update --system - gem --version before_script: - - mysql -u root -e 'CREATE DATABASE test;' + - mysql -u root -e 'CREATE DATABASE travis_ci_test;' + - psql -c 'create database travis_ci_test;' -U postgres gemfile: - gemfiles/3.2.gemfile - gemfiles/4.2.gemfile diff --git a/test/test_helper.rb b/test/test_helper.rb index 5b5ba53..a9aa35c 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -8,6 +8,6 @@ ActiveRecord::Base.establish_connection( "adapter" => "mysql2", - "database" => "test" + "database" => "travis_ci_test", ) require 'seeds' From fafa5c7c03fb6321a3f856a70c908cae8fa99216 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 00:12:51 +0800 Subject: [PATCH 02/18] add postgresql connection --- test/find_with_order_test.rb | 2 ++ test/mysql2_connection.rb | 5 +++++ test/postgresql_connection.rb | 5 +++++ test/test_helper.rb | 6 ------ 4 files changed, 12 insertions(+), 6 deletions(-) create mode 100644 test/mysql2_connection.rb create mode 100644 test/postgresql_connection.rb diff --git a/test/find_with_order_test.rb b/test/find_with_order_test.rb index 54a9bf4..3aab1e2 100644 --- a/test/find_with_order_test.rb +++ b/test/find_with_order_test.rb @@ -1,4 +1,6 @@ require 'test_helper' +# require 'mysql2_connection' +require 'postgresql_connection' class FindWithOrderTest < Minitest::Test def setup diff --git a/test/mysql2_connection.rb b/test/mysql2_connection.rb new file mode 100644 index 0000000..1e30767 --- /dev/null +++ b/test/mysql2_connection.rb @@ -0,0 +1,5 @@ +ActiveRecord::Base.establish_connection( + "adapter" => "mysql2", + "database" => "travis_ci_test", +) +load 'seeds.rb' diff --git a/test/postgresql_connection.rb b/test/postgresql_connection.rb new file mode 100644 index 0000000..642e00b --- /dev/null +++ b/test/postgresql_connection.rb @@ -0,0 +1,5 @@ +ActiveRecord::Base.establish_connection( + "adapter" => "postgresql", + "database" => "travis_ci_test", +) +load 'seeds.rb' diff --git a/test/test_helper.rb b/test/test_helper.rb index a9aa35c..adccb48 100644 --- a/test/test_helper.rb +++ b/test/test_helper.rb @@ -5,9 +5,3 @@ require 'find_with_order' require 'minitest/autorun' - -ActiveRecord::Base.establish_connection( - "adapter" => "mysql2", - "database" => "travis_ci_test", -) -require 'seeds' From 96d87b6416ecbc34e8d7652f5dea87f9438b61c2 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 00:22:45 +0800 Subject: [PATCH 03/18] add env --- .travis.yml | 3 +++ find_with_order.gemspec | 1 + gemfiles/3.2.gemfile | 5 ++++- gemfiles/4.2.gemfile | 5 ++++- gemfiles/5.0.gemfile | 5 ++++- test/find_with_order_test.rb | 10 ++++++++-- 6 files changed, 24 insertions(+), 5 deletions(-) diff --git a/.travis.yml b/.travis.yml index b1d5e03..08b7cbf 100644 --- a/.travis.yml +++ b/.travis.yml @@ -4,6 +4,9 @@ rvm: - 2.3 sudo: required dist: trusty +env: + - DB=mysql + - DB=postgres services: - postgresql before_install: diff --git a/find_with_order.gemspec b/find_with_order.gemspec index b0e78c5..6b73617 100644 --- a/find_with_order.gemspec +++ b/find_with_order.gemspec @@ -33,5 +33,6 @@ Gem::Specification.new do |spec| spec.add_dependency "rails", ">= 3" spec.add_dependency "mysql2", ">= 0.3" + spec.add_dependency "pg", "~> 0.18" end diff --git a/gemfiles/3.2.gemfile b/gemfiles/3.2.gemfile index 5a438e5..0247d1a 100644 --- a/gemfiles/3.2.gemfile +++ b/gemfiles/3.2.gemfile @@ -5,7 +5,10 @@ source 'https://rubygems.org' gem "activerecord", "~> 3.2" group :test do - gem 'mysql2' , '0.3.21' + case ENV['DB'] + when "mysql" ; gem 'mysql2' , '0.3.21' + when "postgres" ; gem 'pg', '~> 0.18' + end gem "simplecov" gem "codeclimate-test-reporter", "~> 1.0.0" end diff --git a/gemfiles/4.2.gemfile b/gemfiles/4.2.gemfile index bc40fb3..e54b064 100644 --- a/gemfiles/4.2.gemfile +++ b/gemfiles/4.2.gemfile @@ -5,7 +5,10 @@ source 'https://rubygems.org' gem "activerecord", "~> 4.2" group :test do - gem 'mysql2' , '0.3.21' + case ENV['DB'] + when "mysql" ; gem 'mysql2' , '0.3.21' + when "postgres" ; gem 'pg', '~> 0.18' + end gem "simplecov" gem "codeclimate-test-reporter", "~> 1.0.0" end diff --git a/gemfiles/5.0.gemfile b/gemfiles/5.0.gemfile index 4c03d16..a3b1a2d 100644 --- a/gemfiles/5.0.gemfile +++ b/gemfiles/5.0.gemfile @@ -5,7 +5,10 @@ source 'https://rubygems.org' gem "activerecord", "~> 5.0" group :test do - gem 'mysql2' , '0.3.21' + case ENV['DB'] + when "mysql" ; gem 'mysql2' , '0.3.21' + when "postgres" ; gem 'pg', '~> 0.18' + end gem "simplecov" gem "codeclimate-test-reporter", "~> 1.0.0" end diff --git a/test/find_with_order_test.rb b/test/find_with_order_test.rb index 3aab1e2..9a14f68 100644 --- a/test/find_with_order_test.rb +++ b/test/find_with_order_test.rb @@ -1,6 +1,12 @@ require 'test_helper' -# require 'mysql2_connection' -require 'postgresql_connection' +case +when defined?(Mysql2) + require 'mysql2_connection' +when defined?(PG) + require 'postgresql_connection' +else + raise "no database" +end class FindWithOrderTest < Minitest::Test def setup From 24d7f680bd6346f695c4553af485fd8552e8a051 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 00:24:41 +0800 Subject: [PATCH 04/18] no tab --- gemfiles/3.2.gemfile | 8 ++++---- gemfiles/4.2.gemfile | 6 +++--- gemfiles/5.0.gemfile | 6 +++--- 3 files changed, 10 insertions(+), 10 deletions(-) diff --git a/gemfiles/3.2.gemfile b/gemfiles/3.2.gemfile index 0247d1a..920010a 100644 --- a/gemfiles/3.2.gemfile +++ b/gemfiles/3.2.gemfile @@ -5,10 +5,10 @@ source 'https://rubygems.org' gem "activerecord", "~> 3.2" group :test do - case ENV['DB'] - when "mysql" ; gem 'mysql2' , '0.3.21' - when "postgres" ; gem 'pg', '~> 0.18' - end + case ENV['DB'] + when "mysql" ; gem 'mysql2' , '0.3.21' + when "postgres" ; gem 'pg', '~> 0.18' + end gem "simplecov" gem "codeclimate-test-reporter", "~> 1.0.0" end diff --git a/gemfiles/4.2.gemfile b/gemfiles/4.2.gemfile index e54b064..6e4e8fc 100644 --- a/gemfiles/4.2.gemfile +++ b/gemfiles/4.2.gemfile @@ -6,9 +6,9 @@ gem "activerecord", "~> 4.2" group :test do case ENV['DB'] - when "mysql" ; gem 'mysql2' , '0.3.21' - when "postgres" ; gem 'pg', '~> 0.18' - end + when "mysql" ; gem 'mysql2' , '0.3.21' + when "postgres" ; gem 'pg', '~> 0.18' + end gem "simplecov" gem "codeclimate-test-reporter", "~> 1.0.0" end diff --git a/gemfiles/5.0.gemfile b/gemfiles/5.0.gemfile index a3b1a2d..2934b2a 100644 --- a/gemfiles/5.0.gemfile +++ b/gemfiles/5.0.gemfile @@ -6,9 +6,9 @@ gem "activerecord", "~> 5.0" group :test do case ENV['DB'] - when "mysql" ; gem 'mysql2' , '0.3.21' - when "postgres" ; gem 'pg', '~> 0.18' - end + when "mysql" ; gem 'mysql2' , '0.3.21' + when "postgres" ; gem 'pg', '~> 0.18' + end gem "simplecov" gem "codeclimate-test-reporter", "~> 1.0.0" end From 291c7bc32a2d9cb8b35822036d10b66c1d651f5e Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 00:28:12 +0800 Subject: [PATCH 05/18] no database error --- test/find_with_order_test.rb | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/test/find_with_order_test.rb b/test/find_with_order_test.rb index 9a14f68..8187274 100644 --- a/test/find_with_order_test.rb +++ b/test/find_with_order_test.rb @@ -1,8 +1,8 @@ require 'test_helper' -case -when defined?(Mysql2) +case ENV['DB'] +when 'mysql' require 'mysql2_connection' -when defined?(PG) +when 'postgres' require 'postgresql_connection' else raise "no database" From 0c91700ec79c7812e57e1ff286b4a45f52c358ee Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 00:33:50 +0800 Subject: [PATCH 06/18] update README --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 9119bd9..d398803 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Find then sort by hash mapping 1.120000 0.010000 1.130000 ( 1.192891) ## Development -After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. +After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test DB=mysql`/`rake test DB=postgres` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). From c2da003da65dbca2bf279163f95760b064a2f9f9 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 00:44:17 +0800 Subject: [PATCH 07/18] modulize mysql, postgresql --- lib/find_with_order.rb | 8 ++++---- lib/find_with_order/mysql_support.rb | 13 +++++++++++++ lib/find_with_order/postgresql_support.rb | 13 +++++++++++++ 3 files changed, 30 insertions(+), 4 deletions(-) create mode 100644 lib/find_with_order/mysql_support.rb create mode 100644 lib/find_with_order/postgresql_support.rb diff --git a/lib/find_with_order.rb b/lib/find_with_order.rb index 7eb870f..1b9238f 100644 --- a/lib/find_with_order.rb +++ b/lib/find_with_order.rb @@ -1,16 +1,16 @@ require "find_with_order/version" +require "find_with_order/mysql_support" +require "find_with_order/postgresql_support" require 'active_record' class << ActiveRecord::Base def find_with_order(ids) return none if ids.blank? - ids = ids.uniq - return where(id: ids).order("field(#{table_name}.id, #{ids.join(',')})").to_a + FindWithOrder::MysqlSupport.find_with_order(self, ids) end def where_with_order(column, ids) return none if ids.blank? - ids = ids.uniq - return where(column => ids).order("field(#{column}, #{ids.map(&:inspect).join(',')})") + FindWithOrder::MysqlSupport.where_with_order(self, column, ids) end end unless ActiveRecord::Base.respond_to?(:none) # extend only if not implement yet diff --git a/lib/find_with_order/mysql_support.rb b/lib/find_with_order/mysql_support.rb new file mode 100644 index 0000000..68b59a8 --- /dev/null +++ b/lib/find_with_order/mysql_support.rb @@ -0,0 +1,13 @@ +module FindWithOrder + VERSION = "1.0.1" + module MysqlSupport + def self.find_with_order(relation, ids) + ids = ids.uniq + return relation.where(id: ids).order("field(#{relation.table_name}.id, #{ids.join(',')})").to_a + end + def self.where_with_order(relation, column, ids) + ids = ids.uniq + return relation.where(column => ids).order("field(#{column}, #{ids.map(&:inspect).join(',')})") + end + end +end diff --git a/lib/find_with_order/postgresql_support.rb b/lib/find_with_order/postgresql_support.rb new file mode 100644 index 0000000..6a35f1b --- /dev/null +++ b/lib/find_with_order/postgresql_support.rb @@ -0,0 +1,13 @@ +module FindWithOrder + VERSION = "1.0.1" + module PostgreSqlSupport + def self.find_with_order(relation, ids) + ids = ids.uniq + return relation.where(id: ids).order("field(#{relation.table_name}.id, #{ids.join(',')})").to_a + end + def self.where_with_order(relation, column, ids) + ids = ids.uniq + return relation.where(column => ids).order("field(#{column}, #{ids.map(&:inspect).join(',')})") + end + end +end From 67ed0cf5788da7de02d70c90b24d1c7c39e7ca6f Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 00:55:36 +0800 Subject: [PATCH 08/18] line pg support --- .travis.yml | 2 +- README.md | 2 +- lib/find_with_order.rb | 8 +++++--- .../{postgresql_support.rb => pg_support.rb} | 2 +- test/find_with_order_test.rb | 2 +- 5 files changed, 9 insertions(+), 7 deletions(-) rename lib/find_with_order/{postgresql_support.rb => pg_support.rb} (93%) diff --git a/.travis.yml b/.travis.yml index 08b7cbf..a0401c6 100644 --- a/.travis.yml +++ b/.travis.yml @@ -6,7 +6,7 @@ sudo: required dist: trusty env: - DB=mysql - - DB=postgres + - DB=pg services: - postgresql before_install: diff --git a/README.md b/README.md index d398803..8d9fc1a 100644 --- a/README.md +++ b/README.md @@ -56,7 +56,7 @@ Find then sort by hash mapping 1.120000 0.010000 1.130000 ( 1.192891) ## Development -After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test DB=mysql`/`rake test DB=postgres` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. +After checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test DB=mysql` / `rake test DB=pg` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment. To install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org). diff --git a/lib/find_with_order.rb b/lib/find_with_order.rb index 1b9238f..bc741ed 100644 --- a/lib/find_with_order.rb +++ b/lib/find_with_order.rb @@ -1,16 +1,18 @@ require "find_with_order/version" require "find_with_order/mysql_support" -require "find_with_order/postgresql_support" +require "find_with_order/pg_support" require 'active_record' class << ActiveRecord::Base def find_with_order(ids) return none if ids.blank? - FindWithOrder::MysqlSupport.find_with_order(self, ids) + return FindWithOrder::MysqlSupport.find_with_order(self, ids) if defined?(Mysql2) + return FindWithOrder::PGSupport.find_with_order(self, ids) if defined?(PG) end def where_with_order(column, ids) return none if ids.blank? - FindWithOrder::MysqlSupport.where_with_order(self, column, ids) + return FindWithOrder::MysqlSupport.where_with_order(self, column, ids) if defined?(Mysql2) + return FindWithOrder::PGSupport.where_with_order(self, column, ids) if defined?(PG) end end unless ActiveRecord::Base.respond_to?(:none) # extend only if not implement yet diff --git a/lib/find_with_order/postgresql_support.rb b/lib/find_with_order/pg_support.rb similarity index 93% rename from lib/find_with_order/postgresql_support.rb rename to lib/find_with_order/pg_support.rb index 6a35f1b..9ef3849 100644 --- a/lib/find_with_order/postgresql_support.rb +++ b/lib/find_with_order/pg_support.rb @@ -1,6 +1,6 @@ module FindWithOrder VERSION = "1.0.1" - module PostgreSqlSupport + module PGSupport def self.find_with_order(relation, ids) ids = ids.uniq return relation.where(id: ids).order("field(#{relation.table_name}.id, #{ids.join(',')})").to_a diff --git a/test/find_with_order_test.rb b/test/find_with_order_test.rb index 8187274..3158777 100644 --- a/test/find_with_order_test.rb +++ b/test/find_with_order_test.rb @@ -2,7 +2,7 @@ case ENV['DB'] when 'mysql' require 'mysql2_connection' -when 'postgres' +when 'pg' require 'postgresql_connection' else raise "no database" From feba54083096ef6f284d4433e0cca420443d111c Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 01:18:31 +0800 Subject: [PATCH 09/18] support PG --- lib/find_with_order/pg_support.rb | 10 ++++++++-- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/lib/find_with_order/pg_support.rb b/lib/find_with_order/pg_support.rb index 9ef3849..a1f0bbc 100644 --- a/lib/find_with_order/pg_support.rb +++ b/lib/find_with_order/pg_support.rb @@ -3,11 +3,17 @@ module FindWithOrder module PGSupport def self.find_with_order(relation, ids) ids = ids.uniq - return relation.where(id: ids).order("field(#{relation.table_name}.id, #{ids.join(',')})").to_a + return relation.where(id: ids).order("array_position(ARRAY[#{ids.join(',')}], #{relation.table_name}.id)").to_a end def self.where_with_order(relation, column, ids) ids = ids.uniq - return relation.where(column => ids).order("field(#{column}, #{ids.map(&:inspect).join(',')})") + relation = relation.where(column => ids) + case ids.first + when Numeric ; return relation.order("array_position(ARRAY[#{ids.join(',')}], #{column})") + when String ; return relation.order("array_position(ARRAY['#{ids.map{|s| s.gsub("'", "\\'") }.join('\',\'')}']::varchar[], #{column})") + else + raise 'not support type: #{ids.first.class}' + end end end end From cccf0be80b64f9415df7c87074892378f0b54cbe Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 01:30:14 +0800 Subject: [PATCH 10/18] escape quote --- lib/find_with_order/pg_support.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/find_with_order/pg_support.rb b/lib/find_with_order/pg_support.rb index a1f0bbc..83cbce3 100644 --- a/lib/find_with_order/pg_support.rb +++ b/lib/find_with_order/pg_support.rb @@ -10,7 +10,7 @@ def self.where_with_order(relation, column, ids) relation = relation.where(column => ids) case ids.first when Numeric ; return relation.order("array_position(ARRAY[#{ids.join(',')}], #{column})") - when String ; return relation.order("array_position(ARRAY['#{ids.map{|s| s.gsub("'", "\\'") }.join('\',\'')}']::varchar[], #{column})") + when String ; return relation.order("array_position(ARRAY['#{ids.map{|s| s.gsub("'", "''") }.join('\',\'')}']::varchar[], #{column})") else raise 'not support type: #{ids.first.class}' end From d83638cd33223a093f82da45e81ee2f4a011227f Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 01:54:05 +0800 Subject: [PATCH 11/18] postgresql doesn't support distinct + order --- test/find_with_order_test.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/test/find_with_order_test.rb b/test/find_with_order_test.rb index 3158777..30687de 100644 --- a/test/find_with_order_test.rb +++ b/test/find_with_order_test.rb @@ -65,8 +65,8 @@ def test_association_find_with_order def test_ambiguous_id_in_join order = [2, 1, 3] - assert_equal order, User.joins(:posts).uniq.find_with_order(order).map(&:id) - assert_equal order, User.joins(:posts).uniq.where_with_order(:'users.id', order).pluck(:id) + assert_equal order, User.joins(:posts).find_with_order(order).map(&:id).uniq #postgresql doesn't support distinct + order + assert_equal order, User.joins(:posts).where_with_order(:'users.id', order).pluck(:id).uniq end end From dce959d654ccfd1f9671ab62576a4573dce7fea3 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 01:56:35 +0800 Subject: [PATCH 12/18] remove unneeded --- lib/find_with_order/mysql_support.rb | 1 - lib/find_with_order/pg_support.rb | 1 - 2 files changed, 2 deletions(-) diff --git a/lib/find_with_order/mysql_support.rb b/lib/find_with_order/mysql_support.rb index 68b59a8..2920998 100644 --- a/lib/find_with_order/mysql_support.rb +++ b/lib/find_with_order/mysql_support.rb @@ -1,5 +1,4 @@ module FindWithOrder - VERSION = "1.0.1" module MysqlSupport def self.find_with_order(relation, ids) ids = ids.uniq diff --git a/lib/find_with_order/pg_support.rb b/lib/find_with_order/pg_support.rb index 83cbce3..e9cb73e 100644 --- a/lib/find_with_order/pg_support.rb +++ b/lib/find_with_order/pg_support.rb @@ -1,5 +1,4 @@ module FindWithOrder - VERSION = "1.0.1" module PGSupport def self.find_with_order(relation, ids) ids = ids.uniq From 329652020265b91dc442efde40b20fa1f1c90889 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 02:10:50 +0800 Subject: [PATCH 13/18] array_position is only support in PG >= 9.5 --- lib/find_with_order/pg_support.rb | 16 +++++++++++++--- 1 file changed, 13 insertions(+), 3 deletions(-) diff --git a/lib/find_with_order/pg_support.rb b/lib/find_with_order/pg_support.rb index e9cb73e..0612747 100644 --- a/lib/find_with_order/pg_support.rb +++ b/lib/find_with_order/pg_support.rb @@ -2,14 +2,24 @@ module FindWithOrder module PGSupport def self.find_with_order(relation, ids) ids = ids.uniq - return relation.where(id: ids).order("array_position(ARRAY[#{ids.join(',')}], #{relation.table_name}.id)").to_a + # return relation.where(id: ids).order("array_position(ARRAY[#{ids.join(',')}], #{relation.table_name}.id)").to_a #array_position is only support in PG >= 9.5 + return relation.where(id: ids) + .joins("JOIN (SELECT id.val, row_number() over() FROM (VALUES(#{ids.join('),(')})) AS id(val)) AS id ON (#{relation.table_name}.id = id.val)") + .order('row_number') end def self.where_with_order(relation, column, ids) ids = ids.uniq relation = relation.where(column => ids) case ids.first - when Numeric ; return relation.order("array_position(ARRAY[#{ids.join(',')}], #{column})") - when String ; return relation.order("array_position(ARRAY['#{ids.map{|s| s.gsub("'", "''") }.join('\',\'')}']::varchar[], #{column})") + when Numeric + # return relation.order("array_position(ARRAY[#{ids.join(',')}], #{column})") #array_position is only support in PG >= 9.5 + return relation.joins("JOIN (SELECT id.val, row_number() over() FROM (VALUES(#{ids.join('),(')})) AS id(val)) AS id ON (#{column} = id.val)") + .order('row_number') + when String + ids = ids.map{|s| s.gsub("'", "''") } + # return relation.order("array_position(ARRAY['#{ids.join("','")}']::varchar[], #{column})") #array_position is only support in PG >= 9.5 + return relation.joins("JOIN (SELECT id.val, row_number() over() FROM (VALUES('#{ids.join("'),('")}')) AS id(val)) AS id ON (#{column} = id.val)") + .order('row_number') else raise 'not support type: #{ids.first.class}' end From 9195e888faf41bb1cfb072f46f52df8a55294c97 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 02:28:25 +0800 Subject: [PATCH 14/18] default use mysql --- lib/find_with_order.rb | 4 ++-- test/mysql2_connection.rb | 2 +- test/postgresql_connection.rb | 2 +- 3 files changed, 4 insertions(+), 4 deletions(-) diff --git a/lib/find_with_order.rb b/lib/find_with_order.rb index bc741ed..ac18752 100644 --- a/lib/find_with_order.rb +++ b/lib/find_with_order.rb @@ -6,13 +6,13 @@ class << ActiveRecord::Base def find_with_order(ids) return none if ids.blank? - return FindWithOrder::MysqlSupport.find_with_order(self, ids) if defined?(Mysql2) return FindWithOrder::PGSupport.find_with_order(self, ids) if defined?(PG) + return FindWithOrder::MysqlSupport.find_with_order(self, ids) end def where_with_order(column, ids) return none if ids.blank? - return FindWithOrder::MysqlSupport.where_with_order(self, column, ids) if defined?(Mysql2) return FindWithOrder::PGSupport.where_with_order(self, column, ids) if defined?(PG) + return FindWithOrder::MysqlSupport.where_with_order(self, column, ids) end end unless ActiveRecord::Base.respond_to?(:none) # extend only if not implement yet diff --git a/test/mysql2_connection.rb b/test/mysql2_connection.rb index 1e30767..d303e14 100644 --- a/test/mysql2_connection.rb +++ b/test/mysql2_connection.rb @@ -2,4 +2,4 @@ "adapter" => "mysql2", "database" => "travis_ci_test", ) -load 'seeds.rb' +require 'seeds' diff --git a/test/postgresql_connection.rb b/test/postgresql_connection.rb index 642e00b..3dcd0e7 100644 --- a/test/postgresql_connection.rb +++ b/test/postgresql_connection.rb @@ -2,4 +2,4 @@ "adapter" => "postgresql", "database" => "travis_ci_test", ) -load 'seeds.rb' +require 'seeds' From c7ecf0e1e8deb6083ed2f000b63b6ac95c1a379b Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 02:32:19 +0800 Subject: [PATCH 15/18] little refactor --- lib/find_with_order/pg_support.rb | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/lib/find_with_order/pg_support.rb b/lib/find_with_order/pg_support.rb index 0612747..c4d319a 100644 --- a/lib/find_with_order/pg_support.rb +++ b/lib/find_with_order/pg_support.rb @@ -16,12 +16,12 @@ def self.where_with_order(relation, column, ids) return relation.joins("JOIN (SELECT id.val, row_number() over() FROM (VALUES(#{ids.join('),(')})) AS id(val)) AS id ON (#{column} = id.val)") .order('row_number') when String - ids = ids.map{|s| s.gsub("'", "''") } + ids.map!{|s| s.gsub("'", "''") } # return relation.order("array_position(ARRAY['#{ids.join("','")}']::varchar[], #{column})") #array_position is only support in PG >= 9.5 return relation.joins("JOIN (SELECT id.val, row_number() over() FROM (VALUES('#{ids.join("'),('")}')) AS id(val)) AS id ON (#{column} = id.val)") .order('row_number') else - raise 'not support type: #{ids.first.class}' + raise "not support type: #{ids.first.class}" end end end From 1c63c2d49d9a2b14157f68e176fdace7d86be84e Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 02:36:35 +0800 Subject: [PATCH 16/18] fix gemspec (mysql2, pg is optional) --- find_with_order.gemspec | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/find_with_order.gemspec b/find_with_order.gemspec index 6b73617..707dc4b 100644 --- a/find_with_order.gemspec +++ b/find_with_order.gemspec @@ -30,9 +30,9 @@ Gem::Specification.new do |spec| spec.add_development_dependency "bundler", "~> 1.11" spec.add_development_dependency "rake", "~> 12.0" spec.add_development_dependency "minitest", "~> 5.0" + spec.add_development_dependency "mysql2", ">= 0.3" + spec.add_development_dependency "pg", "~> 0.18" spec.add_dependency "rails", ">= 3" - spec.add_dependency "mysql2", ">= 0.3" - spec.add_dependency "pg", "~> 0.18" end From 2406b3e16ac97a0b3655520e7d5f4e1a7cc74a13 Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 14:20:27 +0800 Subject: [PATCH 17/18] use #quote_string to escape single quote and backslash --- lib/find_with_order/pg_support.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/lib/find_with_order/pg_support.rb b/lib/find_with_order/pg_support.rb index c4d319a..3c3e161 100644 --- a/lib/find_with_order/pg_support.rb +++ b/lib/find_with_order/pg_support.rb @@ -16,7 +16,7 @@ def self.where_with_order(relation, column, ids) return relation.joins("JOIN (SELECT id.val, row_number() over() FROM (VALUES(#{ids.join('),(')})) AS id(val)) AS id ON (#{column} = id.val)") .order('row_number') when String - ids.map!{|s| s.gsub("'", "''") } + ids.map!{|s| ActiveRecord::Base.connection.quote_string(s) } # return relation.order("array_position(ARRAY['#{ids.join("','")}']::varchar[], #{column})") #array_position is only support in PG >= 9.5 return relation.joins("JOIN (SELECT id.val, row_number() over() FROM (VALUES('#{ids.join("'),('")}')) AS id(val)) AS id ON (#{column} = id.val)") .order('row_number') From 2165b44fdcf441661a861b58a101824cd773a2fa Mon Sep 17 00:00:00 2001 From: khiav reoy Date: Sun, 12 Mar 2017 14:27:08 +0800 Subject: [PATCH 18/18] DRYing: ids = ids.uniq --- lib/find_with_order.rb | 2 ++ lib/find_with_order/mysql_support.rb | 2 -- lib/find_with_order/pg_support.rb | 2 -- 3 files changed, 2 insertions(+), 4 deletions(-) diff --git a/lib/find_with_order.rb b/lib/find_with_order.rb index ac18752..cb2385f 100644 --- a/lib/find_with_order.rb +++ b/lib/find_with_order.rb @@ -6,11 +6,13 @@ class << ActiveRecord::Base def find_with_order(ids) return none if ids.blank? + ids = ids.uniq return FindWithOrder::PGSupport.find_with_order(self, ids) if defined?(PG) return FindWithOrder::MysqlSupport.find_with_order(self, ids) end def where_with_order(column, ids) return none if ids.blank? + ids = ids.uniq return FindWithOrder::PGSupport.where_with_order(self, column, ids) if defined?(PG) return FindWithOrder::MysqlSupport.where_with_order(self, column, ids) end diff --git a/lib/find_with_order/mysql_support.rb b/lib/find_with_order/mysql_support.rb index 2920998..f28f0cc 100644 --- a/lib/find_with_order/mysql_support.rb +++ b/lib/find_with_order/mysql_support.rb @@ -1,11 +1,9 @@ module FindWithOrder module MysqlSupport def self.find_with_order(relation, ids) - ids = ids.uniq return relation.where(id: ids).order("field(#{relation.table_name}.id, #{ids.join(',')})").to_a end def self.where_with_order(relation, column, ids) - ids = ids.uniq return relation.where(column => ids).order("field(#{column}, #{ids.map(&:inspect).join(',')})") end end diff --git a/lib/find_with_order/pg_support.rb b/lib/find_with_order/pg_support.rb index 3c3e161..a7344e3 100644 --- a/lib/find_with_order/pg_support.rb +++ b/lib/find_with_order/pg_support.rb @@ -1,14 +1,12 @@ module FindWithOrder module PGSupport def self.find_with_order(relation, ids) - ids = ids.uniq # return relation.where(id: ids).order("array_position(ARRAY[#{ids.join(',')}], #{relation.table_name}.id)").to_a #array_position is only support in PG >= 9.5 return relation.where(id: ids) .joins("JOIN (SELECT id.val, row_number() over() FROM (VALUES(#{ids.join('),(')})) AS id(val)) AS id ON (#{relation.table_name}.id = id.val)") .order('row_number') end def self.where_with_order(relation, column, ids) - ids = ids.uniq relation = relation.where(column => ids) case ids.first when Numeric