{"id":19063230,"url":"https://github.com/delner/tutor","last_synced_at":"2025-08-31T22:34:18.200Z","repository":{"id":59158275,"uuid":"59374786","full_name":"delner/tutor","owner":"delner","description":"Supplemental teachings for your Ruby classes.","archived":false,"fork":false,"pushed_at":"2016-05-30T16:35:30.000Z","size":16,"stargazers_count":0,"open_issues_count":0,"forks_count":0,"subscribers_count":2,"default_branch":"master","last_synced_at":"2025-02-03T05:16:49.567Z","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":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/delner.png","metadata":{"files":{"readme":"README.md","changelog":null,"contributing":null,"funding":null,"license":"LICENSE.txt","code_of_conduct":null,"threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":null,"support":null}},"created_at":"2016-05-21T18:09:30.000Z","updated_at":"2016-05-21T18:14:23.000Z","dependencies_parsed_at":"2022-09-13T17:50:59.346Z","dependency_job_id":null,"html_url":"https://github.com/delner/tutor","commit_stats":null,"previous_names":[],"tags_count":0,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delner%2Ftutor","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delner%2Ftutor/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delner%2Ftutor/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/delner%2Ftutor/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/delner","download_url":"https://codeload.github.com/delner/tutor/tar.gz/refs/heads/master","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":240118332,"owners_count":19750470,"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-09T00:29:20.881Z","updated_at":"2025-02-22T02:40:35.515Z","avatar_url":"https://github.com/delner.png","language":"Ruby","funding_links":[],"categories":[],"sub_categories":[],"readme":"Tutor\n==========\n\n[![Build Status](https://travis-ci.org/delner/tutor.svg?branch=master)](https://travis-ci.org/delner/tutor) ![Gem Version](https://img.shields.io/gem/v/tutor.svg?maxAge=2592000)\n###### *For Ruby 2+*\n\n*Supplemental teachings for your Ruby classes.*\n\n### Table of Contents\n\n 1. [Introduction](#introduction)\n 2. [Installation](#installation)\n 3. [Features](#features)\n    1. [Attributes](#attributes)\n        1. [Type-checking](#type-checking)\n        2. [Defaults](#defaults)\n        3. [Aliasing](#aliasing)\n        4. [Custom getter \u0026 setter](#custom-getter-and-setter)\n        5. [Inheritance](#inheritance)\n 4. [Testing](#testing)\n 5. [Development](#development)\n 6. [Contributing](#contributing)\n 4. [License](#license)\n\n### \u003ca name=\"introduction\"\u003e\u003c/a\u003eIntroduction\n\n**Tutor** adds some useful patterns and idioms to mixin to your classes.\n\ne.g. Attributes with type and defaults\n\n```ruby\nclass Vertex; end\nclass Polygon\n  include Tutor::Attributes\n\n  attribute(:sides, type: Integer, default: 3)\n  attribute(:vertices, default: lambda { |polygon| Array.new(polygon.sides) { Vertex.new } })\nend\n\np = Polygon.new\np.intialize_attributes\np.sides # =\u003e 3\np.vertices # =\u003e [#\u003cVertex\u003e, #\u003cVertex\u003e, #\u003cVertex\u003e]\n```\n\n###\u003ca name=\"installation\"\u003e\u003c/a\u003e Installation\n\n##### If you're not using Bundler...\n\nInstall the gem via:\n\n```\ngem install tutor\n```\n\nThen require it into your application with:\n\n```\nrequire 'tutor'\n```\n\n##### If you're using Bundler...\n\nAdd the gem to your Gemfile:\n\n```\ngem 'tutor'\n```\n\nAnd then `bundle install` to install the gem and its dependencies.\n\n###\u003ca name=\"features\"\u003e\u003c/a\u003e Features\n\n####\u003ca name=\"attributes\"\u003e\u003c/a\u003e Attributes\n\nEnable attributes on a class by including `Tutor::Attributes` module into the class/module you want to add attributes to.\n\n```ruby\nclass Polygon\n  include Tutor::Attributes\nend\n```\n\nThen add an `attribute` to add a `name` and `name=` method to the class.\n\n```ruby\nclass Polygon\n  include Tutor::Attributes\n\n  attribute(:sides)\nend\n\nPolygon.method_defined?(:sides) # =\u003e true\nPolygon.method_defined?(:sides=) # =\u003e true\n```\n\nOf course, if this is all you need, then you might be better served just using `attr_accessor`. However, `attribute` gives you access to a few additional options.\n\n#####\u003ca name=\"type-checking\"\u003e\u003c/a\u003e Type-checking\n\n```ruby\nattribute(:sides, type: Integer)\n```\n\nAdd type-checking by adding the `type` option, and the class you want to type check against. Any value that is of that type, or inherits from it, will be permitted. Any other value will raise an `ArgumentError`.\n\nBy default, `nil` passes the type check. However, if you want to disallow `nil` values, you can set the `nullable: false` option.\n\n```ruby\nattribute(:sides, type: Integer, nullable: false)\n```\n\n#####\u003ca name=\"defaults\"\u003e\u003c/a\u003e Defaults\n\n```ruby\nattribute(:vertices, default: 3)\n```\n\nAdding the `default` option sets a default value for attribute, when `initialize_attributes` is called. To automatically set these defaults, add the function call to your `initialize` function.\n\n```ruby\ndef initialize\n  initialize_attributes\nend\n```\n\nYou can also pass it a `Hash` of attributes, which will override any default values.\n\n```ruby\ndef initialize(custom_attributes = {})\n  initialize_attributes(custom_attributes)\nend\n```\n\nYou can also set the default to a `Proc` or `lambda`. This is useful for non-static values, like class objects, where you want unique default objects per instance of your class.\n\n```ruby\n# NOTE: The following two definitions are NOT equivalent.\n\n# Sets default to the same object for all instances.\nattribute(:vertices, default: Vertex.new)\n\n# Sets default to the different object for each instance.\nattribute(:vertices, default: -\u003e { Vertex.new })\n```\n\nThese blocks optionally can be defined to accept an argument. In which case, the object being initialized will be passed in. Any explicitly provided attribute values, or previously set defaults will be accessible.\n\n```ruby\nattribute :vertices,\n  default: lambda { |object| object.sides.times { Vertex.new } }\n```\n\n#####\u003ca name=\"aliasing\"\u003e\u003c/a\u003e Aliasing\n\n```ruby\nattribute(:nodes)\nattribute(:vertices, alias: :nodes)\n```\n\nAlias any other attribute with the `alias` option, and the name of the method.\n\n##### \u003ca name=\"custom-getter-and-setter\"\u003e\u003c/a\u003eCustom getter \u0026 setter\n\n```ruby\nattribute :vertices,\n  get: lambda { |object| object.nodes },\n  set: lambda { |object, value| object.nodes = value }\n```\n\nYou can add custom get or set behavior for the attribute, by passing a `Proc` into the `get` or `set` options.\n\n```ruby\nattribute :vertices,\n  get: lambda { |object| object.nodes },\n  set: false\n```\n\nPassing a `false` or `nil` value for either `get` or `set` will skip that method declaration.\n\n#####\u003ca name=\"inheritance\"\u003e\u003c/a\u003e Inheritance\n\n```ruby\nclass Angle; end\n\nclass Polygon\n  include Tutor::Attributes\n  attribute(:sides, type: Integer)\nend\n\nclass Triangle \u003c Polygon\n  include Tutor::Attributes\n  attribute(:angles, default: lambda { |o| o.sides.times { Angle.new } })\nend\n\nTriangle.new.initialize_attributes(sides: 3)\n# =\u003e #\u003cTriangle @sides=3, @angles=[ #\u003cAngle\u003e, #\u003cAngle\u003e, #\u003cAngle\u003e]\u003e\n```\n\nAttributes can be initialized and accessed from inheriting classes. If an attribute name in a subclass conflicts with an already existing attribute or method, it will raise a `NameError`. You can, however, override the parent by passing the `override` option.\n\n```ruby\nclass Angle; end\n\nclass Polygon\n  include Tutor::Attributes\n  attribute(:sides, type: Integer, default: 3)\nend\n\nclass Square \u003c Polygon\n  include Tutor::Attributes\n  attribute(:sides, type: Integer, default: 4, override: true)\nend\n\nSquare.new.initialize_attributes\n# =\u003e #\u003cSquare @sides=4\u003e\n```\n\n### \u003ca name=\"testing\"\u003e\u003c/a\u003eTesting\n\n*Description pending.*\n\n### \u003ca name=\"development\"\u003e\u003c/a\u003eDevelopment\n\nInstall dependencies using `bundle install`. Run tests using `bundle exec rspec`.\n\n### \u003ca name=\"contributing\"\u003e\u003c/a\u003eContributing\n\nBug reports and pull requests are welcome on GitHub at https://github.com/delner/tutor.\n\n### \u003ca name=\"license\"\u003e\u003c/a\u003eLicense\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%2Fdelner%2Ftutor","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fdelner%2Ftutor","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fdelner%2Ftutor/lists"}