{"id":17918214,"url":"https://github.com/jcambass/sane_patch","last_synced_at":"2025-03-23T23:31:07.253Z","repository":{"id":56894256,"uuid":"188192169","full_name":"Jcambass/sane_patch","owner":"Jcambass","description":"Making monkey patches sane again","archived":false,"fork":false,"pushed_at":"2021-08-18T12:53:22.000Z","size":814,"stargazers_count":66,"open_issues_count":0,"forks_count":5,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-03-19T00:39:16.282Z","etag":null,"topics":["monkey-patching","patch","ruby","rubygems"],"latest_commit_sha":null,"homepage":"https://joel.am/blog/introducing-sane-patch","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/Jcambass.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2019-05-23T08:22:05.000Z","updated_at":"2025-03-18T14:24:32.000Z","dependencies_parsed_at":"2022-08-20T16:10:32.652Z","dependency_job_id":null,"html_url":"https://github.com/Jcambass/sane_patch","commit_stats":null,"previous_names":[],"tags_count":3,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jcambass%2Fsane_patch","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jcambass%2Fsane_patch/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jcambass%2Fsane_patch/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/Jcambass%2Fsane_patch/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/Jcambass","download_url":"https://codeload.github.com/Jcambass/sane_patch/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":245186572,"owners_count":20574551,"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":["monkey-patching","patch","ruby","rubygems"],"created_at":"2024-10-28T20:10:22.177Z","updated_at":"2025-03-23T23:31:06.798Z","avatar_url":"https://github.com/Jcambass.png","language":"Ruby","readme":"\u003cimg src=\"https://raw.githubusercontent.com/Jcambass/sane_patch/master/assets/logo.png\" width=\"100\" height=\"100\"\u003e\n\n# SanePatch [![Gem Version](https://badge.fury.io/rb/sane_patch.svg)](https://badge.fury.io/rb/sane_patch) ![Gem Downloads](https://img.shields.io/gem/dt/sane_patch) [![Build Status](https://travis-ci.com/Jcambass/sane_patch.svg?branch=master)](https://travis-ci.com/Jcambass/sane_patch) \n\nSanePatch is a simple and non intrusive helper that aims to make monkey patching a little bit safer.\n\nIt achieves this by only applying your patches to a specific version of a gem and raising a exception if the gem version changed. This means that you will always double check that your patches still work after upgrading gems. No surprises anymore!\n\n## But wait.. Isn't monkey patching bad?\n\nAs with many things in life there is no pure good or bad. Monkey patching can be dangerous in certain situations and should be avoided sometimes but there are reasons to use it.\n\nGood reasons to monkey patch a gem could be:\n- Fixing a bug in a broken gem until a new version of it is released.\n- Performance optimizing a specific method of a gem that is used in a hot code path.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'sane_patch', '~\u003e 1.0'\n```\n\nAnd then execute:\n\n    $ bundle\n\n## Usage\n\nThe usage of SanePatch is straight forward:\n\n\n```ruby\nSanePatch.patch('\u003cgem name\u003e', '\u003ccurrent gem version\u003e') do\n  # Apply your patches here the same way as usual.\nend\n```\n\nA more specific example:\n\n```ruby\nGreeter.greet # =\u003e 'Hello'\n\n# Let's patch the `Greeter.greet` method to output 'Hello Folks'\nmodule GreeterPatch\n  def greet\n    \"#{super} Folks\"\n  end\nend\n\n# We currently have version 1.1.0 of the greeter gem\nSanePatch.patch('greeter', '1.1.0') do\n  Greeter.prepend(GreeterPatch)\nend\n\nGreeter.greet # =\u003e 'Hello Folks'\n```\n\nIf somebody updates the gem version the patch will raise as soon as its code path is executed:\n```\nSanePatch::Errors::IncompatibleVersion:\n  It looks like the greeter gem was upgraded.\n  There are patches in place that need to be verified.\n  Make sure that the patch at initializers/greeter_patch.rb:8 is still needed and working.\n```\n\nSetting the `raise_error` keyword argument to `false` will skip the execution of the block but will not raise an error.  (The default value for the keyword is `true`.)\n\n### Complex version constraints\n\nSanePatch supports all [version constraints](http://docs.seattlerb.org/rubygems/Gem/Requirement.html) you know and love from RubyGems.\n\n```ruby\nSanePatch.patch('greeter', '~\u003e 1.1.0') { # your patch }\nSanePatch.patch('greeter', '\u003e 1.1.0') { # your patch }\nSanePatch.patch('greeter', '\u003c 1.1.0') { # your patch }\n```\n\nIt even supports version ranges based on multiple constraints:\n\n```ruby\nSanePatch.patch('greeter', '\u003e 1.0.0', '\u003c 1.1.0') { # your patch }\n```\n\nThis is especially useful if you patch a bug where you know the affected gem versions.\n\n### Providing additional information\n\nIf you patch a known bug in a gem it might be useful to provide additional information why the patch is needed and when it can be removed.\n\n```ruby\nGreeter.silence # =\u003e nil\n\nmodule GreeterPatch\n  def silence\n    ''\n  end\nend\n\ndetails = \u003c\u003c-MSG\n  The `silence` method should output an empty string rather than nil.\n  This is a known issue and will be fixed in the next release.\n  See: https://github.com/Jcambass/greeter/issues/45\nMSG\n\nSanePatch.patch('greeter', '1.1.0', details: details) do\n  Greeter.prepend(GreeterPatch)\nend\n\nGreeter.silence # =\u003e ''\n```\n\nThe additionally provided details will also show up in the exception message.\n\n```\nSanePatch::Errors::IncompatibleVersion:\n  It looks like the greeter gem was upgraded.\n  There are patches in place that need to be verified.\n  Make sure that the patch at initializers/greeter_patch.rb:8 is still needed and working.\n  Details:\n  The `silence` method should output an empty string rather than nil.\n  This is a known issue and will be fixed in the next release.\n  See: https://github.com/Jcambass/greeter/issues/45\n```\n\n### Logging support\n\nThe `logger` keyword argument can be used to supply a logger instance.  SanePatch will pass the exception message to that object's `#warn` method when the version constraint is not satisfied:\n\n```ruby\nSanePatch.patch('greeter', '1.1.0', logger: Logger.new(STDOUT)) { # your patch }\n```\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/Jcambass/sane_patch. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [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 [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the SanePatch project’s codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/Jcambass/sane_patch/blob/master/CODE_OF_CONDUCT.md).\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjcambass%2Fsane_patch","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjcambass%2Fsane_patch","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjcambass%2Fsane_patch/lists"}