{"id":22972961,"url":"https://github.com/marcinruszkiewicz/where_chain","last_synced_at":"2025-08-04T03:32:42.168Z","repository":{"id":30835967,"uuid":"125647844","full_name":"marcinruszkiewicz/where_chain","owner":"marcinruszkiewicz","description":"WhereChain - don't write Post.where('comments \u003e ?', 5), write Post.where.gt(comments: 5) instead!","archived":false,"fork":false,"pushed_at":"2024-10-15T23:42:32.000Z","size":104,"stargazers_count":45,"open_issues_count":3,"forks_count":4,"subscribers_count":3,"default_branch":"master","last_synced_at":"2025-07-24T07:18:59.109Z","etag":null,"topics":["activerecord","hacktoberfest","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/marcinruszkiewicz.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"MIT-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":"2018-03-17T16:22:16.000Z","updated_at":"2024-11-22T01:41:25.000Z","dependencies_parsed_at":"2024-08-06T13:33:19.454Z","dependency_job_id":"b7df0464-923e-438e-82f8-d4f25fd39dfe","html_url":"https://github.com/marcinruszkiewicz/where_chain","commit_stats":{"total_commits":64,"total_committers":4,"mean_commits":16.0,"dds":0.09375,"last_synced_commit":"49221d0a2bb4c1225e57cfc76ded879f5f111015"},"previous_names":[],"tags_count":11,"template":false,"template_full_name":null,"purl":"pkg:github/marcinruszkiewicz/where_chain","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcinruszkiewicz%2Fwhere_chain","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcinruszkiewicz%2Fwhere_chain/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcinruszkiewicz%2Fwhere_chain/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcinruszkiewicz%2Fwhere_chain/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/marcinruszkiewicz","download_url":"https://codeload.github.com/marcinruszkiewicz/where_chain/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/marcinruszkiewicz%2Fwhere_chain/sbom","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":268215475,"owners_count":24214361,"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","status":"online","status_checked_at":"2025-08-01T02:00:08.611Z","response_time":67,"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":["activerecord","hacktoberfest","rails","ruby"],"created_at":"2024-12-14T23:36:47.104Z","updated_at":"2025-08-04T03:32:42.143Z","avatar_url":"https://github.com/marcinruszkiewicz.png","language":"Ruby","readme":"[![Gem Version](https://badge.fury.io/rb/where_chain.svg)](https://badge.fury.io/rb/where_chain) ![TravisCI](https://github.com/marcinruszkiewicz/where_chain/actions/workflows/rspec.yml/badge.svg)\n\n# WhereChain\n\nIn Rails, we usually use Active Record, which allows us to escape from writing SQL code like this `SELECT * FROM posts WHERE posts.name = 'Foo'` and allows us to write `Post.where(name: 'Foo')` instead. However, this has always been limited to matching equality, so you still have to write `Post.where('comments \u003e ?', 5)` to get Posts that have more than 5 comments.\n\nIn the older versions, you also had to write `Post.where('name IS NOT null')` to do a negation. Rails 4.0 added a class called `WhereChain` that added some [new possibilities](https://github.com/rails/rails/commit/de75af7acc5c05c708443de40e78965925165217), one of which was a `not` method. The proper way to write  became `Post.where.not(name: nil)` instead.\n\nWithin the same commit there were also two new methods that [didn't survive to the release of Rails 4.0](https://github.com/rails/rails/commit/8d02afeaee8993bd0fde69687fdd9bf30921e805) - `.like` and `.not_like`. As you can read in this commit discussion, there has been work made to bring them back, like the [activerecord-like](https://github.com/ReneB/activerecord-like) gem or [Squeel](https://github.com/activerecord-hackery/squeel), but these have their own problems - activerecord-like only adds `.like` and `.not_like` back and the latest version is locked to Active Record 5; and Squeel provides a whole new query DSL, which not everyone will like. There was actually a pull request adding `.gt` and other [inequality methods](https://github.com/rails/rails/pull/8453), which was closed even faster than the first one.\n\nThis gem brings these two methods back and extends WhereChain with additional methods: `.gt`, `.gte`, `.lt` and `.lte`, so that by using it you can replace the SQL strings like `Post.where('comments \u003e 5')` with `Post.where.gt(comments: 5)`.\n\nWhereChain depends on the Active Record gem in a version higher than 4.2. The gem is tested on the latest Ruby and all current Rails versions - 5.2, 6.0, 6.1, and 7.0. If you have an older version, it will probably still work, because Active Record doesn't really change all that often, but Rails versions older than 5.2 depend on old and unsupported Ruby versions, so I'm not making any promises there.\n\n## Usage\n\nSome examples of using the gem and what can be replaced with it:\n\n| Rails SQL string | with WhereChain |\n|------------|-----------------|\n|`Post.where('comments \u003e ?', 5)` | `Post.where.gt(comments: 5)` |\n|`Post.where('comments \u003e= ?', 5)` | `Post.where.gte(comments: 5)` |\n|`Post.where('comments \u003c ?', 5)` | `Post.where.lt(comments: 5)` |\n|`Post.where('comments \u003c= ?', 5)` | `Post.where.lte(comments: 5)` |\n|`Post.where('name LIKE ?', \"%foo%\")` | `Post.where.like(name: \"%foo%\")` |\n|`Post.where('name NOT LIKE ?', \"%foo%\")` | `Post.where.unlike(name: \"%foo%\")` |\n|`Post.where('comments \u003e ? AND shares \u003e ?', 5, 10)` | `Post.where.gt({ comments: 5, shares: 10 })` |\n|`Post.where('comments \u003e ? OR shares \u003e ?', 5, 10)` | `Post.where.gt(comments: 5).or(Post.where.gt(shares: 10))` |\n\nYou can now also chain the methods in your Active Record queries:\n\n```ruby\nPost.where.not.gt(comments: 5).where.like(name: '%foo%')\n```\n\nThis, however, will **NOT** work at all:\n\n```ruby\nPost.gt(comments: 5).like(name: '%foo%')\nPost.where.gt(comments: 5).lt(comments: 10)\n```\n\nYou need to prepend each of the new methods with either `.where` or `.where.not` for them to work.\n\nAll the methods accept a Hash attribute and can compare all proper types as values, except Arrays and Hashes. These will **not** work and will raise an ArgumentError exception:\n\n```ruby\nPost.where.gt(comments: [1, 2, 3])\nPost.where.gt(comments: { bad: :thing })\n\nArgumentError: The value passed to this method should be a valid type.\n\nPost.where.gt('comments \u003e ?', 5)\nPost.where.gt([{ number: 5 }, 'name \u003e ?'], 'abc')\n\nArgumentError: This method requires a Hash as an argument.\n```\n\n## Installation\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'where_chain'\n```\n\nAnd then execute:\n```bash\n$ bundle\n```\n\nOr install it yourself as:\n```bash\n$ gem install where_chain\n```\n\n## Contributing\n\n1. Fork it\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Added some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Make sure all the tests pass on all versions\n6. Create new Pull Request\n\n## Testing the code\n\nBefore running any test, you should finish installing the appraised gems:\n\n```bash\n$ bundle exec appraisal install\n```\n\nRunning all the tests for all Rails version targets:\n\n```bash\n$ bundle exec appraisal rspec\n```\n\nRunning tests for a specific version:\n\n```bash\n$ bundle exec appraisal 7.0 rspec\n```\n\nYou can see all the targets to use instead of `7.0` in the `Appraisals` file.\n\n## License\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcinruszkiewicz%2Fwhere_chain","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fmarcinruszkiewicz%2Fwhere_chain","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fmarcinruszkiewicz%2Fwhere_chain/lists"}