{"id":13879604,"url":"https://github.com/janko/sequel-activerecord_connection","last_synced_at":"2025-05-15T20:04:29.702Z","repository":{"id":41814152,"uuid":"259274048","full_name":"janko/sequel-activerecord_connection","owner":"janko","description":"Allows Sequel to reuse Active Record's database connection","archived":false,"fork":false,"pushed_at":"2024-12-25T20:52:08.000Z","size":351,"stargazers_count":138,"open_issues_count":0,"forks_count":11,"subscribers_count":7,"default_branch":"master","last_synced_at":"2025-04-11T00:04:42.366Z","etag":null,"topics":["activerecord","database-connection","sequel"],"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/janko.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":".github/FUNDING.yml","license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","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},"funding":{"github":"janko"}},"created_at":"2020-04-27T09:58:58.000Z","updated_at":"2025-03-30T00:46:47.000Z","dependencies_parsed_at":"2023-12-26T23:31:01.639Z","dependency_job_id":"c320b25f-cfa4-4de9-a00b-956bbfe4cf8e","html_url":"https://github.com/janko/sequel-activerecord_connection","commit_stats":null,"previous_names":["janko/sequel-activerecord-adapter"],"tags_count":33,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janko%2Fsequel-activerecord_connection","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janko%2Fsequel-activerecord_connection/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janko%2Fsequel-activerecord_connection/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janko%2Fsequel-activerecord_connection/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janko","download_url":"https://codeload.github.com/janko/sequel-activerecord_connection/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":254414499,"owners_count":22067272,"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":["activerecord","database-connection","sequel"],"created_at":"2024-08-06T08:02:26.551Z","updated_at":"2025-05-15T20:04:22.952Z","avatar_url":"https://github.com/janko.png","language":"Ruby","funding_links":["https://github.com/sponsors/janko"],"categories":["Ruby","Gems"],"sub_categories":["Articles"],"readme":"# sequel-activerecord_connection\n\nThis is a database extension for [Sequel] that makes it to reuse an existing\nActive Record connection for database interaction.\n\nThis can be useful if you want to use a library that uses Sequel (e.g.\n[Rodauth] or [rom-sql]), or you're transitioning from Active Record to Sequel,\nor if you just want to use Sequel for more complex queries, and you want to\navoid creating new database connections.\n\nIt fully supports PostgreSQL, MySQL and SQLite adapters, both the native ones\nand JDBC (JRuby). The [SQL Server] external adapter is supported as well\n(`tinytds` in Sequel), and there is attempted support for [Oracle enhanced]\n(`oracle` and in Sequel). Other adapters might work too, but their integration\nhasn't been tested.\n\n## Why reuse the database connection?\n\nAt first it might appear that, as long as you're fine with the performance\nimpact of your database server having to maintain additional open connections,\nit would be fine if Sequel had its own database connection. However, there are\nadditional caveats when you try to combine it with Active Record.\n\nIf Sequel and Active Record each have their own connections, then it's not\npossible to combine their transactions. If we executed a Sequel query inside of\nan Active Record transaction, that query won't actually be executed inside a\ndatabase transaction. This is because transactions are tied to the database\nconnection; if one connection opens a transaction, this doesn't affect queries\nexecuted on a different connection, even if both connections are used in the\nsame ruby process. With this library, transactions and queries can be\nseamlessly combined between Active Record and Sequel.\n\nIn Rails context, there are additional considerations for a Sequel connection\nto play nicely. Connecting and disconnecting would have to go in lockstep with\nActive Record, to make commands such as `rails db:create` and `rails db:drop`\nwork. You'd also need to find a way for system tests and the app running in the\nbackground to share the same database connection, which is something Sequel\nwasn't designed for. Reusing Active Record's connection means (dis)connecting\nand sharing between threads is all handled automatically.\n\n## Installation\n\nAdd the gem to your project:\n\n```sh\n$ bundle add sequel-activerecord_connection\n```\n\nIf you're using Active Record 7.1 or older, you'll also need to add the [after_commit_everywhere] gem:\n\n```sh\n$ bundle add after_commit_everywhere # on Active Record 7.1 or older\n```\n\n## Usage\n\nAssuming you've configured your ActiveRecord connection, you can initialize the\nappropriate Sequel adapter and load the `activerecord_connection` extension: e.g.\n\n```rb\n# Place in relevant initializer\n# e.g. Rails: config/initializers/sequel.rb\n\nrequire \"sequel\"\nDB = Sequel.postgres(extensions: :activerecord_connection) # for PostgreSQL\n```\n\nNow any Sequel operations that you make will internaly be done using the\nActiveRecord connection, so you should see the queries in your ActiveRecord\nlogs.\n\n```rb\nDB.create_table :posts do\n  primary_key :id\n  String :title, null: false\n  Stirng :body, null: false\nend\n\nDB[:posts].insert(\n  title: \"Sequel::ActiveRecordConnection\",\n  body:  \"Allows Sequel to reuse ActiveRecord's connection\",\n)\n#=\u003e 1\n\nDB[:posts].all\n#=\u003e [{ title: \"Sequel::ActiveRecordConnection\", body: \"Allows Sequel to reuse ActiveRecord's connection\" }]\n\nDB[:posts].update(title: \"sequel-activerecord_connection\")\n#=\u003e 1\n```\n\nThe database extension supports `postgresql`, `mysql2` and `sqlite3`\nActiveRecord adapters, just make sure to initialize the corresponding Sequel\nadapter before loading the extension.\n\n```rb\nSequel.postgres(extensions: :activerecord_connection) # for \"postgresql\" adapter\nSequel.mysql2(extensions: :activerecord_connection)   # for \"mysql2\" adapter\nSequel.sqlite(extensions: :activerecord_connection)   # for \"sqlite3\" adapter\n```\n\nIf you're on JRuby, you should be using the JDBC adapters:\n\n```rb\nSequel.connect(\"jdbc:postgresql://\", extensions: :activerecord_connection) # for \"jdbcpostgresql\" adapter\nSequel.connect(\"jdbc:mysql://\", extensions: :activerecord_connection)      # for \"jdbcmysql\" adapter\nSequel.connect(\"jdbc:sqlite://\", extensions: :activerecord_connection)     # for \"jdbcsqlite3\" adapter\n```\n\n### Transactions\n\nThis database extension keeps the transaction state of Sequel and ActiveRecord\nin sync, allowing you to use Sequel and ActiveRecord transactions\ninterchangeably (including nesting them), and have things like ActiveRecord's\nand Sequel's transactional callbacks still work correctly.\n\n```rb\nActiveRecord::Base.transaction do\n  DB.in_transaction? #=\u003e true\nend\n```\n\nSequel's transaction API is fully supported:\n\n```rb\nDB.transaction(isolation: :serializable) do\n  DB.after_commit { ... } # executed after transaction commits\n  DB.transaction(savepoint: true) do # creates a savepoint\n    DB.after_commit(savepoint: true) { ... } # executed if all enclosing savepoints have been released\n  end\nend\n```\n\nWhen registering transaction hooks, they will be registered on Sequel\ntransactions when possible, in which case they will behave as described in the\n[Sequel docs][sequel transaction hooks].\n\n```rb\n# Sequel: An after_commit transaction hook will always get executed if the outer\n# transaction commits, even if it's added inside a savepoint that's rolled back.\nDB.transaction do\n  ActiveRecord::Base.transaction(requires_new: true) do\n    DB.after_commit { puts \"after commit\" }\n    raise ActiveRecord::Rollback\n  end\nend\n#\u003e\u003e BEGIN\n#\u003e\u003e SAVEPOINT active_record_1\n#\u003e\u003e ROLLBACK TO SAVEPOINT active_record_1\n#\u003e\u003e COMMIT\n#\u003e\u003e after commit\n\n# Sequel: An after_commit savepoint hook will get executed only after the outer\n# transaction commits, given that all enclosing savepoints have been released.\nDB.transaction(auto_savepoint: true) do\n  DB.transaction do\n    DB.after_commit(savepoint: true) { puts \"after commit\" }\n    raise Sequel::Rollback\n  end\nend\n#\u003e\u003e BEGIN\n#\u003e\u003e SAVEPOINT active_record_1\n#\u003e\u003e ROLLBACK TO SAVEPOINT active_record_1\n#\u003e\u003e COMMIT\n```\n\nIn case of (a) adding a transaction hook while Active Record holds the\ntransaction, or (b) adding a savepoint hook when Active Record holds any\nenclosing savepoint, Active Record transaction callbacks will be used instead\nof Sequel hooks, which have slightly different behaviour in some circumstances.\n\n```rb\n# ActiveRecord: An after_commit transaction callback is not executed if any\n# if the enclosing savepoints have been rolled back\nActiveRecord::Base.transaction do\n  DB.transaction(savepoint: true) do\n    DB.after_commit { puts \"after commit\" }\n    raise Sequel::Rollback\n  end\nend\n#\u003e\u003e BEGIN\n#\u003e\u003e SAVEPOINT active_record_1\n#\u003e\u003e ROLLBACK TO SAVEPOINT active_record_1\n#\u003e\u003e COMMIT\n\n# ActiveRecord: An after_commit transaction callback can be executed already\n# after a savepoint is released, if the enclosing transaction is not joinable.\nActiveRecord::Base.transaction(joinable: false) do\n  DB.transaction do\n    DB.after_commit { puts \"after savepoint release\" }\n  end\nend\n#\u003e\u003e BEGIN\n#\u003e\u003e SAVEPOINT active_record_1\n#\u003e\u003e RELEASE SAVEPOINT active_record_1\n#\u003e\u003e after savepoint release\n#\u003e\u003e COMMIT\n```\n\n### Model\n\nBy default, the connection configuration will be read from `ActiveRecord::Base`.\nIf you want to use connection configuration from a different model, you can\ncan assign it to the database object after loading the extension:\n\n```rb\nclass MyModel \u003c ActiveRecord::Base\n  connects_to database: { writing: :animals, reading: :animals_replica }\nend\n```\n```rb\nDB.activerecord_model = MyModel\n```\n\n### Normalizing SQL logs\n\nActive Record injects values into queries using bound variables, and displays\nthem at the end of SQL logs:\n\n```sql\nSELECT accounts.* FROM accounts WHERE accounts.email = $1 LIMIT $2  [[\"email\", \"user@example.com\"], [\"LIMIT\", 1]]\n```\n\nSequel interpolates values into its queries, so by default its SQL logs include\nthem inline:\n\n```sql\nSELECT accounts.* FROM accounts WHERE accounts.email = 'user@example.com' LIMIT 1\n```\n\nIf you want to normalize logs to group similar queries, or you want to protect\nsensitive data from being stored in the logs, you can use the\n[sql_log_normalizer] extension to remove literal strings and numbers from\nlogged SQL queries:\n\n```rb\nSequel.postgres(extensions: [:activerecord_connection, :sql_log_normalizer])\n```\n```sql\nSELECT accounts.* FROM accounts WHERE accounts.email = ? LIMIT ?\n```\n\n## Tests\n\nYou'll first want to run the rake tasks for setting up databases and users:\n\n```sh\n$ rake db_setup_postgres\n$ rake db_setup_mysql\n```\n\nThen you can run the tests:\n\n```sh\n$ rake test\n```\n\nWhen you're done, you can delete the created databases and users:\n\n```sh\n$ rake db_teardown_postgres\n$ rake db_teardown_mysql\n```\n\n## Support\n\nPlease feel free to raise a new disucssion in [Github issues](https://github.com/janko/sequel-activerecord_connection/discussions), or search amongst the existing questions there.\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in this project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/janko/sequel-activerecord-adapter/blob/master/CODE_OF_CONDUCT.md).\n\n[Sequel]: https://github.com/jeremyevans/sequel\n[Rodauth]: https://github.com/jeremyevans/rodauth\n[rom-sql]: https://github.com/rom-rb/rom-sql\n[sequel transaction hooks]: http://sequel.jeremyevans.net/rdoc/files/doc/transactions_rdoc.html#label-Transaction+Hooks\n[Oracle enhanced]: https://github.com/rsim/oracle-enhanced\n[SQL Server]: https://github.com/rails-sqlserver/activerecord-sqlserver-adapter\n[sql_log_normalizer]: https://sequel.jeremyevans.net/rdoc-plugins/files/lib/sequel/extensions/sql_log_normalizer_rb.html\n[after_commit_everywhere]: https://github.com/Envek/after_commit_everywhere\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanko%2Fsequel-activerecord_connection","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanko%2Fsequel-activerecord_connection","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanko%2Fsequel-activerecord_connection/lists"}