{"id":20481166,"url":"https://github.com/janlelis/value_struct","last_synced_at":"2025-09-03T03:38:37.188Z","repository":{"id":5335685,"uuid":"6521117","full_name":"janlelis/value_struct","owner":"janlelis","description":"Read-only structs in Ruby","archived":false,"fork":false,"pushed_at":"2021-12-29T20:38:18.000Z","size":23,"stargazers_count":25,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-07-29T07:20:24.684Z","etag":null,"topics":["ruby","ruby-struct","value-object"],"latest_commit_sha":null,"homepage":"https://rbjl.janlelis.com/65-value_struct-read-only-structs-in-ruby","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/janlelis.png","metadata":{"files":{"readme":"README.md","changelog":"ChangeLog.md","contributing":null,"funding":null,"license":"MIT-LICENSE.txt","code_of_conduct":"CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2012-11-03T15:48:19.000Z","updated_at":"2023-02-17T05:43:14.000Z","dependencies_parsed_at":"2022-07-05T23:32:03.134Z","dependency_job_id":null,"html_url":"https://github.com/janlelis/value_struct","commit_stats":null,"previous_names":[],"tags_count":6,"template":false,"template_full_name":null,"purl":"pkg:github/janlelis/value_struct","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fvalue_struct","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fvalue_struct/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fvalue_struct/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fvalue_struct/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/janlelis","download_url":"https://codeload.github.com/janlelis/value_struct/tar.gz/refs/heads/main","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/janlelis%2Fvalue_struct/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":272789723,"owners_count":24993352,"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-29T02:00:10.610Z","response_time":87,"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":["ruby","ruby-struct","value-object"],"created_at":"2024-11-15T16:07:05.437Z","updated_at":"2025-09-03T03:38:37.161Z","avatar_url":"https://github.com/janlelis.png","language":"Ruby","readme":"# Value Struct [![[version]](https://badge.fury.io/rb/value_struct.svg)](https://badge.fury.io/rb/value_struct)  [![[ci]](https://github.com/janlelis/value_struct/workflows/Test/badge.svg)](https://github.com/janlelis/value_struct/actions?query=workflow%3ATest)\n\nA value struct is a subclass of the normal [Ruby struct](http://graysoftinc.com/ruby-voodoo/all-about-struct) that behaves almost the same. However, it has a major difference:\n\n__Value structs are immutable, i.e. they don't have setters (although, not recursively*)__\n\nAdditionally, this gem provides the following optional mixins to make life easier when using immutable structs:\n\n* __:dup_with_changes__ Extends `#dup` to take a optional hash for setting new values in the duplicate\n* __:strict_arguments__ Value structs need to be initialized with the exact amount of arguments\n* __:freeze__ Automatically freezes new instances\n* __:no_clone__ Alters `#clone` to return the same object\n\nBy default, only __:dup_with_changes__ will be included.\n\nWithout mixins, ValueStructs are almost as fast as normal structs. Some mixins add noticable overhead, e.g. strict_arguments\n\n## Why?\n\nSee [this blog article](https://rbjl.janlelis.com/65-value_struct-read-only-structs-in-ruby) for more information.\n\n## Example 1\n\n    require 'value_struct'\n\n    SimplePoint = ValueStruct.new(:x, :y)\n\n\nPlease refer to the [documentation of Ruby's struct](https://ruby-doc.org/core/Struct.html) for more details on general struct usage.\n\n## How to use structs with mixins\n\n    Point = ValueStruct.new_with_mixins :x, :y, [\n      :freeze,\n      :dup_with_changes,\n      :strict_arguments,\n    ]\n\n    p = Point.new(1,2)\n    p.frozen?    #=\u003e true\n    p.dup(x: 0)  #=\u003e #\u003cValueStruct Point x=0, y=2\u003e\n    Point.new(1) # ArgumentError\n\nAlternatively, you can put custom modules in the mixin array.\n\n## Example 2\n\n    require 'value_struct'\n\n    Point = ValueStruct.new_with_mixins(\n      :x,\n      :y,\n       [:dup_with_changes, :freeze, :no_clone],\n    ) do\n\n      def initialize(x,y)\n        raise ArgumentError, 'points must be initialized with two numerics' unless x.is_a?(Numeric) \u0026\u0026 y.is_a?(Numeric)\n        super(x,y)\n      end\n\n      def abs\n        ( x**2 + y**2 ) ** 0.5\n      end\n\n      def +(o)\n        dup(x: x + o.x, y: y + o.y)\n      end\n\n      def -(o)\n        dup(x: x - o.x, y: y - o.y)\n      end\n\n      def +@\n        self\n      end\n\n      def -@\n        dup(x: -x, y: -o.y)\n      end\n\n      def to_c\n        Complex(x,y)\n      end\n\n      def to_s\n        \"(#{x},#{y})\"\n      end\n      alias inspect to_s\n    end\n\n## *\n\nBecause of the nature of Ruby, most things are not really immutable. So if you have an attribute `:by` and initialize it with an array, you cannot change the value struct anymore, but still the array:\n\n    Ru = ValueStruct.new(:by)\n    ruby = Ru.by([1,2,3])\n    ruby.by # =\u003e [1,2,3]\n\n    ruby.by = [1,2,3,4] # not possible\n    ruby.by \u003c\u003c 4        # possible\n\n## Install\n\n    $ gem install value_struct\n\n## Influenced by / Thanks to\n\n* Tom Crayford: [Values](https://github.com/tcrayford/Values)\n* Theo Hultberg: [ImmutableStruct](https://github.com/iconara/immutable_struct)\n* Ruby Rogues\n\n## J-_-L\n\nCopyright © 2012-2015 Jan Lelis, janlelis.com, released under the MIT license.\n","funding_links":[],"categories":[],"sub_categories":[],"project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanlelis%2Fvalue_struct","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fjanlelis%2Fvalue_struct","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fjanlelis%2Fvalue_struct/lists"}