{"id":20154929,"url":"https://github.com/aliou/tablature","last_synced_at":"2025-05-06T22:31:07.668Z","repository":{"id":59157141,"uuid":"138424719","full_name":"aliou/tablature","owner":"aliou","description":"Rails + Postgres partitions","archived":true,"fork":false,"pushed_at":"2021-08-27T08:17:40.000Z","size":120,"stargazers_count":8,"open_issues_count":7,"forks_count":0,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-04-26T09:38:24.117Z","etag":null,"topics":["partitioning","postgres","postgresql","rails","ruby"],"latest_commit_sha":null,"homepage":"","language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/aliou.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2018-06-23T18:27:41.000Z","updated_at":"2025-03-08T09:56:18.000Z","dependencies_parsed_at":"2022-09-13T20:04:02.177Z","dependency_job_id":null,"html_url":"https://github.com/aliou/tablature","commit_stats":null,"previous_names":[],"tags_count":8,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aliou%2Ftablature","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aliou%2Ftablature/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aliou%2Ftablature/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/aliou%2Ftablature/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/aliou","download_url":"https://codeload.github.com/aliou/tablature/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":252778968,"owners_count":21802859,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["partitioning","postgres","postgresql","rails","ruby"],"created_at":"2024-11-13T23:29:04.845Z","updated_at":"2025-05-06T22:31:07.276Z","avatar_url":"https://github.com/aliou.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Tablature\n\nTablature is a library built on top of ActiveRecord to simplify management of partitioned tables in Rails applications.\nIt ships with Postgres support and can easily supports other databases through adapters.\n\n## Status\n\nTablature is a learning project is not currently used in production. It is probably not production-ready, YMMV.\n\n## Installation\n\n##### Requirements\n\nTablature requires Ruby 2.5+, Rails 5+ and Postgres 10+.\n\n##### Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'tablature'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install tablature\n\n## Usage\n\n### Partitioning a table\n\n```ruby\nclass CreateEvents \u003c ActiveRecord::Migration[5.0]\n  def up\n    # Create the events table as a partitioned table using range as partitioning method\n    # and `event_date` as partition key.\n    create_range_partition :events_by_range, partition_key: 'event_date' do |t|\n      t.string :event_type, null: false\n      t.integer :value, null: false\n      t.date :event_date, null: false\n    end\n\n    # Create partitions with the bounds of the partition.\n    create_range_partition_of :events_by_range,\n      name: 'events_range_y2018m12', range_start: '2018-12-01', range_end: '2019-01-01'\n\n    # Create the events table as a partitioned table using list as partitioning method\n    # and `event_date` as partition key.\n    create_list_partition :events_by_list, partition_key: 'event_date' do |t|\n      t.string :event_type, null: false\n      t.integer :value, null: false\n      t.date :event_date, null: false\n    end\n\n    # Create partitions with the bounds of the partition.\n    create_list_partition_of :events_by_list,\n      name: 'events_list_y2018m12', values: (Date.parse('2018-12-01')..Date.parse('2018-12-31')).to_a\n\n  end\n\n  def down\n    drop_table :events_by_range\n    drop_table :events_by_list\n  end\nend\n```\n\n### Having a partition back a model\n\nIn your migration:\n```ruby\n# db/migrate/create_events.rb\nclass CreateEvents \u003c ActiveRecord::Migration\n  def change\n    # You can use blocks when the partition key are SQL expression instead of\n    # being only a field.\n    create_range_partition :events, partition_key: -\u003e { '(timestamp::DATE)' } do |t|\n      t.string :event_type, null: false\n      t.integer :value, null: false\n      t.datetime :timestamp, null: false\n      t.timestamps\n    end\n\n    create_range_partition_of :events,\n      name: 'events_y2018m12', range_start: '2018-12-01', range_end: '2019-01-01'\n\n    create_range_partition_of :events,\n      name: 'events_y2019m01', range_start: '2019-01-01', range_end: '2019-02-01'\n  end\nend\n```\n\nIn your model, calling one of `range_partition` or `list_partition` to inject\nmethods:\n```ruby\n# app/models/event.rb\nclass Event \u003c ApplicationRecord\n  range_partition\nend\n```\n\nFinally, you can now list the partitions :\n```ruby\n\u003e\u003e Event.partitions\n# =\u003e [\"events_y2018m12\", \"events_y2019m01\"]\n```\n\nYou can also create new partitions directly from the model :\n```ruby\n\u003e\u003e Event.create_range_partition(\n    name: 'events_y2019m02',\n    range_start: '2019-02-01'.to_date,\n    range_end: '2019-03-01'.to_date\n  )\n# =\u003e ...\n\u003e\u003e Event.partitions\n# =\u003e [\"events_y2018m12\", \"events_y2019m01\", \"events_y2019m02\"]\n```\n\n### Partitioning an existing table\nStart by renaming your table and create the partition table:\n```ruby\nclass PartitionEvents \u003c ActiveRecord::Migration\n  def change\n    # Get the bounds of the events.\n    min_month = Event.minimum(:timestamp).beginning_of_month.to_date\n    max_month = Event.maximum(:timestamp).beginning_of_month.to_date\n\n    # Create the partition bounds based on the existing data. In this example,\n    # we generate an array with the ranges.\n    months = min_month.upto(max_month).uniq(\u0026:beginning_of_month)\n\n    # Rename the existing table.\n    rename_table :events, :old_events\n\n    # Create the partitioned table.\n    create_range_partition :events, partition_key: -\u003e { '(timestamp::DATE)' } do |t|\n      t.string :event_type, null: false\n      t.integer :value, null: false\n      t.datetime :timestamp, null: false\n      t.timestamps\n    end\n\n    # Create the partitions based on the bounds generated before:\n    months.each do |month|\n      # Creates a name like \"events_y2018m12\"\n      partition_name = \"events_y#{month.year}m#{month.month}\"\n\n      create_range_partition_of :events,\n        name: partition_name, range_start: month, range_end: month.next_month\n    end\n\n    # Finally, add the rows from the old table to the new partitioned table.\n    # This might take some time depending on the size of your old table.\n    execute(\u003c\u003c~SQL)\n      INSERT INTO events\n      SELECT * FROM old_events\n    SQL\n  end\nend\n```\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies.\nThen, run `rake spec` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Acknowledgements\nTablature's structure is heavily inspired by [Scenic](https://github.com/scenic-views/scenic) and [F(x)](http://github.com/teoljungberg/fx).\nTablature's features are heavily inspired by [PgParty](https://github.com/rkrage/pg_party).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/aliou/tablature.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faliou%2Ftablature","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Faliou%2Ftablature","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Faliou%2Ftablature/lists"}