{"id":22981047,"url":"https://github.com/rubyworks/reusing","last_synced_at":"2025-08-13T17:33:53.096Z","repository":{"id":15758933,"uuid":"18497715","full_name":"rubyworks/reusing","owner":"rubyworks","description":"Transform core extensions into refinements","archived":false,"fork":false,"pushed_at":"2015-02-12T19:37:41.000Z","size":168,"stargazers_count":4,"open_issues_count":0,"forks_count":0,"subscribers_count":5,"default_branch":"master","last_synced_at":"2024-04-25T11:21:53.859Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":null,"language":"Ruby","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"bsd-2-clause","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rubyworks.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2014-04-06T19:44:52.000Z","updated_at":"2016-12-10T22:30:38.000Z","dependencies_parsed_at":"2022-09-24T03:51:48.586Z","dependency_job_id":null,"html_url":"https://github.com/rubyworks/reusing","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubyworks%2Freusing","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubyworks%2Freusing/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubyworks%2Freusing/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rubyworks%2Freusing/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rubyworks","download_url":"https://codeload.github.com/rubyworks/reusing/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":229773540,"owners_count":18122031,"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":[],"created_at":"2024-12-15T01:46:50.954Z","updated_at":"2024-12-15T01:46:51.547Z","avatar_url":"https://github.com/rubyworks.png","language":"Ruby","readme":"# Reusing\n\n## Short Story\n\nReusing allows for the use of refinements directly from an extension file.\n\n```ruby\nrequire 'reusing'\n\nusing 'some_extension_script'\n```\n\n## Long Story\n\nRuby introduced refinements in version 2.0. Refinements are essentially\na safe alternative to monkey-patching. Unfortunately, the degree to which\nthe syntax of refinements differs from writing traditional class extensions\nis a sever hinderence to their adoption. Traditionally, if you wanted to add\na method to the String class, for instance, you simply open the class\nand define the method.\n\n```ruby\nclass String\n  def some_method\n    ...\n  end\nend\n```\n\nAnd that's it. You can put this code in a file and require it as needed.\nRefinements, on the other hand, have much more *boiler-plate*. The\nabove would have to be written:\n\n```ruby\nmodule SomeModule\n  refine String do\n    def some_method\n      ...\n    end\n  end\nend\n\nusing SomeModule\n```\n\nThe top portion can be put in an extension file too, but the `using SomeModule` part\nwill have to be reissued in every file the refinement is needed.\n\nFor a one-off, this isn't a big deal. But for a method library such as\nRuby Facets, this has huge implications. In fact, Facets does not yet support\nrefinements precisely becuase of this issue. To do so would require maintaining\na second copy of every method in refinement format. While doable, it is obviously\nnot DRY, and quite simply too much a pain in the ass to bother.\n\nSo I consder what, if anything, could be done about this problem. And the idea of\noverriding the `using` method to accept a library file name was hatched.\nWith it, most extension scripts can be readily used as-is, without all\nthe boiler-plate. Usage is pretty simple. Let's say the example given\nabove is in a library file called `some_method.rb`, then we can do:\n\n```ruby\nrequire 'reusing'\n\nusing 'some_method'\n```\n\nThe new using method will find the file, read it in, perform a transformation\nconverting `class String` into `refine String do` and wrap it all in a module\nwhich it then passed to the original `using` method (which has been aliased\nas `reusing`, btw, hence the name of this library).\n\n\n## Caveats\n\nUnfortunately the implementation of Reusing is necessarily a bit of a hack. Although\nit works fine for basic extensions there are complications if, for instance,\nthe script requires another extension script. While the scripts extensions will become\nrefinements, the further requirements will not. There may also be issues if the\nextenesion defines meta-methods (i.e. class level extensions).\n\n\n## Thoughts\n\nIf Ruby Team were to take this issue to heat, than probably the ideal solution would\nhave refinement syntax use normal `class` and `module` keywords, instead of the\nspecial `refine` clause.\n\n```ruby\nmodule M\n  class String\n    def important!\n      self + \"!\"\n    end\n  end\nend\n\n# refinement\nusing M::*\n```\n\nIn conjunction with this is should be possible to monkey patch with the same code as well.\n\n```ruby\n# core extension\npatch M::*\n```\n\nIn this way the both techniques could be used via the same code, while still being modular.\nBut that is a significant change to Ruby itself, and ultimately falls to Matz to decide.\n\n\n## Copyrights\n\nCopyright (c) 2014 Rubyworks (BSD-2 License)\n\nSee LICENSE.txt for details.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubyworks%2Freusing","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frubyworks%2Freusing","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frubyworks%2Freusing/lists"}