ranked-model 0.4.0 → 0.4.7

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 116f5fc0aeafe231cddba562c5135e868ba06604
4
- data.tar.gz: c720ee45d4532e3c96fb2d829788a2c43cdd7f8f
2
+ SHA256:
3
+ metadata.gz: 8dac9a4acefc5a44cfe74e77931854bb8edd031cc986f3bc0bd8232f543dc0f9
4
+ data.tar.gz: 9bd6120114a23ef47ae08581b860cd0cb4fa18779fb237b9b9570d94a889cc75
5
5
  SHA512:
6
- metadata.gz: 00ca1355412ab2cc161edc2831bc685862f4996b33903a7bf5a65077e2a638e2f385d665db6e20bdfe50f59d93c8517cdf68c8e694a325680c4a2314e4adb677
7
- data.tar.gz: 72dbeebd7402e29238fb7219c0037f04ba588dba79e06ecbabf6ee9962cee67131b0b96246945639271b7585c63ebf6edb09274c7ba779ca864a336ba576af72
6
+ metadata.gz: dc8d0ad9348de7596934a2eab69da78228c3351bd4d16303eae592b3893ecfedc28ff4620997977e8a88dc9d26dc27999c99e6e2abddc7ab6fe1f24aeb108527
7
+ data.tar.gz: 03a77db0fc8e9f59b4ffaccf24c966a54125141ab07a931046387e30cf62b7bf0577d9d983d268322dc69a7004c68c001168083d428cffff118832085afe3d21
data/.gitignore CHANGED
@@ -4,3 +4,5 @@ pkg/*
4
4
  *.un~
5
5
 
6
6
  Gemfile.lock
7
+ *.gemfile.lock
8
+ .ruby-version
data/.rspec CHANGED
@@ -1,2 +1,3 @@
1
1
  --color
2
+ --warnings
2
3
  --format documentation
data/.travis.yml CHANGED
@@ -1,82 +1,51 @@
1
1
  language: ruby
2
+ cache: bundler
3
+ before_install:
4
+ - gem update --system
5
+ - gem install bundler
2
6
  before_script:
3
7
  - mysql -e 'create database ranked_model_test;'
4
8
  - psql -c 'create database ranked_model_test;' -U postgres
5
9
  rvm:
6
- - "1.9.2"
7
- - "1.9.3"
8
- - "2.0.0"
9
- - "2.1.0"
10
- - "jruby-19mode"
11
- - "rbx"
10
+ - 2.4
11
+ - 2.5
12
+ - 2.6
13
+ - 2.7
14
+ - 3.0
15
+ - jruby-9.1.17.0
12
16
  env:
13
- - "ACTIVERECORD_VERSION=4.1.0.beta1"
14
- - "ACTIVERECORD_VERSION=4.1.0.beta1 DB=mysql_travis"
15
- - "ACTIVERECORD_VERSION=4.1.0.beta1 DB=postgresql_travis"
16
- - "ACTIVERECORD_VERSION=4.0.2"
17
- - "ACTIVERECORD_VERSION=4.0.2 DB=mysql_travis"
18
- - "ACTIVERECORD_VERSION=4.0.2 DB=postgresql_travis"
19
- - "ACTIVERECORD_VERSION=3.2.16"
20
- - "ACTIVERECORD_VERSION=3.2.16 DB=mysql_travis"
21
- - "ACTIVERECORD_VERSION=3.2.16 DB=postgresql_travis"
22
- - "ACTIVERECORD_VERSION=3.1.12"
23
- - "ACTIVERECORD_VERSION=3.1.12 DB=mysql_travis"
24
- - "ACTIVERECORD_VERSION=3.1.12 DB=postgresql_travis"
25
- - "ACTIVERECORD_VERSION=master"
26
- - "ACTIVERECORD_VERSION=master DB=mysql_travis"
27
- - "ACTIVERECORD_VERSION=master DB=postgresql_travis"
17
+ - DB=sqlite
18
+ - DB=mysql
19
+ - DB=postgresql
20
+ services:
21
+ - mysql
22
+ - postgresql
23
+ gemfile:
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
28
29
  matrix:
29
30
  exclude:
30
- - env: "ACTIVERECORD_VERSION=4.1.0.beta1"
31
- rvm: "1.9.2"
32
- - env: "ACTIVERECORD_VERSION=4.1.0.beta1 DB=mysql_travis"
33
- rvm: "1.9.2"
34
- - env: "ACTIVERECORD_VERSION=4.1.0.beta1 DB=postgresql_travis"
35
- rvm: "1.9.2"
36
- - env: "ACTIVERECORD_VERSION=4.1.0.beta1"
37
- rvm: "1.9.3"
38
- - env: "ACTIVERECORD_VERSION=4.1.0.beta1 DB=mysql_travis"
39
- rvm: "1.9.3"
40
- - env: "ACTIVERECORD_VERSION=4.1.0.beta1 DB=postgresql_travis"
41
- rvm: "1.9.3"
42
- - env: "ACTIVERECORD_VERSION=4.1.0.beta1"
43
- rvm: "jruby-19mode"
44
- - env: "ACTIVERECORD_VERSION=4.1.0.beta1 DB=mysql_travis"
45
- rvm: "jruby-19mode"
46
- - env: "ACTIVERECORD_VERSION=4.1.0.beta1 DB=postgresql_travis"
47
- rvm: "jruby-19mode"
48
- - env: "ACTIVERECORD_VERSION=master"
49
- rvm: "jruby-19mode"
50
- - env: "ACTIVERECORD_VERSION=master DB=mysql_travis"
51
- rvm: "jruby-19mode"
52
- - env: "ACTIVERECORD_VERSION=master DB=postgresql_travis"
53
- rvm: "jruby-19mode"
54
- - env: "ACTIVERECORD_VERSION=4.0.2"
55
- rvm: "1.9.2"
56
- - env: "ACTIVERECORD_VERSION=4.0.2 DB=mysql_travis"
57
- rvm: "1.9.2"
58
- - env: "ACTIVERECORD_VERSION=4.0.2 DB=postgresql_travis"
59
- rvm: "1.9.2"
60
- - env: "ACTIVERECORD_VERSION=master"
61
- rvm: "1.9.2"
62
- - env: "ACTIVERECORD_VERSION=master DB=mysql_travis"
63
- rvm: "1.9.2"
64
- - env: "ACTIVERECORD_VERSION=master DB=postgresql_travis"
65
- rvm: "1.9.2"
66
- - env: "ACTIVERECORD_VERSION=master"
67
- rvm: "1.9.3"
68
- - env: "ACTIVERECORD_VERSION=master DB=mysql_travis"
69
- rvm: "1.9.3"
70
- - env: "ACTIVERECORD_VERSION=master DB=postgresql_travis"
71
- rvm: "1.9.3"
72
- allow_failures:
73
- # Master may or may not pass
74
- - env: "ACTIVERECORD_VERSION=master"
75
- - env: "ACTIVERECORD_VERSION=master DB=mysql_travis"
76
- - env: "ACTIVERECORD_VERSION=master DB=postgresql_travis"
77
- # Rails 3.1 is incompatible with database cleaner 1.2
78
- - env: "ACTIVERECORD_VERSION=3.1.12 DB=mysql_travis"
79
- - env: "ACTIVERECORD_VERSION=3.1.12 DB=postgresql_travis"
80
- # Postgres is not supported before Rails 4.0.
81
- - env: "ACTIVERECORD_VERSION=3.1.12 DB=postgresql_travis"
82
- - env: "ACTIVERECORD_VERSION=3.2.16 DB=postgresql_travis"
31
+ # Rails <6 does not support Ruby 3, see:
32
+ # https://github.com/rails/rails/issues/40938#issuecomment-751898275
33
+ - rvm: 3.0
34
+ gemfile: gemfiles/rails_4_2.gemfile
35
+ - rvm: 3.0
36
+ gemfile: gemfiles/rails_5_0.gemfile
37
+ - rvm: 3.0
38
+ gemfile: gemfiles/rails_5_1.gemfile
39
+ - rvm: 3.0
40
+ gemfile: gemfiles/rails_5_2.gemfile
41
+ # Ruby ≥2.7 uses a `bigdecimal` version that doesn't support BigDecimal.new
42
+ # that Rails 4.2 uses. See also:
43
+ # https://github.com/ruby/bigdecimal#which-version-should-you-select
44
+ - rvm: 2.7
45
+ gemfile: gemfiles/rails_4_2.gemfile
46
+ - rvm: jruby-9.1.17.0
47
+ gemfile: gemfiles/rails_5_2.gemfile
48
+ - rvm: 2.4
49
+ gemfile: gemfiles/rails_6_0.gemfile
50
+ - rvm: jruby-9.1.17.0
51
+ gemfile: gemfiles/rails_6_0.gemfile
data/Appraisals ADDED
@@ -0,0 +1,72 @@
1
+ appraise "rails-4-2" do
2
+ group :sqlite do
3
+ gem "activerecord-jdbcsqlite3-adapter", "~> 1.3.24", platform: :jruby
4
+ end
5
+ group :mysql do
6
+ gem "mysql2", "~> 0.4.0", platform: :ruby
7
+ gem "jdbc-mysql", "~> 5.1.47", platform: :jruby
8
+ gem "activerecord-jdbcmysql-adapter", "~> 1.3.24", platform: :jruby
9
+ end
10
+ group :postgresql do
11
+ gem "pg", "~> 0.18.4", platform: :ruby
12
+ gem "activerecord-jdbcpostgresql-adapter", "~> 1.3.24", platform: :jruby
13
+ end
14
+
15
+ gem "activerecord", "~> 4.2.0"
16
+ end
17
+
18
+ appraise "rails-5-0" do
19
+ group :sqlite do
20
+ gem "activerecord-jdbcsqlite3-adapter", "~> 50.0", platform: :jruby
21
+ end
22
+ group :mysql do
23
+ gem "activerecord-jdbcmysql-adapter", "~> 50.0", platform: :jruby
24
+ end
25
+ group :postgresql do
26
+ gem "activerecord-jdbcpostgresql-adapter", "~> 50.0", platform: :jruby
27
+ end
28
+
29
+ gem "activerecord", "~> 5.0.0"
30
+ end
31
+
32
+ appraise "rails-5-1" do
33
+ group :sqlite do
34
+ gem "activerecord-jdbcsqlite3-adapter", "~> 51.0", platform: :jruby
35
+ end
36
+ group :mysql do
37
+ gem "activerecord-jdbcmysql-adapter", "~> 51.0", platform: :jruby
38
+ end
39
+ group :postgresql do
40
+ gem "activerecord-jdbcpostgresql-adapter", "~> 51.0", platform: :jruby
41
+ end
42
+
43
+ gem "activerecord", "~> 5.1.0"
44
+ end
45
+
46
+ appraise "rails-5-2" do
47
+ group :sqlite do
48
+ gem "activerecord-jdbcsqlite3-adapter", "~> 52.0", platform: :jruby
49
+ end
50
+ group :mysql do
51
+ gem "activerecord-jdbcmysql-adapter", "~> 52.0", platform: :jruby
52
+ end
53
+ group :postgresql do
54
+ gem "activerecord-jdbcpostgresql-adapter", "~> 52.0", platform: :jruby
55
+ end
56
+
57
+ gem "activerecord", "~> 5.2.0"
58
+ end
59
+
60
+ appraise "rails-6-0" do
61
+ group :sqlite do
62
+ gem "sqlite3", "~> 1.4", platform: :ruby
63
+ gem "activerecord-jdbcsqlite3-adapter", "~> 60.0", platform: :jruby
64
+ end
65
+ group :mysql do
66
+ gem "activerecord-jdbcmysql-adapter", "~> 60.0", platform: :jruby
67
+ end
68
+ group :postgresql do
69
+ gem "activerecord-jdbcpostgresql-adapter", "~> 60.0", platform: :jruby
70
+ end
71
+ gem "activerecord", "~> 6.0.0"
72
+ end
data/Gemfile CHANGED
@@ -3,30 +3,14 @@ source "https://rubygems.org"
3
3
  # Specify your gem's dependencies in ranked-model.gemspec
4
4
  gemspec
5
5
 
6
- ar_version = ENV["ACTIVERECORD_VERSION"] || "default"
7
-
8
- ar_gem_version = case ar_version
9
- when "master"
10
- gem "activerecord", {github: "rails/rails"}
11
- when "default"
12
- # Allow the gemspec to specify
13
- else
14
- gem "activerecord", "~> #{ar_version}"
6
+ group :sqlite do
7
+ gem "sqlite3", "~> 1.3.13", platform: :ruby
15
8
  end
16
9
 
17
- platforms :rbx do
18
- gem 'rubysl', '~> 2.0'
19
- gem 'rubinius-developer_tools'
10
+ group :postgresql do
11
+ gem "pg", "~> 1.2.0", platform: :ruby
20
12
  end
21
13
 
22
- # SQLite
23
- gem "activerecord-jdbcsqlite3-adapter", ">= 1.3.0", platforms: :jruby
24
- gem "sqlite3", platforms: :ruby
25
-
26
- # Postgres
27
- gem "activerecord-jdbcpostgresql-adapter", platforms: :jruby
28
- gem "pg", platforms: :ruby
29
-
30
- # MySQL
31
- gem "activerecord-jdbcmysql-adapter", platforms: :jruby
32
- gem "mysql", platforms: :ruby
14
+ group :mysql do
15
+ gem "mysql2", "~> 0.5.0", platform: :ruby
16
+ end
data/Readme.mkd CHANGED
@@ -1,13 +1,11 @@
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
3
  [![Build Status](https://travis-ci.org/mixonic/ranked-model.png)](https://travis-ci.org/mixonic/ranked-model)
4
4
 
5
5
  Installation
6
6
  ------------
7
7
 
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.
8
+ ranked-model passes specs with Rails 4.2, 5.0, 5.1, 5.2 and 6.0 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
9
 
12
10
  To install ranked-model, just add it to your `Gemfile`:
13
11
 
@@ -16,7 +14,7 @@ gem 'ranked-model'
16
14
 
17
15
  # Or pin ranked-model to git
18
16
  # gem 'ranked-model',
19
- # :git => 'git@github.com:mixonic/ranked-model.git'
17
+ # git: 'git@github.com:mixonic/ranked-model.git'
20
18
  ```
21
19
 
22
20
  Then use `bundle install` to update your `Gemfile.lock`.
@@ -31,6 +29,18 @@ class Duck < ActiveRecord::Base
31
29
  end
32
30
  ```
33
31
 
32
+ Give them an order (integer column):
33
+
34
+ ```bash
35
+ rails g migration AddRowOrderToDucks row_order:integer
36
+ rails db:migrate
37
+ ```
38
+
39
+ **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)**
40
+
41
+
42
+
43
+
34
44
  Put your ducks in a row:
35
45
 
36
46
  ``` ruby
@@ -42,7 +52,7 @@ class Duck < ActiveRecord::Base
42
52
  end
43
53
  ```
44
54
 
45
- This simple example assumes an integer column called `row_order`. To order Ducks by this order:
55
+ Order the Ducks by this order:
46
56
 
47
57
  ``` ruby
48
58
  Duck.rank(:row_order).all
@@ -52,9 +62,11 @@ The ranking integers stored in the `row_order` column will be big and spaced apa
52
62
  implement a sorting UI, just update the resource by appending the column name with `_position` and indicating the desired position:
53
63
 
54
64
  ``` ruby
55
- @duck.update_attribute :row_order_position, 0 # or 1, 2, 37. :first, :last, :up and :down are also valid
65
+ @duck.update row_order_position: 0 # or 1, 2, 37. :first, :last, :up and :down are also valid
56
66
  ```
57
67
 
68
+ **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.**
69
+
58
70
  Position numbers begin at zero. A position number greater than the number of records acts the
59
71
  same as :last. :up and :down move the record up/down the ladder by one step.
60
72
 
@@ -70,27 +82,47 @@ $.ajax({
70
82
  });
71
83
  ```
72
84
 
85
+ 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.
86
+
87
+ 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.
88
+
89
+ ``` ruby
90
+ Duck.rank(:row_order).first.row_order_rank # => 0
91
+ Duck.rank(:row_order).third.row_order_rank # => 2
92
+ ```
93
+
73
94
  Complex Use
74
95
  -----------
75
96
 
76
- The `ranks` method takes serveral arguments:
97
+ The `ranks` method takes several arguments:
77
98
 
78
99
  ``` ruby
79
100
  class Duck < ActiveRecord::Base
80
101
 
81
102
  include RankedModel
82
103
 
83
- ranks :row_order, # Name this ranker, used with rank()
84
- :column => :sort_order # Override the default column, which defaults to the name
85
-
104
+ ranks :row_order, # Name this ranker, used with rank()
105
+ column: :sort_order # Override the default column, which defaults to the name
106
+
86
107
  belongs_to :pond
87
108
  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 )
109
+ with_same: :pond_id # Ducks belong_to Ponds, make the ranker scoped to one pond
110
+
111
+ ranks :row_order,
112
+ with_same: [:pond_id, :breed] # Lets rank them by breed
113
+
114
+ scope :walking, where(walking: true )
91
115
  ranks :walking_order,
92
- :scope => :walking # Narrow this ranker to a scope
116
+ scope: :walking # Narrow this ranker to a scope
93
117
 
118
+ belongs_to :parent, class_name: 'Duck', optional: true
119
+ ranks :child_order,
120
+ unless: :has_no_parent?, # Rank only ducks that have a parent. Alternatively a Proc or lambda can be passed, e.g. proc { parent.nil? }
121
+ with_same: :parent_id
122
+
123
+ def has_no_parent?
124
+ parent.nil?
125
+ end
94
126
  end
95
127
  ```
96
128
 
@@ -104,12 +136,95 @@ Pond.first.ducks.rank(:swimming_order)
104
136
  Duck.walking.rank(:walking)
105
137
  ```
106
138
 
139
+ Single Table Inheritance (STI)
140
+ ------------------------------
141
+
142
+ ranked-model scopes your records' positions based on the class name of the object. If you have
143
+ a STI `type` column set in your model, ranked-model will reference that class for positioning.
144
+
145
+ Consider this example:
146
+
147
+ ``` ruby
148
+ class Vehicle < ActiveRecord::Base
149
+ ranks :row_order
150
+ end
151
+
152
+ class Car < Vehicle
153
+ end
154
+
155
+ class Truck < Vehicle
156
+ end
157
+
158
+ car = Car.create!
159
+ truck = Truck.create!
160
+
161
+ car.row_order
162
+ => 0
163
+ truck.row_order
164
+ => 0
165
+ ```
166
+
167
+ In this example, the `row_order` for both `car` and `truck` will be set to `0` because they have
168
+ different class names (`Car` and `Truck`, respectively).
169
+
170
+ If you would like for both `car` and `truck` to be ranked together based on the base `Vehicle`
171
+ class instead, use the `class_name` option:
172
+
173
+ ``` ruby
174
+ class Vehicle < ActiveRecord::Base
175
+ ranks :row_order, class_name: 'Vehicle'
176
+ end
177
+
178
+ class Car < Vehicle
179
+ end
180
+
181
+ class Truck < Vehicle
182
+ end
183
+
184
+ car = Car.create!
185
+ truck = Truck.create!
186
+
187
+ car.row_order
188
+ => 0
189
+ truck.row_order
190
+ => 4194304
191
+ ```
192
+
193
+ Migrations for existing data
194
+ ----------------------------
195
+
196
+ If you use `ranked_model` with existing data, the following migration (for Rails
197
+ 6) can be a starting point. Make sure to declare `include RankedModel` and
198
+ `ranks :row_order` in your `Duck` before running the migration.
199
+
200
+ ```bash
201
+ rails g migration AddRowOrderToDucks row_order:integer
202
+ ```
203
+
204
+ Then, adjust the migration:
205
+ ```ruby
206
+ # e.g. file db/migrate/20200325095038_add_row_order_to_ducks.rb
207
+ class AddRowOrderToDucks < ActiveRecord::Migration[6.0]
208
+ def change
209
+ add_column :ducks, :row_order, :integer
210
+
211
+ # Newest Duck shall rank "highest"" (be last).
212
+ Duck.update_all('row_order = EXTRACT(EPOCH FROM created_at)')
213
+
214
+ # Alternatively, implement any other sorting default
215
+ # Duck.order(created_at: :desc).desc.each do |duck|
216
+ # duck.update!(row_order: duck.created_at.to_i + duck.age / 2)
217
+ # end
218
+ end
219
+ end
220
+ ```
221
+
107
222
  Internals
108
223
  ---------
109
224
 
110
- This libarary is written using ARel from the ground-up. This leaves the code much cleaner
225
+ This library is written using ARel from the ground-up. This leaves the code much cleaner
111
226
  than many implementations. ranked-model is also optimized to write to the database as little
112
- as possible: ranks are stored as a number between -8388607 and 8388607 (the MEDIUMINT range in MySQL).
227
+ as possible: ranks are stored as a number between -2147483648 and 2147483647 (the INT range in MySQL).
113
228
  When an item is given a new position, it assigns itself a rank number between two neighbors.
114
229
  This allows several movements of items before no digits are available between two neighbors. When
115
230
  this occurs, ranked-model will try to shift other records out of the way. If items can't be easily
@@ -121,13 +236,17 @@ Contributing
121
236
 
122
237
  Fork, clone, write a test, write some code, commit, push, send a pull request. Github FTW!
123
238
 
239
+ The code is published under the [MIT License](LICENSE).
240
+
124
241
  The specs can be run with sqlite, postgres, and mysql:
125
242
 
126
243
  ```
127
- DB=postgres bundle exec rake
244
+ bundle
245
+ appraisal install
246
+ DB=postgresql bundle exec appraisal rake
128
247
  ```
129
248
 
130
- Is no DB is specified, the tests run against sqlite.
249
+ If no DB is specified (`sqlite`, `mysql`, or `postgresql`), the tests run against sqlite.
131
250
 
132
251
  RankedModel is mostly the handiwork of Matthew Beale:
133
252
 
@@ -149,3 +268,4 @@ A hearty thanks to these contributors:
149
268
  * [jguyon](https://github.com/jguyon)
150
269
  * [pehrlich](https://github.com/pehrlich)
151
270
  * [petergoldstein](https://github.com/petergoldstein)
271
+ * [brendon](https://github.com/brendon)