{"id":17942650,"url":"https://github.com/petercamilleri/safe_clone","last_synced_at":"2025-04-03T13:27:38.504Z","repository":{"id":22751505,"uuid":"26096935","full_name":"PeterCamilleri/safe_clone","owner":"PeterCamilleri","description":"A safe, fast, exception free clone method that demonstrates the use of inheritance and safe monkey patching.","archived":false,"fork":false,"pushed_at":"2021-05-19T19:22:22.000Z","size":21,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2024-04-25T10:01:00.917Z","etag":null,"topics":["clone","monkey-patching","ruby","ruby-gem","safe","utility-library"],"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/PeterCamilleri.png","metadata":{"files":{"readme":"README.md","changelog":null,"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":"2014-11-02T23:49:20.000Z","updated_at":"2023-03-05T04:20:47.000Z","dependencies_parsed_at":"2022-07-27T03:32:07.114Z","dependency_job_id":null,"html_url":"https://github.com/PeterCamilleri/safe_clone","commit_stats":null,"previous_names":[],"tags_count":7,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterCamilleri%2Fsafe_clone","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterCamilleri%2Fsafe_clone/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterCamilleri%2Fsafe_clone/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PeterCamilleri%2Fsafe_clone/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PeterCamilleri","download_url":"https://codeload.github.com/PeterCamilleri/safe_clone/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247008779,"owners_count":20868423,"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":["clone","monkey-patching","ruby","ruby-gem","safe","utility-library"],"created_at":"2024-10-29T03:06:38.855Z","updated_at":"2025-04-03T13:27:38.485Z","avatar_url":"https://github.com/PeterCamilleri.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# SafeClone\n\nThis tiny gem implements a version of clone called safe\\_clone. In Ruby, if an\nattempt is made to clone an immutable data item like a number, an error occurs.\nThe justification for this uncharacteristic strictness is not at all clear, but\nit does mean that the clone operation must be applied with great care.\n\nUnlike the standard clone method, the safe\\_clone method does not throw an\nexception when it sees un-clonable value objects like 42 or true. These values\nsimply return themselves. This is deemed correct because those types of objects\nare immutable and do not need to be duped. Instead of raising an exception,\nthe code returns the immutable object instead.\n\nOn a note about performance, this gem does not just rescue the exceptions\nnormally generated by clone, it prevents them from occurring and wasting time\nin the first place.\n\nFinally, this gem does not monkey patch the behavior of the clone method.\nModifying such a crucial method was considered too risky. Instead, the\nsafe_clone method is introduced. This is done to reduce the possibility of\nbreaking existing code that often occurs when monkey patching goes too far.\n\n## Family Overview\n\nThis gem is a member of a family of four gems that all provide data copying\nservices in a safe, easy to use format. The following outlines the available\ngems and how to chose from among them.\n\nDepth / Action | Need to copy all. | Need to copy data only.\n---------------|------------------------------|------------\nNeed a shallow copy | require 'safe\\_clone' | require 'safe\\_dup'\nNeed a full copy    | require 'full\\_clone' | require 'full\\_dup'\n\n\u003cbr\u003e**Notes**\n* Since none of these gems override the default clone and dup\nmethods, the default behaviors remain available. Further, if multiple,\ndiffering requirements exists, more than one family member gem may be\nemployed in the same project without fear of conflict.\n* If multiple family gems are employed, they will each need to be installed and\nrequired into the application. See below for details.\n* Meta-data attributes include the frozen status and singleton methods. However\nthe tainted status is always copied.\n\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n    gem 'safe_clone'\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install safe_clone\n\nThe safe_dup gem is at: ( https://rubygems.org/gems/safe_dup )\n\u003cbr\u003eThe safe_clone gem is at: ( https://rubygems.org/gems/safe_clone )\n\u003cbr\u003eThe full_dup gem is at: ( https://rubygems.org/gems/full_dup )\n\u003cbr\u003eThe full_clone gem is at: ( https://rubygems.org/gems/full_clone )\n\n## Usage\n\n    require 'safe_clone'\n\nthen, in those places where regular clone was problematic, use:\n\n    foo = my_object.safe_clone\n\ninstead of\n\n    begin\n      foo = my_object.clone\n    rescue TypeError\n      foo = my_object\n    end\n\nIt is actually pretty easy to determine where safe\\_clone needs to be used. It's\nthose places where the clone method is generating unwanted exceptions.\n\n## Demo\n\nA test bed for experimenting with the safe_clone gem is available as a rake task:\n\n    $ rake console\n\n## Performance\nA reasonable question to raise is \"How does safe clone compare with just\ncatching the exception and handling it?\" The benchmark sets a a realistic\nscenario where an array (whose contents may be varied) is having its\n_contents_ cloned. The benchmarking code follows:\n\n```ruby\nrequire \"benchmark/ips\"\nrequire 'safe_clone'\n\nclass Array\n  def use_clone\n    self.map do |element|\n      begin\n        element.clone\n      rescue TypeError\n        element\n      end\n    end\n  end\n\n  def use_safe_clone\n    self.map {|element| element.safe_clone }\n  end\nend\n\nX = [\"Test\", :test, 43, true, nil, false]\n\nBenchmark.ips do |x|\n  x.report(\"Clone with standard clone method\") { X.use_clone }\n  x.report(\"Clone with the safe clone method\") { X.use_safe_clone }\n  x.compare!\nend\n```\n\n#### Results: ruby 1.9.3p484 (2013-11-22) [i386-mingw32]\n    C:\\Sites\\safe_clone\u003eruby bench\\bench.rb\n    Warming up --------------------------------------\n    Clone with standard clone method\n                             1.247k i/100ms\n    Clone with the safe clone method\n                            35.027k i/100ms\n    Calculating -------------------------------------\n    Clone with standard clone method\n                             12.957k (± 5.8%) i/s -     64.844k\n    Clone with the safe clone method\n                            534.740k (± 8.9%) i/s -      2.662M\n\n    Comparison:\n    Clone with the safe clone method:   534740.1 i/s\n    Clone with standard clone method:    12956.6 i/s - 41.27x slower\n\n#### Results: ruby 2.1.6p336 (2015-04-13 revision 50298) [i386-mingw32]\n    C:\\Sites\\safe_clone\u003eruby bench\\bench.rb\n    Warming up --------------------------------------\n    Clone with standard clone method\n                             4.945k i/100ms\n    Clone with the safe clone method\n                            38.109k i/100ms\n    Calculating -------------------------------------\n    Clone with standard clone method\n                             54.491k (± 7.3%) i/s -    271.975k\n    Clone with the safe clone method\n                            569.236k (±10.2%) i/s -      2.820M\n\n    Comparison:\n    Clone with the safe clone method:   569236.4 i/s\n    Clone with standard clone method:    54491.3 i/s - 10.45x slower\n\n#### Results: ruby 2.2.3p173 (2015-08-18 revision 51636) [i386-cygwin]\n    Peter Camilleri@NCC1701G /cygdrive/c/sites/safe_clone\n    $ ruby bench/bench.rb\n    Warming up --------------------------------------\n    Clone with standard clone method\n                             3.698k i/100ms\n    Clone with the safe clone method\n                            28.999k i/100ms\n    Calculating -------------------------------------\n    Clone with standard clone method\n                             40.076k (± 5.1%) i/s -    203.390k\n    Clone with the safe clone method\n                            481.524k (±10.0%) i/s -      2.407M\n\n    Comparison:\n    Clone with the safe clone method:   481524.1 i/s\n    Clone with standard clone method:    40075.6 i/s - 12.02x slower\n\n\nOverall: Shorter code  _and_ faster. Winner, winner, chicken dinner!\n\n## Contributing\n\n#### Plan A\n\n1. Fork it ( https://github.com/PeterCamilleri/safe_clone/fork )\n2. Create your feature branch (`git checkout -b my-new-feature`)\n3. Commit your changes (`git commit -am 'Add some feature'`)\n4. Push to the branch (`git push origin my-new-feature`)\n5. Create a new Pull Request\n\n#### Plan B\n\nGo to the GitHub repository and raise an issue calling attention to some\naspect that could use some TLC or a suggestion or an idea.\n\n## License\n\nThe gem is available as open source under the terms of the\n[MIT License](./LICENSE.txt).\n\n## Code of Conduct\n\nEveryone interacting in the fully_freeze project’s codebases, issue trackers,\nchat rooms and mailing lists is expected to follow the\n[code of conduct](./CODE_OF_CONDUCT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpetercamilleri%2Fsafe_clone","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpetercamilleri%2Fsafe_clone","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpetercamilleri%2Fsafe_clone/lists"}