{"id":20127275,"url":"https://github.com/ama-team/ruby-entity-mapper","last_synced_at":"2025-09-07T02:34:08.480Z","repository":{"id":59150552,"uuid":"96459912","full_name":"ama-team/ruby-entity-mapper","owner":"ama-team","description":"When there's not enough Java in your Ruby","archived":false,"fork":false,"pushed_at":"2017-08-08T20:36:52.000Z","size":286,"stargazers_count":0,"open_issues_count":12,"forks_count":0,"subscribers_count":1,"default_branch":"master","last_synced_at":"2025-08-15T21:36:54.058Z","etag":null,"topics":["entity","mapper","ruby"],"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/ama-team.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":null,"funding":null,"license":"LICENSE","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2017-07-06T18:22:47.000Z","updated_at":"2017-08-05T05:02:55.000Z","dependencies_parsed_at":"2022-09-13T10:50:19.397Z","dependency_job_id":null,"html_url":"https://github.com/ama-team/ruby-entity-mapper","commit_stats":null,"previous_names":[],"tags_count":5,"template":false,"template_full_name":null,"purl":"pkg:github/ama-team/ruby-entity-mapper","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ama-team%2Fruby-entity-mapper","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ama-team%2Fruby-entity-mapper/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ama-team%2Fruby-entity-mapper/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ama-team%2Fruby-entity-mapper/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/ama-team","download_url":"https://codeload.github.com/ama-team/ruby-entity-mapper/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/ama-team%2Fruby-entity-mapper/sbom","scorecard":{"id":188024,"data":{"date":"2025-08-11","repo":{"name":"github.com/ama-team/ruby-entity-mapper","commit":"66acb10f97b9e0d05bc3a40ea17ceb3bad6c6a51"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":3,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/30 approved changesets -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project requires human code review before pull requests (aka merge requests) are merged.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#code-review"}},{"name":"Dangerous-Workflow","score":-1,"reason":"no workflows found","details":null,"documentation":{"short":"Determines if the project's GitHub Action workflows avoid dangerous patterns.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#dangerous-workflow"}},{"name":"Maintained","score":0,"reason":"0 commit(s) and 0 issue activity found in the last 90 days -- score normalized to 0","details":null,"documentation":{"short":"Determines if the project is \"actively maintained\".","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#maintained"}},{"name":"SAST","score":0,"reason":"no SAST tool detected","details":["Warn: no pull requests merged into dev branch"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Packaging","score":-1,"reason":"packaging workflow not detected","details":["Warn: no GitHub/GitLab publishing workflow detected."],"documentation":{"short":"Determines if the project is published as a package that others can easily download, install, easily update, and uninstall.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#packaging"}},{"name":"Token-Permissions","score":-1,"reason":"No tokens found","details":null,"documentation":{"short":"Determines if the project's workflows follow the principle of least privilege.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#token-permissions"}},{"name":"Pinned-Dependencies","score":-1,"reason":"no dependencies found","details":null,"documentation":{"short":"Determines if the project has declared and pinned the dependencies of its build process.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#pinned-dependencies"}},{"name":"Binary-Artifacts","score":10,"reason":"no binaries found in the repo","details":null,"documentation":{"short":"Determines if the project has generated executable (binary) artifacts in the source repository.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#binary-artifacts"}},{"name":"CII-Best-Practices","score":0,"reason":"no effort to earn an OpenSSF best practices badge detected","details":null,"documentation":{"short":"Determines if the project has an OpenSSF (formerly CII) Best Practices Badge.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#cii-best-practices"}},{"name":"Security-Policy","score":0,"reason":"security policy file not detected","details":["Warn: no security policy file detected","Warn: no security file to analyze","Warn: no security file to analyze","Warn: no security file to analyze"],"documentation":{"short":"Determines if the project has published a security policy.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#security-policy"}},{"name":"Fuzzing","score":0,"reason":"project is not fuzzed","details":["Warn: no fuzzer integrations found"],"documentation":{"short":"Determines if the project uses fuzzing.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#fuzzing"}},{"name":"Vulnerabilities","score":10,"reason":"0 existing vulnerabilities detected","details":null,"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}},{"name":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE:0","Info: FSF or OSI recognized license: MIT License: LICENSE:0"],"documentation":{"short":"Determines if the project has defined a license.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#license"}},{"name":"Signed-Releases","score":-1,"reason":"no releases found","details":null,"documentation":{"short":"Determines if the project cryptographically signs release artifacts.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#signed-releases"}},{"name":"Branch-Protection","score":0,"reason":"branch protection not enabled on development/release branches","details":["Warn: branch protection not enabled for branch 'master'"],"documentation":{"short":"Determines if the default and release branches are protected with GitHub's branch protection settings.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#branch-protection"}}]},"last_synced_at":"2025-08-16T20:08:44.945Z","repository_id":59150552,"created_at":"2025-08-16T20:08:44.945Z","updated_at":"2025-08-16T20:08:44.945Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":273987647,"owners_count":25202918,"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","status":"online","status_checked_at":"2025-09-07T02:00:09.463Z","response_time":67,"last_error":null,"robots_txt_status":"success","robots_txt_updated_at":"2025-07-24T06:49:26.215Z","robots_txt_url":"https://github.com/robots.txt","online":true,"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":["entity","mapper","ruby"],"created_at":"2024-11-13T20:20:04.021Z","updated_at":"2025-09-07T02:34:08.433Z","avatar_url":"https://github.com/ama-team.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# AMA::Entity::Mapper\n\n[![Gem][shields.gem]][gem]\n[![CircleCI][shields.circleci.master]][circleci.master]\n[![Coveralls][shields.coveralls.master]][coveralls.master]\n[![Code Climate][shields.codeclimate]][codeclimate]\n[![Scrutinizer][shields.scrutinizer.master]][scrutinizer.master]\n\nThis library provides entity mapper - API for seamless \none-class-to-another object conversion. This comes handy in:\n\n- Deserializing complex structures\n- Converting structures to objects that don't have one-to-one relation\n- Retrieving entity information from it's path (e.g. inferring parent hash\nkeys as entity attribute)\n- Deserializing objects that may have different representation (e.g. name\nmay came as both `'John Doe'` or `{first: 'John', last: 'Doe'}`)\n\nYou may find yourself in such a situation when storing data in Chef \nnode attributes, building API clients or storing data in database.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'ama-entity-mapper'\n```\n\nAnd then execute:\n\n    $ bundle\n\nOr install it yourself as:\n\n    $ gem install ama-entity-mapper\n\n## Usage\n\nMapper is created to map data from one type to another. There are no hard \nbounds in this, conversion may be done with any types as long as rough corners\nare handled by corresponding handlers (more on that later). \nLet's start with easy object to hash and vice versa conversion:\n\n```ruby\nrequire 'ama-entity-mapper'\n\nclass User\n  attr_accessor :first_name\n  attr_accessor :last_name\n  attr_accessor :login\nend\n\ndata = { first_name: 'John', last_name: 'Doe', login: 'john-doe' }\n\nuser = AMA::Entity::Mapper.map(data, User)\n\nrestored_data = AMA::Entity::Mapper.map(user, Hash)\n```\n\nThis is, of course, terribly simple; the real power shows up in nested\nstructure processing. Imagine an API that responds with hash of lists:\n\n```yml\nwinners:\n  - first_name: Max\n    last_name: Payne\n    login: mpayne\nlosers:\n  - first_name: Nicole\n    last_name: Horne\n    login: nhorne\n```\n\nEnd developer would like to receive all keys as symbols, and denormalize User\nobjects. To do so, you should specify target type parameters:\n\n```ruby\n# still hash of arrays, but with users now\ndata = AMA::Entity::Mapper.map(input, [Hash, K: Symbol, V: [Array, T: User]])\n```\n\nBasically it means 'map input data to hash with symbol keys and values as \narrays of User instances'. K, V and T are predefined type parameters, and\nArray and Hash mappings were added automatically.\n\nThe next desired action would be to map some input structure into nested\ncustom classes. This is possible with custom mappings, with easiest way to \nspecify them via custom DSL:\n\n```ruby\nclass Page\n  include AMA::Entity::Mapper::DSL\n  \n  attribute :number, Integer\n  attribute :last, TrueClass, FalseClass\n  # Substituting Array's parameter T with page class parameter E,\n  # so content is not Array\u003cArray.T\u003e, but Array\u003cPage.E\u003e\n  attribute :content, [Array, T: parameter(:E)]\nend\n\nclass User\n  include AMA::Entity::Mapper::DSL\n  \n  attribute :login, Symbol, aliases: %i[id user_id]\n  attribute :policy, Symbol, values: %i[read write manage], default: :read\n  attribute :keys, [Hash, K: Symbol, V: PrivateKey], default: {}\n  attribute :last_login, DateTime, nullable: true\nend\n\nclass PrivateKey\n  include AMA::Entity::Mapper::DSL\n  \n  attribute :id, Symbol\n  # Sensitive attributes may be restored from incoming data, but are ignored\n  # when mapped into another type.\n  attribute :content, String, sensitive: true\nend\n\ndata = {\n  number: 1,\n  last: false,\n  content: [\n    ron: {\n      id: 'charlie-the-unicorn',\n      policy: 'read',\n      keys: {\n        id_rsa: {\n          id: 'id_rsa',\n          content: '----BEGIN PRIVATE KEY....'\n        }\n      }\n    }\n  ]\n}\n\npage = AMA::Entity::Mapper.map(data, [Page, E: User])\n```\n\nLast thing to say is that attributes, in fact, may have several possible types,\nand `#map` method accepts several types as well:\n\n```ruby\nresult = AMA::Entity::Mapper.map(data, TrueClass, FalseClass)\n```\n\nThis would try to map data to TrueClass, and, if it fails - to FalseClass.\n\nThat's the crash course, most probably you've already got what you need.\nIf that's not enough, full documentation is available at \n[GitHub Pages][doc].\n\n## Versioning\n\nThis project adheres to [Semantic Versioning][semver]. In a nutshell,\nthis means the following:\n\n- Every patch release (a.b.X -\u003e a.b.Y) fixes bugs and is safe to\nupdate to from previous patch release\n- Every minor release (a.X.b -\u003e a.Y.0) contains new features\n- Every minor release before 1.0.0 **may** break API\n- Every minor release after 1.0.0 does not break API (but may introduce\nnew coexisting replacement API and schedule existing API for,\ndeprecation) updating to next minor release is safe after 1.0.0\n- Every major release contains significant API change and it is not \nsafe to jump from one major release to another.\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies\nand git hooks.  \nThen, run `rake validate` to run lint and tests. If you have \n[Allure report generator][allure] on your machine, you may run \n`rake test:with-report` to generate report after test run.\n\nTests are separated into three categories: unit (no dependencies, \neverything is mocked), integration (testing components with their \ndependencies, optional mocking) and acceptance (no mocks, real data,\ntesting high-level components and library as a whole).\n\nDevelopment is performed using git-flow, meaning that development id\ndone in dev or release/x.y branch, features and stuff is done in \nbranches spawn from branches specified above.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. \nTo release a new version, update the version number in `version.rb`, \nand then run `bundle exec rake release`, which will create a git tag for \nthe version, push git commits and tags, and push the `.gem` file \nto [rubygems.org][rubygems].\n\nDev branch state:\n\n[![CircleCI][shields.circleci.dev]][circleci.dev]\n[![Coveralls][shields.coveralls.dev]][coveralls.dev]\n[![Scrutinizer][shields.scrutinizer.dev]][scrutinizer.dev]\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at \n[https://github.com/ama-team/ruby-entity-mapper](). Please send your pull\nrequests into dev branch (not into master).\n\n## License\n\nThe gem is available as open source under the terms of the \n[MIT License][mit-license].\n\n  [mit-license]: http://opensource.org/licenses/MIT\n  [repository]: https://github.com/ama-team/ruby-entity-mapper\n  [doc]: https://ama-team.github.io/ruby-entity-mapper\n  [rubygems]: https://rubygems.org\n  [allure]: https://github.com/allure-framework/allure2\n  [shields.scrutinizer.master]: https://img.shields.io/scrutinizer/g/ama-team/ruby-entity-mapper/master.svg?style=flat-square\n  [shields.scrutinizer.dev]: https://img.shields.io/scrutinizer/g/ama-team/ruby-entity-mapper/dev.svg?style=flat-square\n  [shields.coveralls.master]: https://img.shields.io/coveralls/ama-team/ruby-entity-mapper/master.svg?style=flat-square\n  [shields.coveralls.dev]: https://img.shields.io/coveralls/ama-team/ruby-entity-mapper/dev.svg?style=flat-square\n  [shields.circleci.master]: https://img.shields.io/circleci/project/github/ama-team/ruby-entity-mapper/master.svg?style=flat-square\n  [shields.circleci.dev]: https://img.shields.io/circleci/project/github/ama-team/ruby-entity-mapper/dev.svg?style=flat-square\n  [shields.codeclimate]: https://img.shields.io/codeclimate/github/ama-team/ruby-entity-mapper.svg?style=flat-square\n  [shields.gem]: https://img.shields.io/gem/v/ama-entity-mapper.svg?style=flat-square\n  [scrutinizer.master]: https://scrutinizer-ci.com/g/ama-team/ruby-entity-mapper?branch=master \n  [scrutinizer.dev]: https://scrutinizer-ci.com/g/ama-team/ruby-entity-mapper?branch=dev\n  [coveralls.master]: https://coveralls.io/github/ama-team/ruby-entity-mapper?branch=master\n  [coveralls.dev]: https://coveralls.io/github/ama-team/ruby-entity-mapper?branch=dev\n  [circleci.master]: https://circleci.com/gh/ama-team/ruby-entity-mapper/tree/master \n  [circleci.dev]: https://circleci.com/gh/ama-team/ruby-entity-mapper/tree/dev\n  [codeclimate]: https://codeclimate.com/github/ama-team/ruby-entity-mapper\n  [gem]: https://rubygems.org/gems/ama-entity-mapper\n  [semver]: http://semver.org/spec/v2.0.0.html\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fama-team%2Fruby-entity-mapper","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fama-team%2Fruby-entity-mapper","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fama-team%2Fruby-entity-mapper/lists"}