{"id":20461016,"url":"https://github.com/ericgj/roth","last_synced_at":"2026-04-21T19:02:23.575Z","repository":{"id":6262930,"uuid":"7495953","full_name":"ericgj/roth","owner":"ericgj","description":null,"archived":false,"fork":false,"pushed_at":"2013-01-08T05:12:37.000Z","size":120,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-12-04T07:34:25.791Z","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":null,"status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/ericgj.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":null,"code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2013-01-08T05:09:32.000Z","updated_at":"2014-05-13T04:40:33.000Z","dependencies_parsed_at":"2022-09-16T14:41:23.102Z","dependency_job_id":null,"html_url":"https://github.com/ericgj/roth","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"purl":"pkg:github/ericgj/roth","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericgj%2Froth","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericgj%2Froth/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericgj%2Froth/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericgj%2Froth/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ericgj","download_url":"https://codeload.github.com/ericgj/roth/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ericgj%2Froth/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32105868,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-04-21T11:25:29.218Z","status":"ssl_error","status_checked_at":"2026-04-21T11:25:28.499Z","response_time":128,"last_error":"SSL_connect returned=1 errno=0 peeraddr=140.82.121.5:443 state=error: unexpected eof while reading","robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":false,"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":[],"created_at":"2024-11-15T12:22:51.624Z","updated_at":"2026-04-21T19:02:23.530Z","avatar_url":"https://github.com/ericgj.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"## Reimplementing Thor::Actions\n\n### A work in progress\n\nThis library is an extraction _and reimplementation_ of Thor's file actions and\n'shell' -- arguably the most useful functionality that Thor provides, most \nvisibly in Rails generators.\n\n### Why is this needed\n\nThe functionality provided by [Thor::Actions][thor] has no deep dependency on Thor.\nThere is no reason to have to subclass Thor (or even install thor at all) in \norder to use it. That was my first thought: given I don't want to use Thor, but \nwant to do generator-y things, how simple would it be to just extract it?\n\nAs it turns out, it's not too hard. But then... one comes in close range of the\nmoldering cheese that is Thor::Actions. It's only so long you can leave it in\nthe back of the fridge, cutting off bits now and then to save it.\n\nThus, _reimplementation_. I summarize below the main problems.\n\nBut first, how to use it.\n\n### How does the interface differ from Thor::Actions?\n\nThe main difference is that you compose the object that does the actions, \ninstead of mixing in the action methods into your objects.  So\n\n```ruby\nclass FooGenerator \u003c Thor\n  include Thor::Actions\n  \n  attr_accessor :source_root\n  \n  def do_it\n    inside('app') do\n      copy_file 'foo' if yes?('copy foo?')\n    end\n  end\nend\n```\n\nbecomes\n\n```ruby\nclass FooGenerator\n\n  attr_accessor :source_root\n  \n  def gen\n    @gen ||= FileActions.from(source_root)\n  end\n  \n  def do_it\n    gen.inside('app') do\n      gen.copy_file 'foo' if gen.yes?('copy foo?')\n    end\n  end\n```\n\nOf course, you can use delegation to give it the same syntax as before (but \nwithout the mixin headaches).\n\n\n### Main problems with Thor::Actions as currently implemented\n\n1. Action methods are dumped into your application classes (commands)\nas mixins. Also, whether you use one of them or all 21 or so, you get them all\n(how lucky!). This is on top of all the Shell methods which are dumped into\nthe Thor base class.\n\n2. Worse yet, Thor::Actions itself brings with it a bunch of state (options, \ndestination and source directories, etc.) and methods for dealing with that\nstate.\n\n3. The shell keeps a reference to the command and also vice-versa, coupling them\nunnecessarily tightly. \n\n4. The internal division of responsibilities between Thor::Actions and \nparticular actions is not clear and it is leaking encapsulation juice in a number\nof places. It's definitely a smell that both Thor::Actions and individual \nactions make filesystem changes. Archeologically speaking (and it's only \nspeculation here, no I have not mined the depths of git history), it appears the \nold edifice was never torn down completely when certain improvements were \nintroduced.\n\n5. It makes a certain kind of sense to inherit other actions from EmptyDirectory,\nthe simplest case, but overall I think this is a mistake that leads to \nhard-to-follow code.\n\n\n[thor]: https://github.com/wycats/thor/blob/master/lib/thor/actions.rb ","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericgj%2Froth","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fericgj%2Froth","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fericgj%2Froth/lists"}