{"id":13879137,"url":"https://github.com/umbrellio/umbrellio-sequel-plugins","last_synced_at":"2025-04-10T01:23:57.465Z","repository":{"id":39498680,"uuid":"169726983","full_name":"umbrellio/umbrellio-sequel-plugins","owner":"umbrellio","description":"Sequel plugins","archived":false,"fork":false,"pushed_at":"2024-09-23T07:35:30.000Z","size":144,"stargazers_count":15,"open_issues_count":1,"forks_count":8,"subscribers_count":8,"default_branch":"master","last_synced_at":"2025-02-26T09:43:36.806Z","etag":null,"topics":["database","extensions","plugins","sequel"],"latest_commit_sha":null,"homepage":null,"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/umbrellio.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null}},"created_at":"2019-02-08T11:45:52.000Z","updated_at":"2024-09-23T07:21:09.000Z","dependencies_parsed_at":"2024-11-09T06:36:57.065Z","dependency_job_id":null,"html_url":"https://github.com/umbrellio/umbrellio-sequel-plugins","commit_stats":{"total_commits":48,"total_committers":13,"mean_commits":"3.6923076923076925","dds":0.6041666666666667,"last_synced_commit":"642dfe00d297d7b161cebee07bfbda4fb40856ea"},"previous_names":[],"tags_count":18,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umbrellio%2Fumbrellio-sequel-plugins","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umbrellio%2Fumbrellio-sequel-plugins/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umbrellio%2Fumbrellio-sequel-plugins/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/umbrellio%2Fumbrellio-sequel-plugins/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/umbrellio","download_url":"https://codeload.github.com/umbrellio/umbrellio-sequel-plugins/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":248138786,"owners_count":21053952,"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":["database","extensions","plugins","sequel"],"created_at":"2024-08-06T08:02:10.933Z","updated_at":"2025-04-10T01:23:57.437Z","avatar_url":"https://github.com/umbrellio.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# SequelPlugins\n[![Build Status](https://travis-ci.org/umbrellio/umbrellio-sequel-plugins.svg?branch=master)](https://travis-ci.org/umbrellio/umbrellio-sequel-plugins)\n[![Coverage Status](https://coveralls.io/repos/github/umbrellio/umbrellio-sequel-plugins/badge.svg?branch=master)](https://coveralls.io/github/umbrellio/umbrellio-sequel-plugins?branch=master)\n[![Gem Version](https://badge.fury.io/rb/umbrellio-sequel-plugins.svg)](https://badge.fury.io/rb/umbrellio-sequel-plugins)\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'umbrellio-sequel-plugins'\n```\n\nAnd then execute:\n\n$ bundle\n\n# Extensions\n\n- [`CurrencyRates`](#currencyrates)\n- [`PGTools`](#pgtools)\n- [`Slave`](#slave)\n- [`Synchronize`](#synchronize)\n- [`Methods in Migrations`](#methods-in-migrations)\n- [`Deferrable Foreign Keys`](#deferrable-foreign-keys)\n- [`Set Local`](#set-local)\n- [`Migration Transaction Options`](#migration-transaction-options)\n- [`Fibered Connection Pool`](#fibered-connection-pool)\n\n# Plugins\n\n- [`AttrEncrypted`](#attrencrypted)\n- [`Duplicate`](#duplicate)\n- [`GetColumnValue`](#getcolumnvalue)\n- [`MoneyAccessors`](#moneyaccessors)\n- [`StoreAccessors`](#storeaccessors)\n- [`Synchronize`](#synchronize)\n- [`Upsert`](#upsert)\n- [`WithLock`](#withlock)\n\n# Tools\n- [`TimestampMigratorUndoExtension`](#timestampmigratorundoextension)\n- [`Rails DBConsole`](#rails-dbconsole)\n\n## CurrencyRates\n\nPlugin for joining currency rates table to any other table and money exchange.\n\nEnable: `DB.extension :currency_rates`\n\nCurrency rates table example:\n\n```sql\nCREATE TABLE currency_rates (\n    id integer NOT NULL,\n    currency text NOT NULL,\n    period tsrange NOT NULL,\n    rates jsonb NOT NULL\n);\n\nINSERT INTO currency_rates (currency, period, rates) VALUES\n('EUR', tsrange('2019-02-07 16:00:00 +0300', '2019-02-07 16:00:00 +0300'), '{\"USD\": 1.1, \"EUR\": 1.0, \"RUB\": 81}'),\n('EUR', tsrange('2019-02-07 17:00:00 +0300', NULL), '{\"USD\": 1.2, \"EUR\": 1.0, \"RUB\": 75}')\n```\n\nUsage example:\n\n```sql\nCREATE TABLE items (\n    id integer NOT NULL,\n    currency text NOT NULL,\n    price numeric NOT NULL,\n    created_at timestamp without time zone NOT NULL\n);\n\nINSERT INTO items (currency, price, created_at) VALUES (\"EUR\", 10, '2019-02-07 16:10:00 +0300')\n```\n\n```ruby\nDB[:items]\n    .with_rates\n    .select(Sequel[:price].exchange_to(\"USD\").as(:usd_price))\n    .first\n# =\u003e { \"usd_price\" =\u003e 12.0 }\n```\n\n\n## PGTools\n\nEnable: `DB.extension :pg_tools`\n\n### `#inherited_tables_for`\n\nPlugins for getting all inherited tables.\n\nExample:\n\n```ruby\nDB.inherited_tables_for(:event_log) # =\u003e [:event_log_2019_01, :event_log_2019_02]\n```\n\n## Slave\n\nEnable: `DB.extension :slave`\n\nPlugin for choosing slave server for query.\n\nExample:\n\n```ruby\nDB[:users].slave.where(email: \"test@test.com\") # executes on a slave server\n```\n\n**Important:** you have to define a server named 'slave' in sequel config before using it.\n\n\n## Synchronize\n\nEnable: `DB.extension :synchronize`\n\nPlugin for using transaction advisory locks for application-level mutexes.\n\nExample:\n\n```ruby\nDB.synchronize_with([:ruby, :forever]) { p \"Hey, I'm in transaction!\"; sleep 5 }\n# =\u003e BEGIN\n# =\u003e SELECT pg_try_advisory_xact_lock(3764656399) -- 'ruby-forever'\n# =\u003e COMMIT\n```\n\n## Methods in Migrations\n\nEnable: `Sequel.extension(:methods_in_migrations)`. Also, you will need to add and require `symbiont-ruby` gem.\n\nSupport for method definitions and invocations inside `Sequel.migration`.\n\nExample:\n\n```ruby\nSequel.extension(:methods_in_migrations)\n\nSequel.migration do\n  # define\n  def get_data\n    # ...some code...\n  end\n\n  # use\n  up { get_data }\n  down { get_data }\n\n  # without extension:\n  #   =\u003e NameError: undefined local variable or method `get_data' for #\u003cSequel::Postgres::Database\u003e\nend\n```\n\n## Deferrable Foreign Keys\n\nEnable: `Sequel.extension(:deferrable_foreign_keys)`\n\nMakes foreign keys constraints deferrable (`DEFERABLE INITIALLY DEFERRED`) by default.\n\nExample:\n\n```ruby\nDB.create_table(:users) { primary_key :id }\nDB.create_table(:items) do\n  primary_key :id\n  foreign_key :user_id, :users\nend\n```\n```sql\nCREATE TABLE users (\n  id integer NOT NULL\n);\nCREATE TABLE items (\n  id integer NOT NULL\n);\n\n-- without extension:\nALTER TABLE items ADD CONSTRAINT items_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id);\n\n-- with extension:\nALTER TABLE items ADD CONSTRAINT items_user_id_fkey FOREIGN KEY (user_id) REFERENCES users(id) DEFERRABLE INITIALLY DEFERRED;\n```\n\nOR\n\n```ruby\n# wives attributes: id (pk), husband_id (fk)\n# husbands attributes: id (pk), wife_id (fk)\n\nWife = Sequel::Model(:wives)\nHusband = Sequel::Model(:husbands)\n\nDB.transaction do\n  wife = Wife.create(id: 1, husband_id: 123456789)\n  husband = Husband.create(id: 1)\n  wife.update(husband_id: husband.id)\n  husband.update(wife_id: wife.id)\nend\n# assume there are no husband with id=123456789\n# without extension:\n#   =\u003e Sequel::ForeignKeyConstraintViolation: Key (husband_id)=(123456789) is not present in table \"husbands\".\n# with extension:\n#   =\u003e \u003cWife @attributes={id:1, husband_id: 1}\u003e\n#   =\u003e \u003cHusband @attributes={id:1, wife_id: 1}\u003e\n```\n\n\n## Set Local\n\nEnable: `DB.extension(:set_local)`\n\nMakes possible to set transaction locals.\n\nExample:\n\n```ruby\nDB.transaction(set_local: { lock_timeout: \"5s\", statement_timeout: \"5s\" }) {}\n```\n```sql\nBEGIN;\nSET LOCAL lock_timeout = '5s';\nSET LOCAL statement_timeout = '5s';\nCOMMIT;\n```\n\n\n## Migration Transaction Options\n\nEnable: `Sequel.extension(:migration_transaction_options)`\n\nMakes possible to pass `transaction_options` in migrations.\n\nExample:\n\n```ruby\nSequel.migration do\n  transaction_options rollback: :always\n\n  up { DB.select(\"1\") }\nend\n```\n```sql\nBEGIN;\nSELECT '1';\nROLLBACK;\n```\n\n## Fibered Connection Pool\n\nSequel connection pool for fiber powered web servers or applications\n(e.g. [falcon](https://github.com/socketry/falcon), [async](https://github.com/socketry/async))\n\nRuntime dependency: [async](https://github.com/socketry/async)\n\nYou need to make sure that command `require \"async\"` works for your project.\n\nThe main difference from default `Sequel::ThreadedConnectionPool` that you can skip max_connections\nconfiguration to produce as much connection as your application neeeded.\n\nAlso there is no any thead-safe code with synchronize and etc. So this connection pool works much\nfaster.\n\nEnable:\n\nPut this code before your application connects to database\n```ruby\nSequel.extension(:fiber_concurrency) # Default Sequel extension for fiber isolation level\nSequel.extension(:fibered_connection_pool)\n```\n\n## AttrEncrypted\n\nEnable: `Sequel::Model.plugin :attr_encrypted`\n\nPlugin for storing encrypted model attributes.\n\nExample:\n\n```ruby\nSequel.migration do\n  change do\n    alter_table :orders do\n      add_column :encrypted_first_name, :text\n      add_column :encrypted_last_name, :text\n      add_column :encrypted_secret_data, :text\n    end\n  end\nend\n\nclass Order \u003c Sequel::Model\n  attr_encrypted :first_name, :last_name, key: Settings.private_key\n  attr_encrypted :secret_data, key: Settings.another_private_key\nend\n\nOrder.create(first_name: \"Ivan\")\n# =\u003e INSERT INTO \"orders\" (\"encrypted_first_name\") VALUES ('/sTi9Q==$OTpuMRq5k8R3JayQ$WjSManQGP9UaZ3C40yDjKg==')\n\norder = Order.create(first_name: \"Ivan\", last_name: \"Smith\",\n                      secret_data: { \"some_key\" =\u003e \"Some Value\" })\norder.first_name # =\u003e \"Ivan\"\norder.secret_data # =\u003e { \"some_key\" =\u003e \"Some Value\" }\n```\n\n## Duplicate\n\nEnable: `Sequel::Model.plugin :duplicate`\n\nModel plugin for creating a copies.\n\nExample:\n\n```ruby\nUser = Sequel::Model(:users)\nuser1 = User.create(name: \"John\")\nuser2 = user1.duplicate(name: \"James\")\nuser2.name # =\u003e \"James\"\n```\nOR\n\n```ruby\nuser2 = User.duplicate(user1, name: \"James\")\nuser2.name # =\u003e \"James\"\n```\n\n## GetColumnValue\n\nEnable: `Sequel::Model.plugin :get_column_value`\n\nPlugin for getting raw column value\n\nExample:\n\n```ruby\nitem = Item.first\nitem.price # =\u003e #\u003cMoney fractional:5000.0 currency:USD\u003e\nitem.get_column_value(:amount) # =\u003e 0.5e2\n```\n\n## MoneyAccessors\n\n**Important:** requires `money` gem described below.\n\nPlugin for using money field keys as model properties.\n\nEnable:\n\n```ruby\ngem \"money\"\nSequel::Model.plugin :money_accessors\n````\n\nExamples of usage:\n\n##### Money accessor\n\n```ruby\nclass Order \u003c Sequel::Model\n  money_accessor :amount, :currency\nend\n\norder = Order.create(amount: 200, currency: \"EUR\")\norder.amount # =\u003e #\u003cMoney fractional:20000.0 currency:EUR\u003e\norder.currency # =\u003e \"EUR\"\n\norder.amount = Money.new(150, \"RUB\")\norder.amount # =\u003e #\u003cMoney fractional:150.0 currency:RUB\u003e\n```\n\n##### Money setter\n\n```ruby\nclass Order \u003c Sequel::Model\n  money_setter :amount, :currency\nend\n\norder = Order.create(amount: 200, currency: \"EUR\")\norder.amount = Money.new(150, \"RUB\")\norder.currency # =\u003e \"RUB\"\n```\n\n##### Money getter\n\n```ruby\nclass Order \u003c Sequel::Model\n  money_getter :amount, :currency\nend\n\norder = Order.create(amount: 200, currency: \"EUR\")\norder.amount # =\u003e #\u003cMoney fractional:20000.0 currency:EUR\u003e\norder.currency # =\u003e \"EUR\"\n```\n\n## StoreAccessors\n\nEnable: `Sequel::Model.plugin :store_accessors`\n\nPlugin for using jsonb field keys as model properties.\n\nExample:\n\n```ruby\nclass User \u003c Sequel::Model\n  store :data, :first_name, :last_name\nend\n\nuser = User.create(first_name: \"John\")\nuser.first_name # =\u003e \"John\"\nuser.data # =\u003e {\"first_name\": \"John\"}\n```\n\n## Synchronize\n\n**Important:** requires a `synchronize` extension described below.\n\nSame as `DB#synchronize_with`\n\nEnable:\n\n```ruby\nDB.extension :synchronize\nSequel::Model.plugin :synchronize\n```\n\nExample:\n\n```ruby\nuser = User.first\nuser.synchronize([:ruby, :forever]) { p \"Hey, I'm in transaction!\"; sleep 5 }\n```\n\n## Upsert\n\nEnable: `Sequel::Model.plugin :upsert`\n\nPlugin for create an \"UPSERT\" requests to database.\n\nExample:\n\n```ruby\nUser.upsert(name: \"John\", email: \"jd@test.com\", target: :email)\nUser.upsert_dataset.insert(name: \"John\", email: \"jd@test.com\")\n```\n\n## WithLock\n\nEnable: `Sequel::Model.plugin :with_lock`\n\nPlugin for locking row for update.\n\nExample:\n\n```ruby\nuser = User.first\nuser.with_lock do\n  user.update(name: \"James\")\nend\n```\n\n## TimestampMigratorUndoExtension\nAllows to undo a specific migration\n\nExample:\n\n```ruby\nm = Sequel::TimestampMigrator.new(DB, \"db/migrations\")\nm.undo(1549624163) # 1549624163 is a migration version\n```\n\nAlso you can use `sequel:undo` rake task for it.\nExample:\n\n```sh\nrake sequel:undo VERSION=1549624163\n```\n\n## Rails DBConsole\n\nOverrides Rails default `dbconsole` and `db` commands. In order to use it, you have to add the following line to your `boot.rb` file:\n\n```ruby\nrequire \"umbrellio_sequel_plugins/rails_db_command\"\n```\n\n# Database Tasks for ClickHouse and Sequel\n\n## ClickHouse Rake Tasks\n\nWe have added a set of Rake tasks to manage ClickHouse database migrations and database operations. These tasks are located in the `namespace :ch`.\n\n### Task: `ch:create`\n\nCreates a ClickHouse database in the specified cluster.\n\n```bash\nrake ch:create\n```\nThis task will create a ClickHouse database as defined in the configuration file with the option to specify the cluster using the ClickHouse.config.database.\n\nExample: \n```ruby\nClickHouse.config do |config|\n  config.assign Rails.application.config_for(:clickhouse)\nend\n```\n\n### Task: `ch:create_migration_table`\n\nCreates a migration tracking table for ClickHouse in PostgreSQL. This table will be used to track applied migrations for the ClickHouse database.\n\n```bash\nrake ch:create_migration_table\n```\n\n### Task: `ch:drop`\n\nDrops the ClickHouse database and truncates the migration tracking table.\n\n```bash\nrake ch:drop\n```\n\n### Task: `ch:migrate`\n\nRuns the migrations for the ClickHouse database from the db/migrate/clickhouse directory.\n\n```bash\nrake ch:migrate\n```\n\nYou can specify a version to migrate to using the VERSION environment variable.\n\n### Task: `ch:rollback`\n\nRollbacks the migrations for the ClickHouse database to a specified version.\n\n```bash\nrake ch:rollback VERSION=\u003cversion_number\u003e\n```\n\nIf no version is provided, it rolls back the last migration.\n\n### Task: `ch:reset`\n\nDrops, recreates, and runs all migrations for the ClickHouse database. This is useful for resetting the entire ClickHouse setup.\n\n```bash\nrake ch:reset\n```\n\n### Task: `ch:rollback_missing_migrations`\n\nRollbacks any missing migrations for the ClickHouse database by comparing applied migrations to the available migration files.\n\n```bash\nrake ch:rollback_missing_migrations\n```\n\n### Sequel Rake Tasks\n\nSeveral tasks have been added under the namespace :sequel to provide better management of migrations and rollbacks in Sequel. These tasks help in managing PostgreSQL and ClickHouse migrations.\n\n### Task: `sequel:archive_migrations`\n\nArchives migration source code into a PostgreSQL table for tracking purposes. This task can now accept custom paths for migrations and source tables.\n\n```bash\nrake sequel:archive_migrations[migrations_path, migration_table_source]\n```\n\n- `migrations_path`: Path to the migration files (default is `db/migrate/*.rb`).\n- `migration_table_source`: Table to store migration source code (default is `:schema_migrations_sources`).\n\n### `Task: sequel:rollback_archived_migrations`\n\nRollbacks migrations that were applied but are no longer present in the current release. The task supports additional options such as custom migration paths, tables, and transaction settings.\n\n```bash\nrake sequel:rollback_archived_migrations[migrations_path, migration_table, migration_table_source, use_transactions]\n```\n\n- `migrations_path`: Path to the migration files (default is `db/migrate/*.rb`).\n- `migration_table`: Table used to track applied migrations (default is `:schema_migrations`).\n- `migration_table_source`: Table storing migration source code (default is `:schema_migrations_sources`).\n- `use_transactions`: Whether to use transactions for rolling back (default is `false`).\n\n### Task: `sequel:rollback_missing_migrations`\n\nRollbacks migrations that are absent in the current release when deploying to staging or production. This task helps ensure consistency between different versions.\n\n```bash\nrake sequel:rollback_missing_migrations[table, use_transactions]\n```\n\n- `table`: The table used to track migrations (optional).\n- `use_transactions`: Whether to use transactions during rollback (default is `false`).\n\n### Task: `sequel:rollback_missing_migrations`\n\nThis task specifically helps during deployment by rolling back any migrations that are not present in the current release.\n\n```bash\nrake sequel:rollback_missing_migrations[table, use_transactions]\n```\n\n- `table`: The table used to track migrations (optional).\n- `use_transactions`: Whether or not to use transactions when rolling back (optional).\n\n## License\n\nReleased under MIT License.\n\n## Authors\n\nCreated by Team Umbrellio.\n\n\u003ca href=\"https://github.com/umbrellio/\"\u003e\n  \u003cimg style=\"float: left;\" src=\"https://umbrellio.github.io/Umbrellio/supported_by_umbrellio.svg\" alt=\"Supported by Umbrellio\" width=\"439\" height=\"72\"\u003e\n\u003c/a\u003e\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fumbrellio%2Fumbrellio-sequel-plugins","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fumbrellio%2Fumbrellio-sequel-plugins","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fumbrellio%2Fumbrellio-sequel-plugins/lists"}