ranked-model 0.4.1 → 0.4.11

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.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 0bc1cd219c463a32552a7f583dbb9f52c95a356b
4
- data.tar.gz: '0362078c1c550eb8da5e22fa2aa9c69864597f44'
2
+ SHA256:
3
+ metadata.gz: c219aee4691eca3a788bd590e056349623685e2dac26405247eccc807b3b580b
4
+ data.tar.gz: 7d50bd015aa1f38ead1a4a4c795d3fc3f5f7ad101e416f37c66415d50251e010
5
5
  SHA512:
6
- metadata.gz: e347568a8c34e9ce8ced2ba819fc8e9f3b297c4dadefff56c8eb0c43cafa12e872e508f4140ded18aea30b7aaed704979b7d2c42030c56f244ce930a150d1125
7
- data.tar.gz: 3ebd264cd22bea1038055c36cf460c3e352b3cc4383bfdb3112134808341ee8b9d180782f21b48341003f15b3dbe199d704dfa0fea3cc5bacb396caf377cf8b1
6
+ metadata.gz: 75a9f1e64091a37289aa2c3f6f35bd30be059237121e8f00af61196be089de2df645304854fb9a80bd1fc1de91d6014e741839b91714cc70ab9e7562e6367451
7
+ data.tar.gz: f8a6ac22945db1b7c609c776db78445f3dd60c550e7b421b4530c974af51fb4e0040375c676f72c7920240cff143b8ac236ec258f7c76f5cdbd418748e493243
@@ -0,0 +1,3 @@
1
+ # These are supported funding model platforms
2
+
3
+ github: [brendon]
@@ -0,0 +1,6 @@
1
+ version: 2
2
+ updates:
3
+ - package-ecosystem: "github-actions"
4
+ directory: "/"
5
+ schedule:
6
+ interval: "weekly"
@@ -0,0 +1,107 @@
1
+ ---
2
+ name: CI
3
+ on: [push, pull_request]
4
+
5
+ jobs:
6
+ tests:
7
+ name: Ruby ${{ matrix.ruby }}, ${{ matrix.gemfile }}, DB ${{ matrix.db }}
8
+ runs-on: ${{ matrix.os }}
9
+ strategy:
10
+ fail-fast: false
11
+ matrix:
12
+ ruby:
13
+ - 2.5
14
+ - 2.6
15
+ - 2.7
16
+ - '3.0'
17
+ - 3.1
18
+ - 3.2
19
+ - 3.3
20
+ gemfile:
21
+ - gemfiles/rails_5_2.gemfile
22
+ - gemfiles/rails_6_0.gemfile
23
+ - gemfiles/rails_6_1.gemfile
24
+ - gemfiles/rails_7_0.gemfile
25
+ db:
26
+ - sqlite
27
+ - mysql
28
+ - postgresql
29
+ exclude:
30
+ - ruby: 2.5
31
+ gemfile: gemfiles/rails_7_0.gemfile
32
+ - ruby: 2.6
33
+ gemfile: gemfiles/rails_7_0.gemfile
34
+ - ruby: '3.0'
35
+ gemfile: gemfiles/rails_5_2.gemfile
36
+ - ruby: 3.1
37
+ gemfile: gemfiles/rails_5_2.gemfile
38
+ - ruby: 3.2
39
+ gemfile: gemfiles/rails_4_2.gemfile
40
+ - ruby: 3.2
41
+ gemfile: gemfiles/rails_5_0.gemfile
42
+ - ruby: 3.2
43
+ gemfile: gemfiles/rails_5_1.gemfile
44
+ - ruby: 3.2
45
+ gemfile: gemfiles/rails_5_2.gemfile
46
+ - ruby: 3.2
47
+ gemfile: gemfiles/rails_6_0.gemfile
48
+ - ruby: 3.2
49
+ gemfile: gemfiles/rails_6_1.gemfile
50
+ - ruby: 3.3
51
+ gemfile: gemfiles/rails_4_2.gemfile
52
+ - ruby: 3.3
53
+ gemfile: gemfiles/rails_5_0.gemfile
54
+ - ruby: 3.3
55
+ gemfile: gemfiles/rails_5_1.gemfile
56
+ - ruby: 3.3
57
+ gemfile: gemfiles/rails_5_2.gemfile
58
+ - ruby: 3.3
59
+ gemfile: gemfiles/rails_6_0.gemfile
60
+ - ruby: 3.3
61
+ gemfile: gemfiles/rails_6_1.gemfile
62
+ os:
63
+ - ubuntu-latest
64
+ services:
65
+ mysql:
66
+ image: mysql:5.7
67
+ env:
68
+ MYSQL_ALLOW_EMPTY_PASSWORD: yes
69
+ ports:
70
+ - 3306:3306
71
+ options: --health-cmd="mysqladmin ping" --health-interval=10s --health-timeout=5s --health-retries=3
72
+
73
+ postgres:
74
+ # Docker Hub image
75
+ image: postgres
76
+ # Provide the password for postgres
77
+ env:
78
+ POSTGRES_USER: postgres
79
+ POSTGRES_HOST_AUTH_METHOD: trust
80
+ ports:
81
+ - 5432:5432
82
+ # Set health checks to wait until postgres has started
83
+ options: >-
84
+ --health-cmd pg_isready
85
+ --health-interval 10s
86
+ --health-timeout 5s
87
+ --health-retries 5
88
+ env:
89
+ BUNDLE_GEMFILE: ${{ matrix.gemfile }}
90
+ DB: ${{ matrix.db }}
91
+ steps:
92
+ - uses: actions/checkout@v4
93
+ - name: Set up Ruby
94
+ uses: ruby/setup-ruby@v1
95
+ with:
96
+ ruby-version: ${{ matrix.ruby }}
97
+ bundler-cache: true
98
+ - name: "Create MySQL database"
99
+ if: ${{ env.DB == 'mysql' }}
100
+ run: |
101
+ mysql -h 127.0.0.1 -u root -e 'create database ranked_model_test;'
102
+ - name: "Create PostgreSQL database"
103
+ if: ${{ env.DB == 'postgresql' }}
104
+ run: |
105
+ psql -c 'create database ranked_model_test;' -h localhost -U postgres
106
+ - name: Run tests
107
+ run: bundle exec rake
data/.gitignore CHANGED
@@ -2,6 +2,8 @@ pkg/*
2
2
  *.gem
3
3
  .bundle
4
4
  *.un~
5
+ *.swp
5
6
 
6
7
  Gemfile.lock
7
8
  *.gemfile.lock
9
+ .ruby-version
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --color
2
+ --warnings
2
3
  --format documentation
data/.travis.yml CHANGED
@@ -1,38 +1,56 @@
1
- sudo: false # use newer travis infrastructure
2
1
  language: ruby
3
2
  cache: bundler
4
3
  before_install:
5
- - gem install bundler -v 1.16.1
4
+ - gem update --system
5
+ - gem install bundler
6
6
  before_script:
7
7
  - mysql -e 'create database ranked_model_test;'
8
8
  - psql -c 'create database ranked_model_test;' -U postgres
9
9
  rvm:
10
- - 1.9.3
11
- - 2.1.10
12
- - 2.2.10
13
- - 2.3.7
14
- - 2.4.4
15
- - 2.5.1
10
+ - 2.4
11
+ - 2.5
12
+ - 2.6
13
+ - 2.7
14
+ - 3.0
16
15
  - jruby-9.1.17.0
17
- - rbx-3.100
18
16
  env:
19
17
  - DB=sqlite
20
18
  - DB=mysql
21
19
  - DB=postgresql
20
+ services:
21
+ - mysql
22
+ - postgresql
22
23
  gemfile:
23
- - gemfiles/rails_3_2.gemfile
24
- - gemfiles/rails_4_1.gemfile
25
24
  - gemfiles/rails_4_2.gemfile
25
+ - gemfiles/rails_5_0.gemfile
26
+ - gemfiles/rails_5_1.gemfile
27
+ - gemfiles/rails_5_2.gemfile
28
+ - gemfiles/rails_6_0.gemfile
29
+ - gemfiles/rails_6_1.gemfile
26
30
  matrix:
27
31
  exclude:
28
- - rvm: 2.4.4
29
- gemfile: gemfiles/rails_3_2.gemfile
30
- - rvm: 2.4.4
31
- gemfile: gemfiles/rails_4_1.gemfile
32
- - rvm: 2.5.1
33
- gemfile: gemfiles/rails_3_2.gemfile
34
- - rvm: 2.5.1
35
- gemfile: gemfiles/rails_4_1.gemfile
36
- - env: DB=postgresql
37
- gemfile: gemfiles/rails_3_2.gemfile
38
-
32
+ # Rails <6 does not support Ruby 3, see:
33
+ # https://github.com/rails/rails/issues/40938#issuecomment-751898275
34
+ - rvm: 3.0
35
+ gemfile: gemfiles/rails_4_2.gemfile
36
+ - rvm: 3.0
37
+ gemfile: gemfiles/rails_5_0.gemfile
38
+ - rvm: 3.0
39
+ gemfile: gemfiles/rails_5_1.gemfile
40
+ - rvm: 3.0
41
+ gemfile: gemfiles/rails_5_2.gemfile
42
+ # Ruby ≥2.7 uses a `bigdecimal` version that doesn't support BigDecimal.new
43
+ # that Rails 4.2 uses. See also:
44
+ # https://github.com/ruby/bigdecimal#which-version-should-you-select
45
+ - rvm: 2.7
46
+ gemfile: gemfiles/rails_4_2.gemfile
47
+ - rvm: jruby-9.1.17.0
48
+ gemfile: gemfiles/rails_5_2.gemfile
49
+ - rvm: 2.4
50
+ gemfile: gemfiles/rails_6_0.gemfile
51
+ - rvm: jruby-9.1.17.0
52
+ gemfile: gemfiles/rails_6_0.gemfile
53
+ - rvm: 2.4
54
+ gemfile: gemfiles/rails_6_1.gemfile
55
+ - rvm: jruby-9.1.17.0
56
+ gemfile: gemfiles/rails_6_1.gemfile
data/Appraisals CHANGED
@@ -1,71 +1,55 @@
1
- appraise "rails-3-2" do
1
+ appraise "rails-5-2" do
2
2
  group :sqlite do
3
- gem "sqlite3", platform: :ruby
4
- gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.24", platform: :jruby
3
+ gem "activerecord-jdbcsqlite3-adapter", "~> 52.0", platform: :jruby
5
4
  end
6
5
  group :mysql do
7
- gem "mysql2", "~> 0.3.21", platform: :ruby
8
- gem "activerecord-jdbcmysql-adapter", "~> 1.3.24", platform: :jruby
6
+ gem "activerecord-jdbcmysql-adapter", "~> 52.0", platform: :jruby
9
7
  end
10
8
  group :postgresql do
11
- gem "pg", "~> 0.18.0", platform: :ruby
12
- gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.24", platform: :jruby
9
+ gem "activerecord-jdbcpostgresql-adapter", "~> 52.0", platform: :jruby
13
10
  end
14
11
 
15
- gem "activerecord", "~> 3.2.22.2"
12
+ gem "activerecord", "~> 5.2.0"
16
13
  end
17
14
 
18
- appraise "rails-4-1" do
15
+ appraise "rails-6-0" do
19
16
  group :sqlite do
20
- gem "sqlite3", platform: :ruby
21
- gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.24", platform: :jruby
17
+ gem "sqlite3", "~> 1.4", platform: :ruby
18
+ gem "activerecord-jdbcsqlite3-adapter", "~> 60.0", platform: :jruby
22
19
  end
23
20
  group :mysql do
24
- gem "mysql2", "~> 0.3.21", platform: :ruby
25
- gem "activerecord-jdbcmysql-adapter", "~> 1.3.24", platform: :jruby
21
+ gem "activerecord-jdbcmysql-adapter", "~> 60.0", platform: :jruby
26
22
  end
27
23
  group :postgresql do
28
- gem "pg", "~> 0.18.0", platform: :ruby
29
- gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.24", platform: :jruby
24
+ gem "activerecord-jdbcpostgresql-adapter", "~> 60.0", platform: :jruby
30
25
  end
31
-
32
- gem "activerecord", "~> 4.1.16"
26
+ gem "activerecord", "~> 6.0.0"
33
27
  end
34
28
 
35
- appraise "rails-4-2" do
29
+ appraise "rails-6-1" do
36
30
  group :sqlite do
37
- gem "sqlite3", platform: :ruby
38
- gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.24", platform: :jruby
31
+ gem "sqlite3", "~> 1.4", platform: :ruby
32
+ gem "activerecord-jdbcsqlite3-adapter", "~> 61.0", platform: :jruby
39
33
  end
40
34
  group :mysql do
41
- gem "mysql2", "~> 0.4.10", platform: :ruby
42
- gem "activerecord-jdbcmysql-adapter", "~> 1.3.24", platform: :jruby
35
+ gem "activerecord-jdbcmysql-adapter", "~> 61.0", platform: :jruby
43
36
  end
44
37
  group :postgresql do
45
- gem "pg", "~> 0.18.0", platform: :ruby
46
- gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.24", platform: :jruby
38
+ gem "activerecord-jdbcpostgresql-adapter", "~> 61.0", platform: :jruby
47
39
  end
48
-
49
- gem "activerecord", "~> 4.2.10"
40
+ gem "activerecord", "~> 6.1.0"
50
41
  end
51
42
 
52
- # appraise "rails-5-0" do
53
- # group :mysql do
54
- # gem "mysql2", "~> 0.4.10", platform: :ruby
55
- # end
56
- # gem "activerecord", "~> 5.0.6"
57
- # end
58
-
59
- # appraise "rails-5-1" do
60
- # group :mysql do
61
- # gem "mysql2", "~> 0.4.10", platform: :ruby
62
- # end
63
- # gem "activerecord", "~> 5.1.4"
64
- # end
65
-
66
- # appraise "rails-5-2" do
67
- # group :mysql do
68
- # gem "mysql2", "~> 0.4.10", platform: :ruby
69
- # end
70
- # gem "activerecord", "~> 5.2.0.rc1"
71
- # end
43
+ appraise "rails-7-0" do
44
+ group :sqlite do
45
+ gem "sqlite3", "~> 1.4", platform: :ruby
46
+ gem "activerecord-jdbcsqlite3-adapter", "~> 61.0", platform: :jruby
47
+ end
48
+ group :mysql do
49
+ gem "activerecord-jdbcmysql-adapter", "~> 61.0", platform: :jruby
50
+ end
51
+ group :postgresql do
52
+ gem "activerecord-jdbcpostgresql-adapter", "~> 61.0", platform: :jruby
53
+ end
54
+ gem "activerecord", "~> 7.0.0"
55
+ end
data/CHANGELOG.md ADDED
@@ -0,0 +1,9 @@
1
+ ## [Unreleased]
2
+
3
+ ## [0.4.11] - 2024-10-20
4
+
5
+ - Add `funding_uri` to gemspec.
6
+
7
+ ## [0.4.10] - 2024-08-09
8
+
9
+ - Publish ActiveSupport notifications on rebalancing. Thanks @tjvc!
data/Gemfile CHANGED
@@ -3,5 +3,14 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in ranked-model.gemspec
4
4
  gemspec
5
5
 
6
- gem 'rubysl', '~> 2.0', platform: :rbx
7
- gem 'rubinius-developer_tools', platform: :rbx
6
+ group :sqlite do
7
+ gem "sqlite3", platform: :ruby
8
+ end
9
+
10
+ group :postgresql do
11
+ gem "pg", platform: :ruby
12
+ end
13
+
14
+ group :mysql do
15
+ gem "mysql2", platform: :ruby
16
+ end
data/Readme.mkd CHANGED
@@ -1,13 +1,18 @@
1
- **ranked-model** is a modern row sorting library built for Rails 3 & 4. It uses ARel aggressively and is better optimized than most other libraries.
1
+ **ranked-model** is a modern row sorting library built for Rails 4.2+. It uses ARel aggressively and is better optimized than most other libraries.
2
2
 
3
- [![Build Status](https://travis-ci.org/mixonic/ranked-model.png)](https://travis-ci.org/mixonic/ranked-model)
3
+ [![Build Status](https://github.com/brendon/ranked-model/actions/workflows/ci.yml/badge.svg)](https://github.com/brendon/ranked-model/actions/workflows/ci.yml)
4
+
5
+ ANNOUNCING: Positioning, the gem
6
+ --------------------------------
7
+
8
+ As maintainer of both Acts As List and the Ranked Model gems, I've become intimately aquainted with the strengths and weaknesses of each. I ended up writing a small scale Rails Concern for positioning database rows for a recent project and it worked really well so I've decided to release it as a gem: [Positioning](https://github.com/brendon/positioning)
9
+
10
+ Positioning works similarly to Acts As List in that it maintains a sequential list of integer values as positions. It differs in that it encourages a unique constraints on the position column and supports multiple lists per database table. It borrows Ranked Model's concept of relative positioning. I encourage you to check it out and give it a whirl on your project!
4
11
 
5
12
  Installation
6
13
  ------------
7
14
 
8
- ranked-model passes specs with Rails 3.1, 3.2, 4.0, and 4.1-beta for MySQL, Postgres, and SQLite on Ruby 1.9.2, 1.9.3, 2.0, 2.1, jruby-19mode, and rubinius where Rails supports the platform. This is with the exception of Postgres before Rails 4.0 on all platforms, which is unsupported (I'd gladly accept a PR to fix this).
9
-
10
- TL;DR, if you are using Rails 4 and up you are 100% good to go. Before Rails 4, be wary of Postgres.
15
+ ranked-model passes specs with Rails 4.2, 5.0, 5.1, 5.2, 6.0 and 6.1 for MySQL, Postgres, and SQLite on Ruby 2.4 through 3.0 (with exceptions, please check the CI setup for supported combinations), and jruby-9.1.17.0 where Rails supports the platform.
11
16
 
12
17
  To install ranked-model, just add it to your `Gemfile`:
13
18
 
@@ -16,7 +21,7 @@ gem 'ranked-model'
16
21
 
17
22
  # Or pin ranked-model to git
18
23
  # gem 'ranked-model',
19
- # :git => 'git@github.com:mixonic/ranked-model.git'
24
+ # git: 'git@github.com:mixonic/ranked-model.git'
20
25
  ```
21
26
 
22
27
  Then use `bundle install` to update your `Gemfile.lock`.
@@ -31,6 +36,18 @@ class Duck < ActiveRecord::Base
31
36
  end
32
37
  ```
33
38
 
39
+ Give them an order (integer column):
40
+
41
+ ```bash
42
+ rails g migration AddRowOrderToDucks row_order:integer
43
+ rails db:migrate
44
+ ```
45
+
46
+ **IMPORTANT: The `_order` table column MUST allow null values. For the reason behind this requirement see [issue#167](https://github.com/mixonic/ranked-model/issues/167)**
47
+
48
+
49
+
50
+
34
51
  Put your ducks in a row:
35
52
 
36
53
  ``` ruby
@@ -42,7 +59,7 @@ class Duck < ActiveRecord::Base
42
59
  end
43
60
  ```
44
61
 
45
- This simple example assumes an integer column called `row_order`. To order Ducks by this order:
62
+ Order the Ducks by this order:
46
63
 
47
64
  ``` ruby
48
65
  Duck.rank(:row_order).all
@@ -52,9 +69,11 @@ The ranking integers stored in the `row_order` column will be big and spaced apa
52
69
  implement a sorting UI, just update the resource by appending the column name with `_position` and indicating the desired position:
53
70
 
54
71
  ``` ruby
55
- @duck.update_attribute :row_order_position, 0 # or 1, 2, 37. :first, :last, :up and :down are also valid
72
+ @duck.update row_order_position: 0 # or 1, 2, 37. :first, :last, :up and :down are also valid
56
73
  ```
57
74
 
75
+ **IMPORTANT: Note that you MUST append _position to the column name when setting a new position on an instance. This is a fake column that can take relative as well as absolute index-based values for position.**
76
+
58
77
  Position numbers begin at zero. A position number greater than the number of records acts the
59
78
  same as :last. :up and :down move the record up/down the ladder by one step.
60
79
 
@@ -70,6 +89,15 @@ $.ajax({
70
89
  });
71
90
  ```
72
91
 
92
+ If you need to find the rank of an item with respect to other ranked items, you can use the `{column_name}_rank` method on the model instance. `{column_name}` is your resource ranking column.
93
+
94
+ Following on from our examples above, the `row_order_rank` method will return the position of the duck object in the list with respect to the order defined by the row_order column.
95
+
96
+ ``` ruby
97
+ Duck.rank(:row_order).first.row_order_rank # => 0
98
+ Duck.rank(:row_order).third.row_order_rank # => 2
99
+ ```
100
+
73
101
  Complex Use
74
102
  -----------
75
103
 
@@ -80,17 +108,28 @@ class Duck < ActiveRecord::Base
80
108
 
81
109
  include RankedModel
82
110
 
83
- ranks :row_order, # Name this ranker, used with rank()
84
- :column => :sort_order # Override the default column, which defaults to the name
85
-
111
+ ranks :row_order, # Name this ranker, used with rank()
112
+ column: :sort_order # Override the default column, which defaults to the name
113
+
86
114
  belongs_to :pond
87
115
  ranks :swimming_order,
88
- :with_same => :pond_id # Ducks belong_to Ponds, make the ranker scoped to one pond
89
-
90
- scope :walking, where(:walking => true )
116
+ with_same: :pond_id # Ducks belong_to Ponds, make the ranker scoped to one pond
117
+
118
+ ranks :row_order,
119
+ with_same: [:pond_id, :breed] # Lets rank them by breed
120
+
121
+ scope :walking, where(walking: true )
91
122
  ranks :walking_order,
92
- :scope => :walking # Narrow this ranker to a scope
123
+ scope: :walking # Narrow this ranker to a scope
93
124
 
125
+ belongs_to :parent, class_name: 'Duck', optional: true
126
+ ranks :child_order,
127
+ unless: :has_no_parent?, # Rank only ducks that have a parent. Alternatively a Proc or lambda can be passed, e.g. proc { parent.nil? }
128
+ with_same: :parent_id
129
+
130
+ def has_no_parent?
131
+ parent.nil?
132
+ end
94
133
  end
95
134
  ```
96
135
 
@@ -104,6 +143,37 @@ Pond.first.ducks.rank(:swimming_order)
104
143
  Duck.walking.rank(:walking)
105
144
  ```
106
145
 
146
+ Drawbacks
147
+ ---------
148
+
149
+ While ranked-model is performant when storing data, it might cause N+1s depending on how you write your code. Consider this snippet:
150
+
151
+ ```ruby
152
+ ducks = Duck.all
153
+ ducks.map do |duck|
154
+ {
155
+ id: duck.id,
156
+ position: duck.row_order_rank # This causes N+1!
157
+ }
158
+ end
159
+ ```
160
+
161
+ Every call to `duck.row_order_rank` will make a call to the DB to check the rank of that
162
+ particular element. If you have a long list of elements this might cause issues to your DB.
163
+
164
+ In order to avoid that, you can use the `rank(:your_rank)` scope and some Ruby code to get
165
+ the element's position:
166
+
167
+ ```ruby
168
+ ducks = Duck.rank(:row_order).all
169
+ ducks.map.with_index do |duck, index|
170
+ {
171
+ id: duck.id,
172
+ position: index
173
+ }
174
+ end
175
+ ```
176
+
107
177
  Single Table Inheritance (STI)
108
178
  ------------------------------
109
179
 
@@ -158,6 +228,35 @@ truck.row_order
158
228
  => 4194304
159
229
  ```
160
230
 
231
+ Migrations for existing data
232
+ ----------------------------
233
+
234
+ If you use `ranked_model` with existing data, the following migration (for Rails
235
+ 6) can be a starting point. Make sure to declare `include RankedModel` and
236
+ `ranks :row_order` in your `Duck` before running the migration.
237
+
238
+ ```bash
239
+ rails g migration AddRowOrderToDucks row_order:integer
240
+ ```
241
+
242
+ Then, adjust the migration:
243
+ ```ruby
244
+ # e.g. file db/migrate/20200325095038_add_row_order_to_ducks.rb
245
+ class AddRowOrderToDucks < ActiveRecord::Migration[6.0]
246
+ def change
247
+ add_column :ducks, :row_order, :integer
248
+
249
+ # Newest Duck shall rank "highest"" (be last).
250
+ Duck.update_all('row_order = EXTRACT(EPOCH FROM created_at)')
251
+
252
+ # Alternatively, implement any other sorting default
253
+ # Duck.order(created_at: :desc).each do |duck|
254
+ # duck.update!(row_order: duck.created_at.to_i + duck.age / 2)
255
+ # end
256
+ end
257
+ end
258
+ ```
259
+
161
260
  Internals
162
261
  ---------
163
262
 
@@ -170,18 +269,37 @@ this occurs, ranked-model will try to shift other records out of the way. If ite
170
269
  shifted anymore, it will rebalance the distribution of rank numbers across all members
171
270
  of the ranked group.
172
271
 
272
+ Record updates to rebalance ranks do not trigger ActiveRecord callbacks. If you need to react to these updates
273
+ (to index them in a secondary data store, for example), you can subscribe to the `ranked_model.ranks_updated`
274
+ [ActiveSupport notification](https://api.rubyonrails.org/v7.1/classes/ActiveSupport/Notifications.html).
275
+ Subscribed consumers receive an event for each rearrangement or rebalancing, the payload of which includes the
276
+ triggering instance and the `scope` and `with_same` options for the ranking, which can be used to retrieve the
277
+ affected records.
278
+
279
+ ```ruby
280
+ ActiveSupport::Notifications.subscribe("ranked_model.ranks_updated") do |_name, _start, _finish, _id, payload|
281
+ # payload[:instance] - the instance whose update triggered the rebalance
282
+ # payload[:scope] - the scope applied to the ranking
283
+ # payload[:with_same] - the with_same option applied to the ranking
284
+ end
285
+ ```
286
+
173
287
  Contributing
174
288
  ------------
175
289
 
176
290
  Fork, clone, write a test, write some code, commit, push, send a pull request. Github FTW!
177
291
 
292
+ The code is published under the [MIT License](LICENSE).
293
+
178
294
  The specs can be run with sqlite, postgres, and mysql:
179
295
 
180
296
  ```
181
- DB=postgresql bundle exec rake
297
+ bundle
298
+ appraisal install
299
+ DB=postgresql bundle exec appraisal rake
182
300
  ```
183
301
 
184
- Is no DB is specified, the tests run against sqlite.
302
+ If no DB is specified (`sqlite`, `mysql`, or `postgresql`), the tests run against sqlite.
185
303
 
186
304
  RankedModel is mostly the handiwork of Matthew Beale:
187
305
 
@@ -203,3 +321,4 @@ A hearty thanks to these contributors:
203
321
  * [jguyon](https://github.com/jguyon)
204
322
  * [pehrlich](https://github.com/pehrlich)
205
323
  * [petergoldstein](https://github.com/petergoldstein)
324
+ * [brendon](https://github.com/brendon)
@@ -0,0 +1,22 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 5.2.0"
6
+
7
+ group :sqlite do
8
+ gem "sqlite3", platform: :ruby
9
+ gem "activerecord-jdbcsqlite3-adapter", "~> 52.0", platform: :jruby
10
+ end
11
+
12
+ group :postgresql do
13
+ gem "pg", platform: :ruby
14
+ gem "activerecord-jdbcpostgresql-adapter", "~> 52.0", platform: :jruby
15
+ end
16
+
17
+ group :mysql do
18
+ gem "mysql2", platform: :ruby
19
+ gem "activerecord-jdbcmysql-adapter", "~> 52.0", platform: :jruby
20
+ end
21
+
22
+ gemspec path: "../"
@@ -0,0 +1,22 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 6.0.0"
6
+
7
+ group :sqlite do
8
+ gem "sqlite3", "~> 1.4", platform: :ruby
9
+ gem "activerecord-jdbcsqlite3-adapter", "~> 60.0", platform: :jruby
10
+ end
11
+
12
+ group :postgresql do
13
+ gem "pg", platform: :ruby
14
+ gem "activerecord-jdbcpostgresql-adapter", "~> 60.0", platform: :jruby
15
+ end
16
+
17
+ group :mysql do
18
+ gem "mysql2", platform: :ruby
19
+ gem "activerecord-jdbcmysql-adapter", "~> 60.0", platform: :jruby
20
+ end
21
+
22
+ gemspec path: "../"
@@ -0,0 +1,22 @@
1
+ # This file was generated by Appraisal
2
+
3
+ source "https://rubygems.org"
4
+
5
+ gem "activerecord", "~> 6.1.0"
6
+
7
+ group :sqlite do
8
+ gem "sqlite3", "~> 1.4", platform: :ruby
9
+ gem "activerecord-jdbcsqlite3-adapter", "~> 61.0", platform: :jruby
10
+ end
11
+
12
+ group :postgresql do
13
+ gem "pg", platform: :ruby
14
+ gem "activerecord-jdbcpostgresql-adapter", "~> 61.0", platform: :jruby
15
+ end
16
+
17
+ group :mysql do
18
+ gem "mysql2", platform: :ruby
19
+ gem "activerecord-jdbcmysql-adapter", "~> 61.0", platform: :jruby
20
+ end
21
+
22
+ gemspec path: "../"