{"id":15405142,"url":"https://github.com/fnando/sql_runner","last_synced_at":"2025-07-15T19:34:17.795Z","repository":{"id":50276966,"uuid":"60571365","full_name":"fnando/sql_runner","owner":"fnando","description":"SQLRunner allows you to load your queries out of SQL files, without using ORMs. Available only for PostgreSQL and MySQL.","archived":false,"fork":false,"pushed_at":"2024-05-08T23:31:00.000Z","size":71,"stargazers_count":7,"open_issues_count":0,"forks_count":2,"subscribers_count":1,"default_branch":"main","last_synced_at":"2025-06-26T06:03:29.186Z","etag":null,"topics":["mysql","postgresql","ruby","sql-files","sqlrunner"],"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/fnando.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":["fnando"],"custom":["https://www.paypal.me/nandovieira/🍕"]}},"created_at":"2016-06-07T01:08:31.000Z","updated_at":"2024-05-08T23:31:01.000Z","dependencies_parsed_at":"2024-10-20T12:40:00.499Z","dependency_job_id":null,"html_url":"https://github.com/fnando/sql_runner","commit_stats":{"total_commits":30,"total_committers":2,"mean_commits":15.0,"dds":0.2666666666666667,"last_synced_commit":"db6f7bdd5b87fe1f4c523aff44c5e4af19fad738"},"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/fnando/sql_runner","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnando%2Fsql_runner","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnando%2Fsql_runner/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnando%2Fsql_runner/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnando%2Fsql_runner/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/fnando","download_url":"https://codeload.github.com/fnando/sql_runner/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/fnando%2Fsql_runner/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":265455126,"owners_count":23768489,"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":["mysql","postgresql","ruby","sql-files","sqlrunner"],"created_at":"2024-10-01T16:15:13.467Z","updated_at":"2025-07-15T19:34:17.744Z","avatar_url":"https://github.com/fnando.png","language":"Ruby","readme":"# SQLRunner\n\n[![ruby-tests](https://github.com/fnando/sql_runner/actions/workflows/test.yml/badge.svg)](https://github.com/fnando/sql_runner/actions/workflows/test.yml)\n[![Gem](https://img.shields.io/gem/v/sql_runner.svg)](https://rubygems.org/gems/sql_runner)\n[![Gem](https://img.shields.io/gem/dt/sql_runner.svg)](https://rubygems.org/gems/sql_runner)\n\nSQLRunner allows you to load your queries out of SQL files, without using ORMs.\nAvailable for PostgreSQL and MySQL.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem \"sql_runner\"\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install sql_runner\n\n## Usage\n\nRun raw queries:\n\n```ruby\nSQLRunner.connect(\"postgresql:///test?application_name=myapp\")\n\nSQLRunner.execute(\"SELECT 1\")\n#=\u003e \u003cPG:Result:0x007fdf8d3475f0\u003e\n\nSQLRunner.execute(\"SELECT 1\").values\n#=\u003e [[\"1\"]]\n\nSQLRunner.execute(\"SELECT :number::integer\", number: 1).values\n#=\u003e [[\"1\"]]\n```\n\nRun SQL files:\n\n```ruby\nSQLRunner.root_dir = \"#{__dir__}/sql\"\n\nclass GetMembers \u003c SQLRunner::Query\n  # by default will use root_dir/get_members.{sql,psql}\nend\n```\n\nSpecify custom SQL:\n\n```ruby\nclass GetMembers \u003c SQLRunner::Query\n  query \"SELECT * FROM members ORDER BY created_at\"\nend\n```\n\nSpecify custom connection:\n\n```ruby\nclass GetMembers \u003c SQLRunner::Query\n  connect \"postgresql:///another_database\"\nend\n```\n\nSpecify other options:\n\n```ruby\nclass GetMembers \u003c SQLRunner::Query\n  query_name \"users\" #=\u003e will load root_dir/users.{psql,sql}\n  root_dir \"/some/path\"\nend\n```\n\nYou can use this with ActiveRecord as well. To make it work, all you need to do\nis establishing the connection using `activerecord:///`:\n\n```ruby\nrequire \"active_record\"\n\n# You probably won't need this if you're using Rails.\nActiveRecord::Base.establish_connection(\"postgresql:///database\")\n\n# Set the adapter to be based on ActiveRecord.\nSQLRunner.connect \"activerecord:///\"\n\nSQLRunner.execute \"SELECT 1\"\n#=\u003e \u003cPG:Result:0x008adf4d5495b0\u003e\n```\n\n### Plugins\n\n#### Load just one record\n\n```ruby\nclass FindUserByEmail \u003c SQLRunner::Query\n  plugin :one\n  query \"SELECT * FROM users WHERE email = :email LIMIT 1\"\nend\n\nFindUserByEmail.call(email: \"john@example.com\")\n#=\u003e {\"id\" =\u003e 1, \"email\" =\u003e \"john@example.com\"}\n\nFindUserByEmail.call(email: \"invalid\")\n#=\u003e nil\n\nFindUserByEmail.call!(email: \"invalid\")\n#=\u003e raise exception SQLRunner::RecordNotFound\n```\n\n#### Use a model\n\n```ruby\nrequire \"virtus\"\n\nclass UserModel\n  include Virtus.model\n\n  attribute :id, String\n  attribute :email, String\n  attribute :name, String\nend\n\nclass FindUserByEmail \u003c SQLRunner::Query\n  plugin :one\n  plugin model: UserModel\n  query \"SELECT * FROM users WHERE email = :email LIMIT 1\"\nend\n\nFindUserByEmail.call(email: \"john@example.com\")\n#=\u003e \u003cUserModel:0x007fdf8c2c1280\u003e\n```\n\n#### Avoid calling .to_a in collections\n\n```ruby\nclass FindUsers \u003c SQLRunner::Query\n  plugin :many\n  query \"SELECT * FROM users\"\nend\n\nFindUsers.call\n#=\u003e [{\"id\" =\u003e \"1\", \"email\" =\u003e \"john@example.com\"}]\n```\n\n### Adding new plugins\n\nFirst you have to create a class/module that implements the\n`.activate(target, options)` class method. The following example overrides the\n`call(**bind_vars)` method by using `Module.prepend`.\n\n```ruby\nmodule ReverseRecords\n  def self.activate(target, options)\n    target.singleton_class.prepend self\n  end\n\n  def call(**bind_vars)\n    super(**bind_vars).to_a.reverse\n  end\nend\n```\n\n#### Register the plugin.\n\n```ruby\nSQLRunner::Query.register_plugin :reverse, ReverseRecords\n\nclass Users \u003c SQLRunner::Query\n  query \"SELECT * FROM users ORDER BY created_at ASC\"\n  plugin :reverse\nend\n\nUsers.call\n```\n\nIf your plugin can receive options, you can call it as\n`plugin reverse: options`, where `options` can be anything (e.g. `Hash`,\n`Array`, `Object`, etc).\n\n## Benchmarks\n\nYou won't gain too much performance by using this gem. The idea is making SQL\neasier to read by extracting complex stuff to their own files. These are the\nresults against ActiveRecord using different wrapping libraries like\n[virtus](https://rubygems.org/gems/virtus) and\n[dry-types](https://rubygems.org/gems/dry-types).\n\nLoading just one record:\n\n```\n  sql_runner - find one (raw)      :     5518.6 i/s\n  sql_runner - find one (dry-types):     5015.4 i/s - same-ish: difference falls within error\n  sql_runner - find one (virtus)   :     4746.2 i/s - 1.16x slower\nactiverecord - find one            :     3468.5 i/s - 1.59x slower\n```\n\nLoading several records:\n\n```\n  sql_runner - find many (raw)      :     6808.2 i/s\n  sql_runner - find many (dry-types):     5251.4 i/s - same-ish: difference falls within error\n  sql_runner - find many (virtus)   :     4145.6 i/s - 1.64x slower\nactiverecord - find many            :     2731.5 i/s - 2.49x slower\n```\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run\n`rake test` to run the tests. You can also run `bin/console` for an interactive\nprompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To\nrelease a new version, update the version number in `version.rb`, and then run\n`bundle exec rake release`, which will create a git tag for the version, push\ngit commits and tags, and push the `.gem` file to\n[rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at\nhttps://github.com/fnando/sql_runner. This project is intended to be a safe,\nwelcoming space for collaboration, and contributors are expected to adhere to\nthe [Contributor Covenant](http://contributor-covenant.org) code of conduct.\n\n## License\n\nThe gem is available as open source under the terms of the\n[MIT License](http://opensource.org/licenses/MIT).\n","funding_links":["https://github.com/sponsors/fnando","https://www.paypal.me/nandovieira/🍕"],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffnando%2Fsql_runner","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Ffnando%2Fsql_runner","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Ffnando%2Fsql_runner/lists"}