{"id":20269896,"url":"https://github.com/teliosdev/mixture","last_synced_at":"2026-05-11T00:47:35.165Z","repository":{"id":56884030,"uuid":"38840494","full_name":"teliosdev/mixture","owner":"teliosdev","description":"Attributes, Coercion, Validation.","archived":false,"fork":false,"pushed_at":"2017-03-08T21:12:55.000Z","size":94,"stargazers_count":1,"open_issues_count":0,"forks_count":0,"subscribers_count":0,"default_branch":"master","last_synced_at":"2026-05-11T00:47:34.027Z","etag":null,"topics":[],"latest_commit_sha":null,"homepage":"http://www.rubydoc.info/github/medcat/mixture","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/teliosdev.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}},"created_at":"2015-07-09T19:20:21.000Z","updated_at":"2017-03-07T19:13:32.000Z","dependencies_parsed_at":"2022-08-20T23:40:26.600Z","dependency_job_id":null,"html_url":"https://github.com/teliosdev/mixture","commit_stats":null,"previous_names":["medcat/mixture"],"tags_count":16,"template":false,"template_full_name":null,"purl":"pkg:github/teliosdev/mixture","repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teliosdev%2Fmixture","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teliosdev%2Fmixture/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teliosdev%2Fmixture/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teliosdev%2Fmixture/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/teliosdev","download_url":"https://codeload.github.com/teliosdev/mixture/tar.gz/refs/heads/master","sbom_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/teliosdev%2Fmixture/sbom","scorecard":null,"host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":286080680,"owners_count":32877246,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2026-05-10T13:40:02.631Z","status":"ssl_error","status_checked_at":"2026-05-10T13:40:02.145Z","response_time":54,"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-14T12:27:56.521Z","updated_at":"2026-05-11T00:47:35.142Z","avatar_url":"https://github.com/teliosdev.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"# Mixture\n\n[![Build Status](https://travis-ci.org/medcat/mixture.svg?branch=master)](https://travis-ci.org/medcat/mixture) [![Coverage Status](https://coveralls.io/repos/medcat/mixture/badge.svg?branch=master\u0026service=github)](https://coveralls.io/github/medcat/mixture?branch=master) [![Gem Version](https://badge.fury.io/rb/mixture.svg)](http://badge.fury.io/rb/mixture)\n\n## Installation\n\nAdd this line to your application's Gemfile:\n\n```ruby\ngem 'mixture'\n```\n\nAnd then execute:\n\n    $ bundle\n\n## Usage\n\nIt's simple, really.\n\n```ruby\nmodule MyLibrary\n  class MyClass\n    include Mixture::Model\n  end\nend\n```\n\nThis provides a few simple things.  First off, it provides the\n`.attribute` class method.  The attribute class method allows you to\ndefine an attribute on your class.  Attributes use the instance\nvariables just like `attr_reader`/`attr_writer` do - but it also\nallows coercion on assignment, as well.  Defining an attribute is as\nsimple as `attribute :name`.  This provides the `:name` and `:name=`\nmethods on the instance.\n\nYou also get access to the `#attributes=`, `#attributes`, and\n`#attribute` instance methods.  The first group assigns attributes,\nrunning it through any update callbacks defined.  The second retrieves\nthe attributes on the instance, even if they weren't assigned.  The\nlast provides easy get/set functionality.\n\nIf you want to take advantage of the coercion abilities, just add a\n`:type` key to the options for the attribute:\n\n```ruby\nmodule MyLibrary\n  class MyClass\n    include Mixture::Model\n\n    attribute :name, type: String\n  end\nend\n```\n\nThis will automagically cause `name` to be coerced to a string on\nassignment.\n\nFor validation, use the `.validate` class method:\n\n```ruby\nmodule MyLibrary\n  class MyClass\n    include Mixture::Model\n    attribute :name, type: String\n    validate :name, format: /^.{3,20}$/\n  end\nend\n```\n\nSome validators are available by default:\n\n- `:exclusion` - Validates that the value for the attribute is not\n  within a given set of values.\n- `:inclusion` - Validates that the value for the attribute _is_\n  within a given set of values.\n- `:length` - Validates that the value for the attribute is within a\n  certain length.\n- `:match` - Validates that the value for the attribute matches a\n  regular expression.  This is also known as `:format`.\n- `:presence` - Validates that the value is not nil and isn't empty\n  (by checking for `#empty?`).\n\nAdding a validator is simple:\n\n```ruby\nmodule MyLibrary\n  class MyValidator \u003c Mixture::Validate::Base\n    # This registers it with Mixture, so it can be used within a\n    # `validate` call.\n    register_as :my_validator\n\n    def validate(record, attribute, value)\n      # this sets instance variables mapping the above arguments.\n      super\n      my_super_awesome_validation\n    end\n  end\nend\n```\n\nAdding a coercer is also simple:\n\n```ruby\nmodule MyLibrary\n  module Types\n    class MyObject \u003c Mixture::Types::Object\n      options[:primitive] = nil\n      constraint { |value| ... }\n    end\n  end\n  module Coerce\n    class MyObject \u003c Mixture::Coerce::Base\n      type MyLibrary::Types::MyObject\n\n      coerce_to(Mixture::Types::Array) do |value|\n        value.to_a\n      end\n    end\n  end\nend\n```\n\nAlthough the builtin coercers should do well.\n\nA more complex example:\n\n```ruby\nmodule MyLibrary\n  class Something\n    include Mixture::Model\n\n    attribute :name, type: String\n    attribute :files, type: Array[String]\n    attribute :authors, type: Set[Author]\n    attribute :dependencies, type: Set[Dependency]\n  end\nend\n```\n\n## Contributing\n\nBug reports and pull requests are welcome on GitHub at\nhttps://github.com/medcat/mixture.  This project is intended to be a\nsafe, welcoming space for collaboration, and contributors are expected\nto adhere to the [Contributor Covenant](contributor-covenant.org) code\nof conduct.\n\n\n## License\n\nThe gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteliosdev%2Fmixture","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fteliosdev%2Fmixture","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fteliosdev%2Fmixture/lists"}