Baike.dev
All toolsOnline toolsAI codingTrendingOpen sourceNewsSubmit
Log in
< Back to tools
R

ranked-model

> 编程语言
Open source

An acts_as_sortable/acts_as_list replacement built for Rails 4+

1.1K stars0 likes1 views
WebsiteGitHub

About

An acts_as_sortable/acts_as_list replacement built for Rails 4+

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. ANNOUNCING: Positioning, the gem

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

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!

Installation

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.

To install ranked-model, just add it to your Gemfile:

ruby
gem 'ranked-model'

# Or pin ranked-model to git
# gem 'ranked-model',
#   git: 'git@github.com:mixonic/ranked-model.git'

Then use bundle install to update your Gemfile.lock.

Simple Use

Use of ranked-model is straight ahead. Get some ducks:

ruby
class Duck  0
Duck.rank(:row_order).third.row_order_rank # => 2

Complex Use

The ranks method takes several arguments:

ruby
class Duck  0
truck.row_order
=> 0

In this example, the row_order for both car and truck will be set to 0 because they have different class names (Car and Truck, respectively).

If you would like for both car and truck to be ranked together based on the base Vehicle class instead, use the class_name option:

ruby
class Vehicle  0
truck.row_order
=> 4194304

Migrations for existing data

If you use ranked_model with existing data, the following migration (for Rails 6) can be a starting point. Make sure to declare include RankedModel and ranks :row_order in your Duck before running the migration.

bash
rails g migration AddRowOrderToDucks row_order:integer

Then, adjust the migration:

ruby
# e.g. file db/migrate/20200325095038_add_row_order_to_ducks.rb
class AddRowOrderToDucks < ActiveRecord::Migration[6.0]
  def change
    add_column :ducks, :row_order, :integer

    # Newest Duck shall rank "highest"" (be last).
    Duck.update_all('row_order = EXTRACT(EPOCH FROM created_at)')

    # Alternatively, implement any other sorting default
    # Duck.order(created_at: :desc).each do |duck|
    #   duck.update!(row_order: duck.created_at.to_i + duck.age / 2)
    # end
  end
end

Internals

This library is written using ARel from the ground-up. This leaves the code much cleaner than many implementations. ranked-model is also optimized to write to the database as little as possible: ranks are stored as a number between -2147483648 and 2147483647 (the INT range in MySQL). When an item is given a new position, it assigns itself a rank number between two neighbors. This allows several movements of items before no digits are available between two neighbors. When this occurs, ranked-model will try to shift other records out of the way. If items can't be easily shifted anymore, it will rebalance the distribution of rank numbers across all members of the ranked group.

Record updates to rebalance ranks do not trigger ActiveRecord callbacks. If you need to react to these updates (to index them in a secondary data store, for example), you can subscribe to the ranked_model.ranks_updated ActiveSupport notification. Subscribed consumers receive an event for each rearrangement or rebalancing, the payload of which includes the triggering instance and the scope and with_same options for the ranking, which can be used to retrieve the affected records.

ruby
ActiveSupport::Notifications.subscribe("ranked_model.ranks_updated") do |_name, _start, _finish, _id, payload|
  # payload[:instance] - the instance whose update triggered the rebalance
  # payload[:scope] - the scope applied to the ranking
  # payload[:with_same] - the with_same option applied to the ranking
end

Contributing

Fork, clone, write a test, write some code, commit, push, send a pull request. Github FTW!

The code is published under the MIT License.

The specs can be run with sqlite, postgres, and mysql:

bundle
appraisal install
DB=postgresql bundle exec appraisal rake

If no DB is specified (sqlite, mysql, or postgresql), the tests run against sqlite.

RankedModel is mostly the handiwork of Matthew Beale:

  • madhatted.com is where I blog. Also @mixonic.

A hearty thanks to these contributors:

  • Harvest where this Gem started. They are great, great folks.
  • yabawock
  • AndrewRadev
  • adheerajkumar
  • mikeycgto
  • robotex82
  • rociiu
  • codepodu
  • kakra
  • metalon
  • jamesalmond
  • jguyon
  • pehrlich
  • petergoldstein
  • brendon

Issues· 0 open

View all issuesOpen on GitHub

No open issues yet, or sync has not completed.

> Tags

Ruby

No comments yet. Be the first to share.

> Details

PublishedAug 1, 2026
UpdatedSep 17, 2026
Category编程语言
PricingOpen source

> Related tools

T
TypeScript
JavaScript 的超集,为前端与全栈提供静态类型
P
Python
通用编程语言,广泛用于 Web、数据与 AI
G
Go
Google 推出的简洁高效系统语言