active_sort_order 0.9.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
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