active_sort_order 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (47) hide show
  1. checksums.yaml +7 -0
  2. data/CHANGELOG.md +10 -0
  3. data/LICENSE +21 -0
  4. data/README.md +140 -0
  5. data/Rakefile +21 -0
  6. data/lib/active_sort_order.rb +11 -0
  7. data/lib/active_sort_order/concerns/sort_order_concern.rb +67 -0
  8. data/lib/active_sort_order/version.rb +3 -0
  9. data/test/dummy_app/Rakefile +7 -0
  10. data/test/dummy_app/app/assets/config/manifest.js +3 -0
  11. data/test/dummy_app/app/assets/javascripts/application.js +0 -0
  12. data/test/dummy_app/app/assets/stylesheets/application.css +3 -0
  13. data/test/dummy_app/app/controllers/application_controller.rb +3 -0
  14. data/test/dummy_app/app/models/application_record.rb +3 -0
  15. data/test/dummy_app/app/models/post.rb +3 -0
  16. data/test/dummy_app/app/models/post_with_base_order_a.rb +7 -0
  17. data/test/dummy_app/app/models/post_with_base_order_a_and_b.rb +7 -0
  18. data/test/dummy_app/app/models/post_with_base_order_b.rb +7 -0
  19. data/test/dummy_app/app/models/post_with_base_order_b_and_a.rb +7 -0
  20. data/test/dummy_app/app/models/post_with_volatile_base_order.rb +7 -0
  21. data/test/dummy_app/app/models/test_helper.rb +0 -0
  22. data/test/dummy_app/app/views/layouts/application.html.erb +14 -0
  23. data/test/dummy_app/config.ru +4 -0
  24. data/test/dummy_app/config/application.rb +66 -0
  25. data/test/dummy_app/config/boot.rb +10 -0
  26. data/test/dummy_app/config/database.yml +11 -0
  27. data/test/dummy_app/config/environment.rb +5 -0
  28. data/test/dummy_app/config/environments/development.rb +30 -0
  29. data/test/dummy_app/config/environments/production.rb +60 -0
  30. data/test/dummy_app/config/environments/test.rb +41 -0
  31. data/test/dummy_app/config/initializers/backtrace_silencers.rb +7 -0
  32. data/test/dummy_app/config/initializers/inflections.rb +10 -0
  33. data/test/dummy_app/config/initializers/mime_types.rb +5 -0
  34. data/test/dummy_app/config/initializers/secret_token.rb +11 -0
  35. data/test/dummy_app/config/initializers/session_store.rb +8 -0
  36. data/test/dummy_app/config/initializers/wrap_parameters.rb +14 -0
  37. data/test/dummy_app/config/locales/en.yml +5 -0
  38. data/test/dummy_app/config/routes.rb +6 -0
  39. data/test/dummy_app/config/secrets.yml +22 -0
  40. data/test/dummy_app/db/migrate/20210128155312_set_up_test_tables.rb +9 -0
  41. data/test/dummy_app/db/schema.rb +19 -0
  42. data/test/dummy_app/db/test.sqlite3 +0 -0
  43. data/test/dummy_app/log/test.log +10098 -0
  44. data/test/test_helper.rb +53 -0
  45. data/test/unit/active_sort_order_test.rb +116 -0
  46. data/test/unit/errors_test.rb +171 -0
  47. metadata +156 -0
@@ -0,0 +1,53 @@
1
+ #$LOAD_PATH.unshift File.expand_path("../lib", __dir__)
2
+ ENV["RAILS_ENV"] = "test"
3
+
4
+ require "active_sort_order"
5
+
6
+ ### Instantiates Rails
7
+ require File.expand_path("../dummy_app/config/environment.rb", __FILE__)
8
+
9
+ require "rails/test_help"
10
+
11
+ class ActiveSupport::TestCase
12
+ # Setup all fixtures in test/fixtures/*.yml for all tests in alphabetical order.
13
+ fixtures :all
14
+ end
15
+
16
+ Rails.backtrace_cleaner.remove_silencers!
17
+
18
+ require 'minitest/reporters'
19
+ Minitest::Reporters.use!(
20
+ Minitest::Reporters::DefaultReporter.new,
21
+ ENV,
22
+ Minitest.backtrace_filter
23
+ )
24
+
25
+ require "minitest/autorun"
26
+
27
+ # Run any available migration
28
+ if ActiveRecord.gem_version >= Gem::Version.new("6.0")
29
+ ActiveRecord::MigrationContext.new(File.expand_path("dummy_app/db/migrate/", __dir__), ActiveRecord::SchemaMigration).migrate
30
+ elsif ActiveRecord.gem_version >= Gem::Version.new("5.2")
31
+ ActiveRecord::MigrationContext.new(File.expand_path("dummy_app/db/migrate/", __dir__)).migrate
32
+ else
33
+ ActiveRecord::Migrator.migrate File.expand_path("dummy_app/db/migrate/", __dir__)
34
+ end
35
+
36
+ [Post].each do |klass|
37
+ ### REGULAR SQL
38
+ #ActiveRecord::Base.connection.execute("TRUNCATE TABLE #{klass.table_name}")
39
+
40
+ ### SQLITE
41
+ ActiveRecord::Base.connection.execute("DELETE FROM #{klass.table_name};")
42
+ ActiveRecord::Base.connection.execute("UPDATE `sqlite_sequence` SET `seq` = 0 WHERE `name` = '#{klass.table_name}';")
43
+ end
44
+
45
+ DATA = {}.with_indifferent_access
46
+
47
+ DATA[:posts] = [
48
+ Post.find_or_create_by!(a: 1, b: 3),
49
+ Post.find_or_create_by!(a: 2, b: 2),
50
+ Post.find_or_create_by!(a: 3, b: 2),
51
+ Post.find_or_create_by!(a: 4, b: 1),
52
+ Post.find_or_create_by!(a: 5, b: 1),
53
+ ].shuffle
@@ -0,0 +1,116 @@
1
+ require "test_helper"
2
+
3
+ class ActiveSortOrderTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def teardown
9
+ end
10
+
11
+ def test_exposes_main_module
12
+ assert ActiveSortOrder.is_a?(Module)
13
+ end
14
+
15
+ def test_exposes_version
16
+ assert ActiveSortOrder::VERSION
17
+ end
18
+
19
+ def test_class_base_sort_order_only
20
+ assert_equal Post.all.count, DATA[:posts].count
21
+
22
+ sorted = PostWithBaseOrderA.all.sort_order
23
+
24
+ expected = DATA[:posts].sort_by{|item| item.a }
25
+
26
+ sorted.each_with_index do |item, i|
27
+ assert_equal expected[i].id, item.id
28
+ end
29
+
30
+ sorted = PostWithBaseOrderB.all.sort_order
31
+
32
+ expected = DATA[:posts].sort_by{|item| item.b }
33
+
34
+ sorted.each_with_index do |item, i|
35
+ assert_equal expected[i].b, item.b ### use b instead of id as its not unique
36
+ end
37
+
38
+ sorted = PostWithBaseOrderAAndB.all.sort_order
39
+
40
+ expected = DATA[:posts].sort_by{|item| [item.a, item.b] }
41
+
42
+ sorted.each_with_index do |item, i|
43
+ assert_equal expected[i].id, item.id
44
+ end
45
+
46
+ sorted = PostWithBaseOrderBAndA.all.sort_order
47
+
48
+ expected = DATA[:posts].sort_by{|item| [item.b, item.a] }
49
+
50
+ sorted.each_with_index do |item, i|
51
+ assert_equal expected[i].id, item.id
52
+ end
53
+ end
54
+
55
+ def test_override_base_sort_order_only
56
+ assert_equal Post.all.count, DATA[:posts].count
57
+
58
+ sorted = PostWithBaseOrderA.order(b: :desc).sort_order(base_sort_order: "posts.b ASC")
59
+
60
+ expected = DATA[:posts].sort_by{|item| item.b }
61
+
62
+ sorted.each_with_index do |item, i|
63
+ assert_equal expected[i].b, item.b ### use b instead of id as its not unique
64
+ end
65
+
66
+ expected = DATA[:posts].sort_by{|item| item.id }
67
+
68
+ ### NIL & FALSE
69
+ [nil, false].each do |v|
70
+ sorted = PostWithBaseOrderA.order(a: :desc).sort_order(base_sort_order: v)
71
+
72
+ sorted.each_with_index do |item, i|
73
+ assert_equal expected[i].id, item.id
74
+ end
75
+ end
76
+ end
77
+
78
+ def test_sort_only
79
+ assert_equal Post.all.count, DATA[:posts].count
80
+
81
+ expected = DATA[:posts].sort_by{|item| item.a }.reverse
82
+
83
+ sorted = PostWithBaseOrderA.all.sort_order(:a, :desc)
84
+
85
+ sorted.each_with_index do |item, i|
86
+ assert_equal expected[i].id, item.id
87
+ end
88
+
89
+ sorted = PostWithBaseOrderA.all.sort_order("posts.a", "DESC")
90
+
91
+ sorted.each_with_index do |item, i|
92
+ assert_equal expected[i].id, item.id
93
+ end
94
+ end
95
+
96
+ def test_base_sort_order_and_sort
97
+ assert_equal Post.all.count, DATA[:posts].count
98
+
99
+ sorted = PostWithBaseOrderA.all.sort_order("posts.a", "DESC")
100
+
101
+ expected = DATA[:posts].sort_by{|item| item.a }.reverse
102
+
103
+ sorted.each_with_index do |item, i|
104
+ assert_equal expected[i].id, item.id
105
+ end
106
+
107
+ sorted = PostWithBaseOrderB.all.sort_order("posts.b", "DESC")
108
+
109
+ expected = DATA[:posts].sort_by{|item| item.b }.reverse
110
+
111
+ sorted.each_with_index do |item, i|
112
+ assert_equal expected[i].b, item.b ### use b instead of id as its not unique
113
+ end
114
+ end
115
+
116
+ end
@@ -0,0 +1,171 @@
1
+ require "test_helper"
2
+
3
+ class ActiveSortOrderTest < ActiveSupport::TestCase
4
+
5
+ def setup
6
+ end
7
+
8
+ def teardown
9
+ end
10
+
11
+ def test_sort_str_errors
12
+ ### TEST VALID
13
+ valid = [
14
+ "foo",
15
+ :foo,
16
+ nil,
17
+ "",
18
+ ]
19
+
20
+ valid.each do |v|
21
+ Post.sort_order(v, :asc).limit(1)
22
+ end
23
+
24
+ ### TEST INVALID
25
+ invalid = [
26
+ true,
27
+ false,
28
+ [],
29
+ Object.new,
30
+ ]
31
+
32
+ invalid.each do |v|
33
+ assert_raise ArgumentError do
34
+ Post.sort_order(v, :asc).limit(1)
35
+ end
36
+ end
37
+
38
+ assert_raise ArgumentError do
39
+ Post.sort_order(Object.new, :asc).limit(1)
40
+ end
41
+
42
+ ### TEST UNIQUE CASES
43
+
44
+ ### HASH - this is allowed because its treated as keyword arguments
45
+ Post.sort_order({}).limit(1)
46
+
47
+ assert_raise do
48
+ Post.sort_order({}, :desc).limit(1)
49
+ end
50
+ end
51
+
52
+ def test_sort_direction_errors
53
+ valid_directions = [
54
+ "ASC",
55
+ "DESC",
56
+ "ASC NULLS FIRST",
57
+ "ASC NULLS LAST",
58
+ "DESC NULLS FIRST",
59
+ "DESC NULLS LAST",
60
+ nil,
61
+ "",
62
+
63
+ ### NASTY BUT TECHNICALLY ALLOWED BECAUSE OF SANITIZATION TECHNIQUE
64
+ "ASC NULLS FIRST",
65
+ " ASC ",
66
+ "ASC\n",
67
+ "ASC\tNULLS\tFirst",
68
+ ].freeze
69
+
70
+ valid_directions.each do |direction|
71
+ PostWithBaseOrderA.sort_order("x", direction).limit(1)
72
+
73
+ if direction
74
+ direction = direction.try!(:downcase)
75
+
76
+ PostWithBaseOrderA.sort_order("x", direction).limit(1)
77
+
78
+ direction = direction.try!(:to_sym)
79
+
80
+ PostWithBaseOrderA.sort_order("foobar", direction).limit(1)
81
+ end
82
+ end
83
+
84
+ bad_directions = [
85
+ false,
86
+ true,
87
+ Object.new,
88
+ [],
89
+ 'ASCC',
90
+ ].freeze
91
+
92
+ bad_directions.each do |direction|
93
+ assert_raise ArgumentError do
94
+ PostWithBaseOrderA.sort_order("foobar", direction).limit(1)
95
+ end
96
+ end
97
+
98
+ ### TEST UNIQUE CASES
99
+
100
+ ### HASH - this is allowed because its treated as keyword arguments
101
+ Post.sort_order("foobar", {}).limit(1).to_sql.include?("foobar ASC")
102
+
103
+ assert_raise do
104
+ Post.sort_order("foobar", {}, {}).limit(1)
105
+ end
106
+ end
107
+
108
+ def test_base_sort_order_errors
109
+ valid = [
110
+ nil,
111
+ false,
112
+ "",
113
+ "foobar",
114
+ ]
115
+
116
+ valid.each do |v|
117
+ Post.sort_order(base_sort_order: v).limit(1)
118
+ end
119
+
120
+ invalid = [
121
+ :foobar,
122
+ [],
123
+ {},
124
+ Object.new,
125
+ ]
126
+
127
+ invalid.each do |v|
128
+ assert_raise ArgumentError do
129
+ Post.sort_order(base_sort_order: v).limit(1)
130
+ end
131
+ end
132
+
133
+ ### INVALID BASE_SORT_ORDER CLASS
134
+ valid = [
135
+ nil,
136
+ false,
137
+ "",
138
+ "foobar",
139
+ ]
140
+
141
+ valid.each do |v|
142
+ silence_warnings do
143
+ PostWithVolatileBaseOrder.define_method :base_sort_order do
144
+ v
145
+ end
146
+ end
147
+
148
+ PostWithVolatileBaseOrder.sort_order(base_sort_order: v).limit(1)
149
+ end
150
+
151
+ invalid = [
152
+ :foobar,
153
+ [],
154
+ {},
155
+ Object.new,
156
+ ]
157
+
158
+ invalid.each do |v|
159
+ silence_warnings do
160
+ PostWithVolatileBaseOrder.define_method :base_sort_order do
161
+ v
162
+ end
163
+ end
164
+
165
+ assert_raise ArgumentError do
166
+ PostWithVolatileBaseOrder.sort_order(base_sort_order: v).limit(1)
167
+ end
168
+ end
169
+ end
170
+
171
+ end
metadata ADDED
@@ -0,0 +1,156 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: active_sort_order
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.9.0
5
+ platform: ruby
6
+ authors:
7
+ - Weston Ganger
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2021-01-29 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: activerecord
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ">="
18
+ - !ruby/object:Gem::Version
19
+ version: '0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ">="
25
+ - !ruby/object:Gem::Version
26
+ version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: railties
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
41
+ description: Dead simple, fully customizable sorting pattern for ActiveRecord.
42
+ email:
43
+ - weston@westonganger.com
44
+ executables: []
45
+ extensions: []
46
+ extra_rdoc_files: []
47
+ files:
48
+ - CHANGELOG.md
49
+ - LICENSE
50
+ - README.md
51
+ - Rakefile
52
+ - lib/active_sort_order.rb
53
+ - lib/active_sort_order/concerns/sort_order_concern.rb
54
+ - lib/active_sort_order/version.rb
55
+ - test/dummy_app/Rakefile
56
+ - test/dummy_app/app/assets/config/manifest.js
57
+ - test/dummy_app/app/assets/javascripts/application.js
58
+ - test/dummy_app/app/assets/stylesheets/application.css
59
+ - test/dummy_app/app/controllers/application_controller.rb
60
+ - test/dummy_app/app/models/application_record.rb
61
+ - test/dummy_app/app/models/post.rb
62
+ - test/dummy_app/app/models/post_with_base_order_a.rb
63
+ - test/dummy_app/app/models/post_with_base_order_a_and_b.rb
64
+ - test/dummy_app/app/models/post_with_base_order_b.rb
65
+ - test/dummy_app/app/models/post_with_base_order_b_and_a.rb
66
+ - test/dummy_app/app/models/post_with_volatile_base_order.rb
67
+ - test/dummy_app/app/models/test_helper.rb
68
+ - test/dummy_app/app/views/layouts/application.html.erb
69
+ - test/dummy_app/config.ru
70
+ - test/dummy_app/config/application.rb
71
+ - test/dummy_app/config/boot.rb
72
+ - test/dummy_app/config/database.yml
73
+ - test/dummy_app/config/environment.rb
74
+ - test/dummy_app/config/environments/development.rb
75
+ - test/dummy_app/config/environments/production.rb
76
+ - test/dummy_app/config/environments/test.rb
77
+ - test/dummy_app/config/initializers/backtrace_silencers.rb
78
+ - test/dummy_app/config/initializers/inflections.rb
79
+ - test/dummy_app/config/initializers/mime_types.rb
80
+ - test/dummy_app/config/initializers/secret_token.rb
81
+ - test/dummy_app/config/initializers/session_store.rb
82
+ - test/dummy_app/config/initializers/wrap_parameters.rb
83
+ - test/dummy_app/config/locales/en.yml
84
+ - test/dummy_app/config/routes.rb
85
+ - test/dummy_app/config/secrets.yml
86
+ - test/dummy_app/db/migrate/20210128155312_set_up_test_tables.rb
87
+ - test/dummy_app/db/schema.rb
88
+ - test/dummy_app/db/test.sqlite3
89
+ - test/dummy_app/log/test.log
90
+ - test/test_helper.rb
91
+ - test/unit/active_sort_order_test.rb
92
+ - test/unit/errors_test.rb
93
+ homepage: https://github.com/westonganger/active_sort_order
94
+ licenses:
95
+ - MIT
96
+ metadata:
97
+ source_code_uri: https://github.com/westonganger/active_sort_order
98
+ changelog_uri: https://github.com/westonganger/active_sort_order/blob/master/CHANGELOG.md
99
+ post_install_message:
100
+ rdoc_options: []
101
+ require_paths:
102
+ - lib
103
+ required_ruby_version: !ruby/object:Gem::Requirement
104
+ requirements:
105
+ - - ">="
106
+ - !ruby/object:Gem::Version
107
+ version: 2.3.0
108
+ required_rubygems_version: !ruby/object:Gem::Requirement
109
+ requirements:
110
+ - - ">="
111
+ - !ruby/object:Gem::Version
112
+ version: '0'
113
+ requirements: []
114
+ rubygems_version: 3.1.2
115
+ signing_key:
116
+ specification_version: 4
117
+ summary: Dead simple, fully customizable sorting pattern for ActiveRecord.
118
+ test_files:
119
+ - test/test_helper.rb
120
+ - test/unit/active_sort_order_test.rb
121
+ - test/unit/errors_test.rb
122
+ - test/dummy_app/app/models/test_helper.rb
123
+ - test/dummy_app/app/models/post_with_volatile_base_order.rb
124
+ - test/dummy_app/app/models/post_with_base_order_a_and_b.rb
125
+ - test/dummy_app/app/models/application_record.rb
126
+ - test/dummy_app/app/models/post_with_base_order_b_and_a.rb
127
+ - test/dummy_app/app/models/post_with_base_order_a.rb
128
+ - test/dummy_app/app/models/post_with_base_order_b.rb
129
+ - test/dummy_app/app/models/post.rb
130
+ - test/dummy_app/app/views/layouts/application.html.erb
131
+ - test/dummy_app/app/assets/stylesheets/application.css
132
+ - test/dummy_app/app/assets/config/manifest.js
133
+ - test/dummy_app/app/assets/javascripts/application.js
134
+ - test/dummy_app/app/controllers/application_controller.rb
135
+ - test/dummy_app/config.ru
136
+ - test/dummy_app/log/test.log
137
+ - test/dummy_app/config/database.yml
138
+ - test/dummy_app/config/environments/production.rb
139
+ - test/dummy_app/config/environments/test.rb
140
+ - test/dummy_app/config/environments/development.rb
141
+ - test/dummy_app/config/routes.rb
142
+ - test/dummy_app/config/environment.rb
143
+ - test/dummy_app/config/locales/en.yml
144
+ - test/dummy_app/config/boot.rb
145
+ - test/dummy_app/config/initializers/secret_token.rb
146
+ - test/dummy_app/config/initializers/inflections.rb
147
+ - test/dummy_app/config/initializers/mime_types.rb
148
+ - test/dummy_app/config/initializers/session_store.rb
149
+ - test/dummy_app/config/initializers/wrap_parameters.rb
150
+ - test/dummy_app/config/initializers/backtrace_silencers.rb
151
+ - test/dummy_app/config/secrets.yml
152
+ - test/dummy_app/config/application.rb
153
+ - test/dummy_app/Rakefile
154
+ - test/dummy_app/db/schema.rb
155
+ - test/dummy_app/db/test.sqlite3
156
+ - test/dummy_app/db/migrate/20210128155312_set_up_test_tables.rb