{"id":20445822,"url":"https://github.com/rapid7/metasploit-concern","last_synced_at":"2025-04-06T02:11:38.052Z","repository":{"id":15597548,"uuid":"18333614","full_name":"rapid7/metasploit-concern","owner":"rapid7","description":"Loads `ActiveSupport::Concern`s from `app/concerns` and and includes them in the appropriate class using `ActiveSupport.on_load(\u003cunderscored_class_name\u003e)`.","archived":false,"fork":false,"pushed_at":"2025-02-13T14:48:53.000Z","size":305,"stargazers_count":4,"open_issues_count":0,"forks_count":13,"subscribers_count":61,"default_branch":"master","last_synced_at":"2025-03-30T01:11:42.498Z","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":"other","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/rapid7.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":"CONTRIBUTING.md","funding":null,"license":"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":"2014-04-01T15:06:48.000Z","updated_at":"2025-02-13T14:48:59.000Z","dependencies_parsed_at":"2024-06-19T00:41:35.669Z","dependency_job_id":"374e1899-2faa-483e-b6e3-9facb01d418f","html_url":"https://github.com/rapid7/metasploit-concern","commit_stats":{"total_commits":194,"total_committers":22,"mean_commits":8.818181818181818,"dds":0.5824742268041236,"last_synced_commit":"e4b0ca46bf817e7b5fc525f1ea3d6d5e48e4b4c0"},"previous_names":[],"tags_count":37,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rapid7%2Fmetasploit-concern","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rapid7%2Fmetasploit-concern/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rapid7%2Fmetasploit-concern/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/rapid7%2Fmetasploit-concern/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/rapid7","download_url":"https://codeload.github.com/rapid7/metasploit-concern/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":247423515,"owners_count":20936626,"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-11-15T10:14:22.599Z","updated_at":"2025-04-06T02:11:38.028Z","avatar_url":"https://github.com/rapid7.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Metasploit::Concern [![Build Status](https://github.com/rapid7/metasploit-concern/actions/workflows/verify.yml/badge.svg)](https://github.com/rapid7/metasploit-concern/actions/workflows/verify.yml)[![Code Climate](https://codeclimate.com/github/rapid7/metasploit-concern.png)](https://codeclimate.com/github/rapid7/metasploit-concern)[![Dependency Status](https://gemnasium.com/rapid7/metasploit-concern.png)](https://gemnasium.com/rapid7/metasploit-concern)[![Gem Version](https://badge.fury.io/rb/metasploit-concern.png)](http://badge.fury.io/rb/metasploit-concern)\n\n`Metasploit::Concern` allows you to define concerns in `app/concerns` that will automatically be included in matching classes.  It can be used to automate adding new associations to `ActiveRecord::Base` models from gems and `Rails::Engine`s.\n\n## Versioning\n\n`Metasploit::Concern` is versioned using [semantic versioning 2.0](http://semver.org/spec/v2.0.0.html).  Each branch should set `Metasploit::Concern::Version::PRERELEASE` to the branch SUMMARY, while master should have no `PRERELEASE` and the `PRERELEASE` section of `Metasploit::Concern::VERSION` does not exist.\n\n## Installation\n\nAdd this line to your application's `Gemfile`:\n\n    gem 'metasploit-concern'\n\nAnd then execute:\n\n    $ bundle\n    \n**This gem's `Rails::Engine` is not required automatically.** You'll need to also add the following to your `config/application.rb`:\n\n    require 'metasploit/concern/engine'\n\nOr install it yourself as:\n\n    $ gem install metasploit-concern\n    \n\n\n## Supporting concerns\n\n`Metasploit::Concern` support is a cooperative effort that involves the classes from the gem being setup to allow downstream dependents to inject concerns.\n\nIn order for `Metasploit::Concern` to load concerns for `app/concerns`, the class on which `Module#include` will be called must support `ActiveSupport` load hooks with a specific name format.  You can run the appropriate load hooks at the bottom of the class body:\n\n    class GemNamespace::GemClass \u003c ActiveRecord::Base\n      # class body\n\n      Metasploit::Concern.run(self)\n    end\n\n### Testing\n\nInclude the shared examples from `Metasploit::Concern` in your `spec_helper.rb`:\n\n\n    Dir[Metasploit::Concern.root.join(\"spec/support/**/*.rb\")].each do |f|\n      require f\n    end\n\n\nTo verify that your classes call `Metasploit::Concern.run` correctly, you can use the `'Metasploit::Concern.run'` shared example:\n\n    # spec/app/models/gem_namespace/gem_class_spec.rb\n    describe GemNamespace::GemClass do\n      it_should_behave_like 'Metasploit::Concern.run'\n    end\n\n## Using concerns\n\nConcerns are added in downstream dependents of gems that support concerns.  These dependents can be a `Rails::Engines` or full `Rails::Application`.\n\n### app/concerns\n\n#### Rails::Application\n\nAdd this line to your application's `config/application.rb`:\n\n    config.paths.add 'app/concerns', autoload: true\n\nOr if you're already using `config.autoload_paths +=`:\n\n    config.autoload_paths += config.root.join('app', 'concerns')\n\n#### Rails::Engine\n\nAdd this line to your engine's class body:\n\n    module EngineNamespace\n      class Engine \u003c ::Rails::Engine\n        config.paths.add 'app/concerns', autoload: true\n      end\n    end\n\n### Concerns\n\nDefine concerns for class under `app/concerns` by creating files under directories named after the namespaced class names:\n\n    $ mkdir -p app/concerns/gem_namespace/gem_class\n    $ edit app/concerns/gem_namespace/gem_class/my_concern.rb\n\nInside each concern, make sure the `module` name matches file name:\n\n    module GemNamespace::GemClass::MyConcern\n      ...\n    end\n\nEach concern is included using `Module#include` which means that the `included` method on each concern will be called.  Using `ActiveSupport::Concern` allow you to add new associations and or validations to `ActiveRecord::Base` subclass:\n\n    module GemNamespace::GemClass::MyConcern\n      extend ActiveSupport::Concern\n\n      included do\n        #\n        # Associations\n        #\n\n        # @!attribute widgets\n        #  Widgets for this gem_class.\n        #\n        #  @return [ActiveRecord::Relation\u003cWidget\u003e]\n        has_many :widgets,\n                 class_name: 'Widget',\n                 dependent: :destroy,\n                 inverse_of :gem_namespace_gem_class\n      end\n    end\n    \n### initializers\n\n`Metasploit::Concern::Engine` defines the `'metasploit_concern.load_concerns'` initializer, which sets up `ActiveSupport.on_load` callbacks.  If you depend on a feature from a concern in your initializers, it is best to have the initializer declare that it needs to be run after `'metasploit_concern.load_concerns`:\n\n    initializer 'application_or_engine_namespace.depends_on_concerns', after: 'metasploit_concern.load_concerns' do\n      if GemNamespace::GemClass.primary.widgets.empty?\n        logger.info('No Widgets on the primary GemClass!')\n      end\n    end\n\n## Contributing\n\nSee [CONTRIBUTING.md](CONTRIBUTING.md)\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frapid7%2Fmetasploit-concern","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Frapid7%2Fmetasploit-concern","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Frapid7%2Fmetasploit-concern/lists"}