{"id":18118196,"url":"https://github.com/sirscriptalot/query_set","last_synced_at":"2026-04-18T10:35:23.411Z","repository":{"id":56889887,"uuid":"107438537","full_name":"sirscriptalot/query_set","owner":"sirscriptalot","description":"A small wrapper for the Ruby 'pg' gem.","archived":false,"fork":false,"pushed_at":"2017-10-18T17:18:37.000Z","size":14,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-03T13:50:12.950Z","etag":null,"topics":["pg","pgsql","postgres","postgresql","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/sirscriptalot.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}},"created_at":"2017-10-18T17:06:52.000Z","updated_at":"2017-10-18T17:21:10.000Z","dependencies_parsed_at":"2022-08-20T15:20:37.970Z","dependency_job_id":null,"html_url":"https://github.com/sirscriptalot/query_set","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/sirscriptalot/query_set","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sirscriptalot%2Fquery_set","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sirscriptalot%2Fquery_set/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sirscriptalot%2Fquery_set/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sirscriptalot%2Fquery_set/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/sirscriptalot","download_url":"https://codeload.github.com/sirscriptalot/query_set/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/sirscriptalot%2Fquery_set/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":31966126,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-18T00:39:45.007Z","status":"online","status_checked_at":"2026-04-18T02:00:07.018Z","response_time":103,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"can_crawl_api":true,"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":["pg","pgsql","postgres","postgresql","ruby"],"created_at":"2024-11-01T05:09:27.785Z","updated_at":"2026-04-18T10:35:23.379Z","avatar_url":"https://github.com/sirscriptalot.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# QuerySet\n\nQuerySet is a small wrapper around the Ruby pg gem for safely executing\nsql that is saved in files.\n\n## Installation\n\n`$ gem install query_set`\n\n## API\n\n### QuerySet\n\n`initialize` Requires a connection and a formattable directory path.\nOptional arguments include `query:` for setting the query class, and `store:`\nfor setting the caching object.\n\n`[]` Fetches a query object from the cache (store). If it does not exist, loads\nthe corresponding template from disk and compiles it.\n\n`[]=` Manually sets an object in the cache.\n\n`execute` Delegates execution to the appropriate query object, passing it the configured\nconnection and any provided arguments.\n\n### Query\n\n`initialize` Requires a string to be compiled into a sql string with ordered\nplaceholders.\n\n`execute` Sends sql to the connection for the given arguments.\n\n## Usage\n\nTo get an understanding of QuerySet (qs), we're going to start from the bottom\nand build our way up. The foundation of qs is the class QuerySet::Query.\n\nQuerySet::Query is responsible for parsing a template string,\nand converting it into a sql string with position based placeholders that\nPostgres understands. This buys us two things. First, we \"upgrade\" our coupling\nfrom one that is based on position to one that is based on name\n(which is generally a good thing, see [connascence][connascence]). The second\nthing we get is security, since we no longer have to be escaping sql strings\nmanually we get to avoid all sorts of vulnerabilities. If you ever find yourself\nusing QuerySet::Query manually, remember to always escape any untrusted values\nvia `PG::Connection.escape_string`.\n\n```ruby\n  # Initialize a new query object.\n  query = QuerySet::Query.new(\"SELECT * FROM users WHERE id = {{ id }} LIMIT 1;\")\n\n  # During initialization, the query object\n  # \"compiles\" the template string into a sql string.\n  query.sql # SELECT * FROM users WHERE id = $1 LIMIT 1;\n\n  # It also remembered the params (as symbols).\n  query.params # [:id]\n```\n\nNow that our template string has been converted into sql that our database\nunderstands, we can execute it. To do so we send our query object\n`#execute(conn, args)`.\n\nThe first argument, `conn`, is expected to be a `PG::Connection`.\nThe second argument is typically a `Hash`,\nthough you can pass it custom objects that implement `#values_at` (quack quack).\n\nThis means that `#execute` knows how to put our args in order\nand then delegate the execution to the connection. The return values are the\nsame as using the `pg` gem directly: `PG::Result` on success, and\non a failure it raises `PG::Error`.\n\nYou're probably thinking this is a little inconvenient, having to pass the conn\nin each time. But don't worry, this is handled for you by the `QuerySet` class.\n\nThe QuerySet class is the top level of the library, and is basically a\nfactory for your query objects. It is responsible for:\n\n* Holding a reference to the database connection.\n* Dealing with the file system.\n* Memoizing query objects (not the results, just the compiled templates).\n* Delegating execute to the the appropriate query object.\n\n```ruby\n  conn = PG.connection.open(ENV['pg'])\n\n  # Construct a QuerySet by giving it a reference to your connection\n  # and also a path where it can find your query templates.\n  # Notice the `%s` in the path, it's super important.\n  # When we call methods on our query set, we will send it the file name\n  # of our query. This file name serves as both the cache key for a query\n  # an it's location on disk.\n  query_set = QuerySet.new(conn, './path/to/queries/%s.sql')\n\n  # To execute a query located in the directory we configured, we send it\n  # '#execute'.\n  query_set.execute('users/by_id', id: id)\n\n  # This is the meat of the entire library. The first thing the execute method\n  # does is check the cache to see if a query object exists for the file\n  # name we gave it. If it does not exist, it creates one by giving QuerySet::Query\n  # the template string it finds on disk. Once the template is compiled, we\n  # get to hop back on the train as if it was a cache hit. On a cache hit,\n  # we send our query object the `#execute` method, passing it the conn we have\n  # a reference to and also the supplied arguments.\n```\n\nCheck out the examples directory and tests to get an even better understand\non how to use QuerySet.\n\n[connascence]: https://www.youtube.com/watch?v=HQXVKHoUQxY\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsirscriptalot%2Fquery_set","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fsirscriptalot%2Fquery_set","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fsirscriptalot%2Fquery_set/lists"}