{"id":13878373,"url":"https://github.com/joelmoss/shreddies","last_synced_at":"2025-11-11T20:39:28.371Z","repository":{"id":40009064,"uuid":"276160943","full_name":"joelmoss/shreddies","owner":"joelmoss","description":"Stupid simple Rails model and object serializer","archived":false,"fork":false,"pushed_at":"2025-03-14T10:12:50.000Z","size":78,"stargazers_count":4,"open_issues_count":5,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-08-02T21:48:30.779Z","etag":null,"topics":["json","rails","ruby-on-rails","serialization"],"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/joelmoss.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,"governance":null,"roadmap":null,"authors":null,"dei":null,"publiccode":null,"codemeta":null,"zenodo":null}},"created_at":"2020-06-30T17:03:41.000Z","updated_at":"2025-03-14T10:12:54.000Z","dependencies_parsed_at":"2025-06-30T06:35:19.192Z","dependency_job_id":"6a2817fb-04b6-464d-912e-6a77e9187589","html_url":"https://github.com/joelmoss/shreddies","commit_stats":null,"previous_names":[],"tags_count":14,"template":false,"template_full_name":null,"purl":"pkg:github/joelmoss/shreddies","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joelmoss%2Fshreddies","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joelmoss%2Fshreddies/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joelmoss%2Fshreddies/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joelmoss%2Fshreddies/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/joelmoss","download_url":"https://codeload.github.com/joelmoss/shreddies/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/joelmoss%2Fshreddies/sbom","scorecard":{"id":527002,"data":{"date":"2025-08-11","repo":{"name":"github.com/joelmoss/shreddies","commit":"74367b45b4a3cf84e7e50f6b1c1dbad98acc39ee"},"scorecard":{"version":"v5.2.1-40-gf6ed084d","commit":"f6ed084d17c9236477efd66e5b258b9d4cc7b389"},"score":2.7,"checks":[{"name":"Code-Review","score":0,"reason":"Found 0/22 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":10,"reason":"no dangerous workflow patterns detected","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":"Pinned-Dependencies","score":0,"reason":"dependency not pinned by hash detected -- score normalized to 0","details":["Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:30: update your workflow using https://app.stepsecurity.io/secureworkflow/joelmoss/shreddies/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:31: update your workflow using https://app.stepsecurity.io/secureworkflow/joelmoss/shreddies/main.yml/master?enable=pin","Warn: GitHub-owned GitHubAction not pinned by hash: .github/workflows/main.yml:17: update your workflow using https://app.stepsecurity.io/secureworkflow/joelmoss/shreddies/main.yml/master?enable=pin","Warn: third-party GitHubAction not pinned by hash: .github/workflows/main.yml:19: update your workflow using https://app.stepsecurity.io/secureworkflow/joelmoss/shreddies/main.yml/master?enable=pin","Info:   0 out of   2 GitHub-owned GitHubAction dependencies pinned","Info:   0 out of   2 third-party GitHubAction dependencies pinned"],"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":"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":"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":"Token-Permissions","score":0,"reason":"detected GitHub workflow tokens with excessive permissions","details":["Warn: no topLevel permission defined: .github/workflows/main.yml:1","Info: no jobLevel write permissions found"],"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":"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":"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":"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":"License","score":10,"reason":"license file detected","details":["Info: project has a license file: LICENSE.txt:0","Info: FSF or OSI recognized license: MIT License: LICENSE.txt: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"}},{"name":"SAST","score":0,"reason":"SAST tool is not run on all commits -- score normalized to 0","details":["Warn: 0 commits out of 8 are checked with a SAST tool"],"documentation":{"short":"Determines if the project uses static code analysis.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#sast"}},{"name":"Vulnerabilities","score":2,"reason":"8 existing vulnerabilities detected","details":["Warn: Project is vulnerable to: GHSA-76r7-hhxj-r776","Warn: Project is vulnerable to: GHSA-9m3q-rhmv-5q44","Warn: Project is vulnerable to: GHSA-353f-x4gh-cqq8","Warn: Project is vulnerable to: GHSA-5w6v-399v-w3cc","Warn: Project is vulnerable to: GHSA-mrxw-mxhj-p664","Warn: Project is vulnerable to: GHSA-47m2-26rw-j2jw","Warn: Project is vulnerable to: GHSA-gjh7-p2fx-99vx","Warn: Project is vulnerable to: GHSA-9j94-67jr-4cqj"],"documentation":{"short":"Determines if the project has open, known unfixed vulnerabilities.","url":"https://github.com/ossf/scorecard/blob/f6ed084d17c9236477efd66e5b258b9d4cc7b389/docs/checks.md#vulnerabilities"}}]},"last_synced_at":"2025-08-20T04:40:05.430Z","repository_id":40009064,"created_at":"2025-08-20T04:40:05.430Z","updated_at":"2025-08-20T04:40:05.430Z"},"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272942394,"owners_count":25019328,"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-08-31T02:00:09.071Z","response_time":79,"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":["json","rails","ruby-on-rails","serialization"],"created_at":"2024-08-06T08:01:47.642Z","updated_at":"2025-10-08T18:19:53.665Z","avatar_url":"https://github.com/joelmoss.png","language":"Ruby","funding_links":[],"categories":["Ruby"],"sub_categories":[],"readme":"# Shreddies - Stupid simple Rails model and object serializer\n\nShreddies is a JSON serialization library for Rails that focuses on simplicity and speed. No more \"magic\" DSL's - just plain old Ruby objects! It's primarily intended to serialize Rails models as JSON, but will also work with pretty much anything at all.\n\nShreddies primary principle is to be explicit. So a serializer will return nothing until you define some methods. This gives you complete control and everything is a known quantity - no surprises.\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'shreddies'\n```\n\nAnd then execute:\n\n    $ bundle install\n\nOr install it yourself as:\n\n    $ gem install shreddies\n\n## Usage\n\nSerializers should be named after your models and located in \"`app/serializers`\". Any public methods you define will be serialized, and you can quickly expose methods from the serialized subject using the `delegate` class method, which simply delegates to the subject.\n\n```ruby\n# app/serializers/user_serializer.rb\nclass UserSerializer \u003c Shreddies::Json\n  delegate :id, :first_name, :last_name, :email\n\n  def name\n    \"#{first_name} #{last_name}\"\n  end\nend\n```\n\nCalling the above will result in this JSON:\n\n```json\n{\n  \"id\": 1,\n  \"name\": \"Joel Moss\",\n  \"firstName\": \"Joel\",\n  \"lastName\": \"Moss\",\n  \"email\": \"me@you.com\"\n}\n```\n\n\u003e **NOTE** that all keys are transformed to camelCase, as the JSON is intended to be used by Javascript.\n\nCall your serializer directly:\n\n```ruby\nUserSerializer.render(user)\n```\n\nOr just use the `#as_json` instance method on your model:\n\n```ruby\nUser.find(1).as_json\n```\n\nModel collections and array's are also supported:\n\n```ruby\nUser.all.as_json\n```\n\n### Collection and Single Modules\n\nYou may find that you don't want or need to return as much data in collections of objects, or may want to include differtent data. So if a serializer defines a `Collection` module, and a collection or array is being rendered, then that Collection module will automatically be included:\n\n```ruby\nArticleSerializer \u003c Shreddies::Json\n  module Collection\n    def url\n      \"https://blah.com/#{subject.slug}\"\n    end\n  end\nend\n```\n\nConversely, you can define a `Single` module, and that will be included when rendering a single object.\n\n```ruby\nArticleSerializer \u003c Shreddies::Json\n  module Single\n    def body\n      'this body is really, really long, and I do not want it returned in lists.'\n    end\n  end\nend\n```\n\n### ActiveRecord Associations\n\nActiveRecord associations are supported with no additional work on your part. Shreddies will simply call `#as_json` on any method that returns an ActiveRecord model or relation.\n\n```ruby\n# app/serializers/user_serializer.rb\nclass UserSerializer \u003c Shreddies::Json\n  delegate :articles\n\n  def latest_article\n    articles.latest\n  end\nend\n```\n\nAnd if you need to be specific about what you render, just call the serializer or `#as_json` directly:\n\n```ruby\n# app/serializers/user_serializer.rb\nclass UserSerializer \u003c Shreddies::Json\n  def articles\n    subject.articles.as_json index_by: :slug\n  end\n\n  def latest_article\n    LatestArticleSerializer.render articles.latest\n  end\nend\n```\n\n### `before_render` callback\n\nYou can define a `#before_render` private method in your serializers, which will act as a callback. It receives the object to be output, and expects you to return the object, which allows you to modify it before rendering.\n\n### Options\n\nBoth `#as_json` and `.render` accepts an `options` hash, which will be forwarded to the serializer class, and available as `options`. This allows you to pass arbitrary options and use them in your serializer.\n\nThe following standard options are supported, and provide additional built-in functionality:\n\n#### `serializer`\n\nBy default `#as_json` will look for a serializer named after your model. So a `User` model will automatically use the `UserSerializer`. Sometimes you want to use a different serializer class, in which case you can use the `serializer` option:\n\n```ruby\nUser.all.as_json serializer: User::AdminSerializer\n```\n\n#### `module`\n\nYou can pass one or module names in the `module` option, and these modules will be included into the serializer. This is great for selectively including attributes and methods.\n\n```ruby\nArticle.all.as_json module: :WithBody\n```\n\n```ruby\nArticleSerializer \u003c Shreddies::Json\n  module WithBody\n    def body\n      'This article body is really, really long'\n    end\n  end\nend\n```\n\nThe `Collection` and `Single` modules can be defined and they will be automatically included. The Collection module will be included when rendering an array or ActiveRecord collection (`ActiveRecord::Relation`), and the Single module will be included when rendering a single obejct.\n\n#### `transform_keys` (default: true)\n\nIf false, the returned keys will not be transformed. The default is to deeply transform all keys to camelCase.\n\n#### `except`\n\nPass one or more attribute names as a Symbol or Array of Symbols, and these will be excluded from the results:\n\n```ruby\nUser.all.as_json(except: [:first_name, :age])\n```\n\n#### `only`\n\nPass one or more attribute names as a Symbol or Array of Symbols, and _ONLY_ these will be included in the results:\n\n```ruby\nUser.all.as_json(only: :first_name)\n```\n\n\u003e Attributes must still be defined within the Serializer.\n\n#### `index_by`\n\nGive this option a property of your serialized subject as a Symbol, and the returned collection will be a Hash keyed by that property.\n\n```ruby\nUser.all.as_json index_by: :id\n```\n\n```json\n{\n  1: {\n    \"id\": 1,\n    \"name\": \"Joel Moss\",\n    \"firstName\": \"Joel\",\n    \"lastName\": \"Moss\"\n  }\n\n  2: {\n    \"id\": 2,\n    \"name\": \"An Other\",\n    \"firstName\": \"An\",\n    \"lastName\": \"Other\"\n  }\n\n  ...\n}\n```\n\n### Serializer Inheritance\n\nA serializer can inherit from any other serializer, which is a great way to create custom views:\n\n```ruby\n# app/serializers/user_serializer.rb\nclass UserSerializer \u003c Shreddies::Json\n  delegate :id, :first_name, :last_name, :email\n\n  def name\n    \"#{first_name} #{last_name}\"\n  end\nend\n\nclass User::AdministratorSerializer \u003c UserSerializer\n  def type\n    'administrator'\n  end\nend\n```\n\nThen call it like any other serializer:\n\n```ruby\nUser::AdministratorSerializer.render(user)\n```\n\n## Development\n\nAfter checking out the repo, run `bin/setup` to install dependencies. Then, run `rake test` to run the tests. You can also run `bin/console` for an interactive prompt that will allow you to experiment.\n\nTo install this gem onto your local machine, run `bundle exec rake install`. To release a new version, update the version number in `version.rb`, and then run `bundle exec rake release`, which will create a git tag for the version, push git commits and tags, and push the `.gem` file to [rubygems.org](https://rubygems.org).\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/joelmoss/shreddies. This project is intended to be a safe, welcoming space for collaboration, and contributors are expected to adhere to the [code of conduct](https://github.com/joelmoss/shreddies/blob/master/CODE_OF_CONDUCT.md).\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](https://opensource.org/licenses/MIT).\n\n## Code of Conduct\n\nEveryone interacting in the Shreddies project's codebases, issue trackers, chat rooms and mailing lists is expected to follow the [code of conduct](https://github.com/joelmoss/shreddies/blob/master/CODE_OF_CONDUCT.md).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoelmoss%2Fshreddies","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjoelmoss%2Fshreddies","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjoelmoss%2Fshreddies/lists"}