Unique variable name generator from keywords
Vega expression parser and code generator.
Turns an AST into code.
Check whether a value is a generator or generator function
Determine if a function is a native generator function.
Provides a helper for yeoman generators that wraps the prompt method with code that will exclude any prompts for data that has been supplied via options.
Mersenne twister pseudorandom number generator
Generate unique and memorable names
Turns an AST into code.
Turn async generator functions into ES2015 generators
Helper function to remap async functions to generators
Explode async and generator functions into a state machine.
A function that returns the normally hidden `GeneratorFunction` constructor
Turn async functions into ES2015 generators
ECMAScript AST recursive visitor
Turn async functions into ES2015 generators
Extra assertions on top of node's assert module
Generate JSON schema from your Typescript sources
Copy a descriptor from object A to object B
Fake data generator
Run a function exactly one time
Turn async generator functions into ES2015 generators
Check if something is a generator function
A noop logger that conforms to the Log4j interface for modules to stub out internal logging
Enable tracing by setting the TRACE environment variable to a list of the names of trace classes you want to investigate. The enabled tracing is generated in a nested format, with significant support for exceptions and debugging.
Font Icons includes a base font called EntypoRegular and easy to remember variable names. Font Icons produces a number of mixins that will allow for the easy generation of font-face declarations and icons.
This gem provides a plugin for Sprockets to transpile modern javascript using Babel. Unlike other options in the sprockets ecosystem, it works with the latest version of Babel and any plugins/presets you install. A primary use case for this gem is to facilitate incremental migration of a large Sprockets-powered javascript codebase to ES6 modules by transforming them to UMD modules that preserve your existing global variable references (hence the name: Babel + UMD = BumbleD). That said, this gem can be used for general purpose babel transpilation within the Sprockets pipeline.
Safer is an umbrella library, with components designed to make it simple to verify and improve the safety of your ruby code. There are at present three modules under the safer umbrella: [<tt>Safer::IVar</tt>] generates specially-named accessor functions for class instance variables. [<tt>Safer::Protocol</tt>] is used to provide a ruby analogue to Objective-C Protocols (which are similar to Java interfaces, but do not require inheritance). [<tt>Safer::HashProtocol</tt>] verifies that a Hash keys follow a defined format. Intended to help use of Hash objects as keyword parameters.
== DESCRIPTION: Creates a configuration controller and model that can be used to quickly create configuration table for your system so you can store system-wide variables that you'd like the user to be able to set. This gem contains a generator to create a simple configuration model, migration, and interface for your application, complete with working tests. == FEATURES * Generates the controller, model, and the associated files. * You can specify the model name and set the fields for the migrations via the generator. == SYNOPSIS: === Setup and overview Generate a new configuration system for your application by executing the generator from the root of your application. ruby script\generate rails_config_model Configuration You can also specify the model fields much like the scaffold_resource generator ruby script/generate rails_config_model Configuration contact_email:string site_name:string welcome_message:text max_number_of_events:integer Once installed, you modify the generated migration to include the fields you want to configure. There are a few defaults there to give you an idea. The generator will create a controller mounted at /configuration so you can edit your configurations. Modify this as needed to provide for security. === The Edit form The application's edit form uses the *form* helper method to auto-generate the fields. This may not be optimal and you may wish to actually write your own view instead. See app/views/configuration/edit.rhtml for more details. === Usage Configuration is simply a model for this table. It is designed to handle a single row of a table, and so additional rows cannot be created. If you have a table that looks like this: id contact_email site_name welcome_message max_number_of_events You simply grab the row from the table @configuration = Configuration.load and then grab the values out. email = @configuration.contact_email Or save new values @configuration = Configuration.load @configuration.welcome_message = "This is the default message." @configuraiton.save
Assigns a case-insensitive unique three-letter code to each record in a scope, based loosely on some other attribute of the record
Sym is a ruby library (gem) that offers both the command line interface (CLI) and a set of rich Ruby APIs, which make it rather trivial to add encryption and decryption of sensitive data to your development or deployment workflow. For additional security the private key itself can be encrypted with a user-generated password. For decryption using the key the password can be input into STDIN, or be defined by an ENV variable, or an OS-X Keychain Entry. Unlike many other existing encryption tools, Sym focuses on getting out of your way by offering a streamlined interface with password caching (if MemCached is installed and running locally) in hopes to make encryption of application secrets nearly completely transparent to the developers. Sym uses symmetric 256-bit key encryption with the AES-256-CBC cipher, same cipher as used by the US Government. For password-protecting the key Sym uses AES-128-CBC cipher. The resulting data is zlib-compressed and base64-encoded. The keys are also base64 encoded for easy copying/pasting/etc. Sym accomplishes encryption transparency by combining several convenient features: 1. Sym can read the private key from multiple source types, such as pathname, an environment variable name, a keychain entry, or CLI argument. You simply pass either of these to the -k flag — one flag that works for all source types. 2. By utilizing OS-X Keychain on a Mac, Sym offers truly secure way of storing the key on a local machine, much more secure then storing it on a file system, 3. By using a local password cache (activated with -c) via an in-memory provider such as memcached, sym invocations take advantage of password cache, and only ask for a password once per a configurable time period, 4. By using SYM_ARGS environment variable, where common flags can be saved. This is activated with sym -A, 5. By reading the key from the default key source file ~/.sym.key which requires no flags at all, 6. By utilizing the --negate option to quickly encrypt a regular file, or decrypt an encrypted file with extension .enc 7. By implementing the -t (edit) mode, that opens an encrypted file in your $EDITOR, and replaces the encrypted version upon save & exit, optionally creating a backup. 8. By offering the Sym::MagicFile ruby API to easily read encrypted files into memory. Please refer the module documentation available here: https://www.rubydoc.info/gems/sym
Inventory-Rake Inventory-Rake provides Rake¹ tasks for your Inventory². This includes tasks for cleaning up our project, compiling extensions, installing dependencies, installing and uninstalling the project itself, and creating and pushing distribution files to distribution points. ¹ See http://rake.rubyforge.org/ ² See http://disu.se/software/inventory-1.0/ § Installation Install Inventory-Rake with % gem install inventory-rake § Usage Include the following code in your ‹Rakefile›, where ‹Package› is the top-level module of your project: require 'inventory-rake-3.0' load File.expand_path('../lib/package/version.rb', __FILE__) Inventory::Rake::Tasks.define Package::Version Inventory::Rake::Tasks.unless_installing_dependencies do # Any additional tasks that your project’s dependencies provide end ‹Inventory::Rake::Tasks.define› does the heavy lifting. It takes our inventory and sets up the tasks mentioned above. We also do some additional customization of the gem specification. As we want to be able to use our Rakefile to install our dependencies for us, the rest of the Rakefile is inside the conditional #unless_installing_dependencies, which, as the name certainly implies, executes its block unless the task being run is the one that installs our dependencies. This becomes relevant if we want to, for example, set up Travis¹ integration. To do so, simply add before_script: - gem install inventory-rake -v '~> VERSION' --no-rdoc --no-ri - rake gem:deps:install to your ‹.travis.yml› file. This’ll make sure that Travis installs all development, runtime, and optional dependencies that you’ve listed in your inventory before running any tests. There’s more information in the {API documentation}² that you’ll likely want to read up on if anything is unclear. ¹ See http://travis-ci.org/ ² See http://disu.se/software/inventory-rake-1.0/api/Inventory/Rake/ § Tasks The tasks that are created if you use Inventory-Rake are: = check. = Check that the package meets its expectations. = mostlyclean. = Delete targets built by rake that are ofter rebuilt. = clean. = Delete targets built by rake; depends on mostlyclean. = distclean. = Delete all files not meant for distribution; depends on clean. = compile. = Compile all extensions; depends on each compile:name. = compile:name. = Compile extension /name/; depends on lib/path/so file. = lib/path/so. = Installed dynamic library of extension /name/ inside inventory path; depends on ext/name/so. = ext/name/so. = Dynamic library of extension /name/; depends on ext/name/Makefile and the source files of the extension. = ext/name/Makefile. = Makefile for extension /name/; depends on inventory path, ext/name/extconf.rb file, and ext/name/depend file. Will be created by extconf.rb, which may take options from environment variable name#upcase_EXTCONF_OPTIONS or ‹EXTCONF_OPTIONS› if defined. = clean:name. = Clean files built for extension /name/; depended upon by clean. = spec. = Create specifications; depends on gem:spec. = gem:spec. = Create gem specification; depends on gemspec. = gemspec (file). = Gem specification file; depends on Rakefile, README, and inventory path. = dist. = Create files for distribution; depends on gem:dist. = gem:dist. = Create gem for distribution; depends on inventory:check and gem file. = inventory:check. = Check that the inventory is correct by looking for files not listed in the inventory that match the pattern and for files listed in the inventory that don’t exist; depends on distclean. = gem (file). = Gem file; depends on files included in gem. = dist:check. = Check files before distribution; depends on dist and gem:dist:check. = gem:dist:check. = Check gem before distribution; depends on gem:dist. = deps:install. = Install dependencies on the local system; depends on gem:deps:install. = gem:deps:install. = Install dependencies in ruby gem directory. = deps:install:user. = Install dependencies for the current user; depends on gem:deps:install:user. = gem:deps:install:user. = Install dependencies in the user gem directory. = install. = Install distribution files on the local system; depends on gem:install. = gem:install. = Install gem in ruby gem directory; depends on gem:dist. = install:user. = Install distribution files for the current user; depends on gem:install:user. = gem:install:user. = Install gem in the user gem directory. = uninstall. = Delete all files installed on the local system. = gem:uninstall. = Uninstall gem from ruby gem directory. = uninstall:user. = Delete all files installed for current user. = gem:uninstall:user. = Uninstall gem from ruby gem directory. = push. = Push distribution files to distribution hubs. = gem:push. = Push gem to rubygems.org. § Financing Currently, most of my time is spent at my day job and in my rather busy private life. Please motivate me to spend time on this piece of software by donating some of your money to this project. Yeah, I realize that requesting money to develop software is a bit, well, capitalistic of me. But please realize that I live in a capitalistic society and I need money to have other people give me the things that I need to continue living under the rules of said society. So, if you feel that this piece of software has helped you out enough to warrant a reward, please PayPal a donation to now@disu.se¹. Thanks! Your support won’t go unnoticed! ¹ Send a donation: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=now@disu.se&item_name=Inventory-Rake § Reporting Bugs Please report any bugs that you encounter to the {issue tracker}¹. ¹ See https://github.com/now/inventory-rake/issues § Authors Nikolai Weibull wrote the code, the tests, the manual pages, and this README. § Licensing Inventory-Rake is free software: you may redistribute it and/or modify it under the terms of the {GNU Lesser General Public License, version 3}¹ or later², as published by the {Free Software Foundation}³. ¹ See http://disu.se/licenses/lgpl-3.0/ ² See http://gnu.org/licenses/ ³ See http://fsf.org/
Inaba SDBM Manipulator ======================= ## Introduction Inaba SDBM Manipulator is a command line tool to manipulate SDBM database. ## Operation Environment We checked good operation within following environment. - Linux(openSUSE 12.2)・Mac OS X 10.8.2 - Ruby 1.9.3 ## Architectonics - **bin** - **inaba** :: Executable script - **doc** :: Documents generated by rdoc - **lib** - **inaba** - **manipulator.rb** :: Manipulator class - **Rakefile** :: Rakefile that is used to generate gem file - **test** - **tb_manipulator.rb** :: Unit test of Manipulator ## Depended libraries - [Hakto SDBM Safe Wrapper](http://blog.quellencode.org/post/37391766923/ruby-hakto-safe-sdbm-wrapper) - [Ariete STDOUT & STDERR Capture Module](http://blog.quellencode.org/post/37625422082/ariete-stdout-stderr-capture-module) ## Install Download inaba-x.y.z.gem, then execute following command to install Inaba. `$ sudo gem install inaba-x.y.z.gem` On the other hand, you can install from RubyGems.org to use following command. `$ sudo gem install inaba` ## Tutorial ### Configuration of environment variable Set file path of SDBM database to environment variable named $INABA_DB. If target database file is named rabbit.sdb, use following command in bash. `$ export INABA_DB="rabbit.sdb"` ### Add key value pair Use **add** command to add a value to key. `$ inaba add rabbit RABBIT` Use **list** command to show key value pairs. `$ inaba list` [rabbit]:RABBIT Add more pairs. `$ inaba add bunny BUNNY` `$ inaba add hare HARE` `$ inaba list` [rabbit]:RABBIT [bunny]:BUNNY [hare]:HARE Inaba can output a pair list with CSV format. `$ inaba csv` rabbit,RABBIT bunny,BUNNY hare,HARE Also use **keys** command to list keys. `$ inaba keys` rabbit, bunny, hare, **Values** command works listing values. `$ inaba values` RABBIT, BUNNY, HARE, Use **del** command to delete key value command. `$ inaba del rabbit` `$ inaba list` [bunny]:BUNNY [hare]:HARE **Clear** command removes all key value pairs. `$ inaba clear` ## Commands reference |コマンド |引数 |説明 | |----------|-------------|------------------------------------| |**add** |*key* *value*|Add *value* to *key* | |**del** |*key* |Delete a value associated with *key*| |**list** | |Output key value pairs | |**keys** | |Output keys | |**values**| |Output values | |**csv** | |Output pairs with CSV format | |**help** | |Output command list | ## License Inaba is distributed with MIT License. See the LICENSE file to read the detail of license. ## About Author Moza USANE [http://blog.quellencode.org/](http://blog.quellencode.org/ "") mozamimy@quellencode.org
ROS Ruby Client: rosruby ======= [ROS](http://ros.org) is Robot Operating System developed by [Willow Garage](http://www.willowgarage.com/) and open source communities. This project supports ruby ROS client. You can program robots by ruby, very easily. **Homepage**: http://otl.github.com/rosruby **Git**: http://github.com/OTL/rosruby **Author**: Takashi Ogura **Copyright**: 2012 **License**: new BSD License **Latest Version**: 0.2.0 Requirements ---------- - ruby (1.8.x/1.9.x) - ROS (electric/fuerte) - ROS requires python2.7 or more libraries Let's start --------------- Install ROS and ruby first. ROS document is [http://ros.org/wiki/ROS/Installation](http://ros.org/wiki/ROS/Installation) . You can install ruby by apt. ```bash $ sudo apt-get install ruby ``` Download rosruby into your ROS_PACKAGE_PATH. ````bash $ git clone git://github.com/OTL/rosruby.git ``` please add RUBYLIB environment variable, like below (if you are using bash). ```bash $ echo "export RUBYLIB=`rospack find rosruby`/lib" >> ~/.bashrc $ source ~/.bashrc ``` To use with precompiled electric release ----------------------- If you are using precompiled ROS distro, use the msg/srv generation script (rosruby_genmsg.py) If you are using ROS from source, it requires just recompile the msg/srv packages by rosmake rosruby. ```bash $ rosrun rosruby rosruby_genmsg.py ``` This converts msg/srv to .rb which is needed by sample programs. If you want to make other packages, add package names for args. For example, ```bash $ rosrun rosruby rosruby_genmsg.py geometry_msgs nav_msgs ``` Sample Source -------------- ## Subscriber ```ruby #!/usr/bin/env ruby require 'ros' require 'std_msgs/String' node = ROS::Node.new('/rosruby/sample_subscriber') node.subscribe('/chatter', Std_msgs::String) do |msg| puts "message come! = \'#{msg.data}\'" end while node.ok? node.spin_once sleep(1) end ``` ## Publisher ```ruby #!/usr/bin/env ruby require 'ros' require 'std_msgs/String' node = ROS::Node.new('/rosruby/sample_publisher') publisher = node.advertise('/chatter', Std_msgs::String) msg = Std_msgs::String.new i = 0 while node.ok? msg.data = "Hello, rosruby!: #{i}" publisher.publish(msg) sleep(1.0) i += 1 end ``` Note ---------------- Ruby requires 'Start with Capital letter' for class or module names. So please use **S**td_msgs::String class instead of **s**td_msgs::String. Try Publish and Subscribe ---------------------- You needs three terminal as it is often for ROS users. Then you run roscore if is not running. ```bash $ roscore ``` run publisher sample ```bash $ rosrun rosruby sample_publisher.rb ``` run subscription sample ```bash $ rosrun rosruby sample_subscriber.rb ``` you can check publication by using rostopic. ```bash $ rostopic list $ rostopic echo /chatter ``` Try Service? ---------------------- ```bash $ rosrun rosruby add_two_ints_server.rb ``` run client with args ('a' and 'b' for roscpp_tutorials/TwoInts) ```bash $ rosrun rosruby add_two_ints_client.rb 10 20 ``` and more... ---------------------- You need more tools for testing, generating documentations. ```bash $ sudo apt-get install rake gem $ sudo gem install yard redcarpet simplecov ``` do all tests ------------------------- run roscore if is not running. ```bash $ roscore ``` and run the unit tests. ```bash $ roscd rosruby $ rake test ``` documents -------------------------- you can generate API documents using yard. Document generation needs yard and redcarpet. You can install these by gem command like this. ```bash $ gem install yard redcarpet ``` Then try to generate documentds. ```bash $ rake yard ``` You can access to the generated documents from [here](http://otl.github.com/rosruby/doc/).
== What's this? {ComicFury}[https://comicfury.com] is an excellent no-bullshit webcomic hosting site created and maintained by the legend Kyo. You should support them on {Patreon}[https://www.patreon.com/comicfury]! {Jekyll}[https://jekyllrb.com] is a highly regarded and widespread static site generator. It builds simple slowly-changing content into HTML files using templates. RageRender allows you to use your ComicFury templates to generate a static version of your webcomic site using Jekyll. You just supply your templates, comics and blogs, and RageRender will output a site that mimics your ComicFury site. Well, I say "mimics". Output is a static site, which means all of the interactive elements of ComicFury don't work. This includes comments, subscriptions, search, and comic management. === But why?! RageRender allows those of us who work on making changes to ComicFury site templates to test our changes before we put them live. With RageRender, you can edit your CSS, HTML templates and site settings before you upload them to ComicFury. This makes the process of testing changes quicker and makes it much more likely that you catch mistakes before any comic readers have a chance to see them. RageRender doesn't compete with the most excellent ComicFury (who's Patreon you should contribute to, as I do!) – you should continue to use ComicFury for all your day-to-day artistic rage management needs. But if you find yourself making changes to a site design, RageRender may be able to help you. == Getting started First, you need to have {Ruby}[https://www.ruby-lang.org/] and {Bundler}[https://bundle.io/] installed. The Jekyll site has {good guides on how to do that}[https://jekyllrb.com/docs/installation/] depending on your operating system. To set up a new site, open a terminal and type: mkdir mycomic && cd mycomic bundle init bundle add jekyll bundle add ragerender --group=jekyll_plugins Now you can add comics! Add the image into an <tt>images</tt> folder: mkdir images cp 'cool comic.jpg' 'images/My first page.jpg' The file name of the image will be the title of your comic page. And that's it, you added your first comic! If you want to add an author note, create a text file in a folder called <tt>_comics</tt> that has the same file name, but with a <tt>.txt</tt> extension: mkdir _comics echo "Check out my cool comic y'all!" > '_comics/My first page.txt' Or use HTML: echo "This is my <strong>first</strong> page!" > '_comics/My first page.html' Generate the site using: bundle exec jekyll build Or start a local website to see it in your browser: bundle exec jekyll serve # Now visit http://localhost:4000! === Customising your site You'll notice a few things that might be off about your site, including that the webcomic title and author name are probably not what you were expecting. You can create a configuration file to tell RageRender the important details. Put something like this in your webcomic folder and call it <tt>_config.yml</tt>: title: "My awesome webcomic!" slogan: "It's the best!" description: > My epic story about how him and her fell into a romantic polycule with they and them status: active genres: - Comedy - Romance defaults: - scope: path: '' values: author: "John smith" theme: ragerender Your webcomic now has its basic information set up. === Adding your layouts If you want to use your own layout code, then create a <tt>_layouts</tt> directory and put the contents of each of your ComicFury layout tabs in there, and then put your CSS in the main folder. The easiest way is to go to your Webcomic Management, click "Edit Layout", then in the box labelled "Useful", click "Download Layout Backup". Pass this file to RageRender, which will <tt>unpack</tt> it for you: bundle exec jekyll unpack mycomic-2025-09-13.cflxml You should end up with a full set of files like: _layouts archive.html blog-archive.html blog-display.html comic-page.html error-page.html overall.html overview.html search.html layout.css Now when you build your site, your custom templates and styles will be used instead. === Adding blogs Add your blogs into a folder called <tt>_posts</tt>: cat _posts/2025-05-29-my-new-comic.md Hey guys, welcome to my new comic! It's gonna be so sick! Note that the name of your blog post has to include the date and the title, or it'll be ignored. === Customising comics and blogs You can add {Front Matter}[https://jekyllrb.com/docs/front-matter/] to set the details of your author notes and blogs manually: --- title: "spooky comic page" date: "2025-03-05 16:20" image: "images/ghost.png" author: "Jane doe" description: "Some spooky mouseover text" keywords: [excellent, comic page, spooky] custom: # use yes and no for tickbox settings spooky: yes # use text in quotes for short texts mantra: "live long and prosper" # use indented text for long texts haiku: > Testing webcomics Now easier than ever Thanks to RageRender transcript: > The transcript contains a machine-readable version of all the text in your comic image. comments: - author: "Skippy" date: "13 Mar 2025, 3.45 PM" comment: "Wow this is so sick!" --- Your author note still goes at the end, like this! === Adding extra pages You can add extra pages just by adding new HTML files to your webcomic folder. The name of the file becomes the URL that it will use. Pages by default won't be embedded into your 'Overall' layout. You can change that and more with optional Front Matter: --- # Include this line to set the page title title: "Bonus content" # Include this line to hide the page from the navigation menu hidden: yes # Include this line to embed this page in the overall layout layout: Overall --- <h1>yo check out my bonus content!</h1> === Controlling the front page As on ComicFury you have a few options for setting the front page of you site. You control this by setting a <tt>frontpage</tt> key in your site config. - <tt>latest</tt> will display the latest comic (also the default) - <tt>first</tt> will display the first comic - <tt>chapter</tt> will display the first comic in the latest chapter - <tt>blog</tt> will display the list of blog posts - <tt>archive</tt> will display the comic archive - <tt>overview</tt> will display the comic overview (blogs and latest page) - anything else will display the extra page that has the matching <tt>slug</tt> in its Front Matter === Comics with custom HTML code You can use custom HTML code in place of an image for your comic page. Instead of creating an image, just create an HTML file in your <tt>images</tt> folder: cat '<video src="/files/my-animation.webm"></video>" > images/1.html === Multi-image comics You can add up to 12 images to each comic page on ComicFury. To do that in RageRender, add each image to an <tt>images</tt> key in your comic page: --- title: "Comic with many pages" date: "2026-04-20 16:20" images: - /images/first.png - /images/second.png - /images/third.png --- === Testing search pages Live search does not work in RageRender, as your site is statically built and can't respond to new data from the browser. However, you can simulate a search when you build the site to help test search results designs. To do that, add a `searchterm` to the search page using defaults in your `_config.yml`: defaults: - scope: path: '' layout: search values: searchterm: "my character" The search that gets performed will be somewhat similar to how ComicFury will search your comic, but may not be exactly the same. === Putting changes on ComicFury Once you're done making changes, you can <tt>pack</tt> your layout: bundle exec jekyll pack The resulting file can be uploaded to ComicFury by going to your Webcomic Management, clicking "Edit Layout", then in the box labelled "Useful", click "Restore Layout Backup". === Stuff that doesn't work Here is a probably incomplete list of things you can expect to be different about your local site compared to ComicFury: - Any comments you specify in Front Matter will be present, but you can't add new ones - Search doesn't do anything at all - Saving and loading your place in the comic isn't implemented - GET and POST variables in templates are ignored and will always be blank - Random numbers in templates will be random only once per site build, not once per page call == Without Jekyll RageRender can also be used without Jekyll to turn ComicFury templates into templates in other languages. E.g: gem install ragerender echo "[c:iscomicpage]<div>[f:js|v:comictitle]</div>[/]" > template.html ruby $(gem which ragerender/to_liquid) template.html # {% if iscomicpage %}<div>{{ comictitle | escape }}</div>{% endif %} ruby $(gem which ragerender/to_erb) template.html # <% if iscomicpage %><div><%= js(comictitle) %></div><% end %> You still need to pass the correct variables to these templates; browse {this unofficial documentation}[https://github.com/heyeinin/comicfury-documentation] or RageRender::ComicDrop etc. to see which variables work on which templates. == Get help That's not a proclamation but an invitation! Reach out if you're having trouble by {raising an issue}[https://github.com/simonwo/ragerender/issues] or posting in the ComicFury forums.
Value Value is a library for defining immutable value objects in Ruby. A value object is an object whose equality to other objects is determined by its value, not its identity, think dates and amounts of money. A value object should also be immutable, as you don’t want the date “2013-04-22” itself to change but the current date to change from “2013-04-22” to “2013-04-23”. That is, you don’t want entries in a calendar for 2013-04-22 to move to 2013-04-23 simply because the current date changes from 2013-04-22 to 2013-04-23. A value object consists of one or more attributes stored in instance variables. Value sets up an #initialize method for you that let’s you set these attributes, as, value objects being immutable, this’ll be your only chance to do so. Value also adds equality checks ‹#==› and ‹#eql?› (which are themselves equivalent), a ‹#hash› method, a nice ‹#inspect› method, and a protected attribute reader for each attribute. You may of course add any additional methods that your value object will benefit from. That’s basically all there’s too it. Let’s now look at using the Value library. § Usage You create value object class by invoking ‹#Value› inside the class (module) you wish to make into a value object class. Let’s create a class that represent points on a plane: class Point Value :x, :y end A ‹Point› is thus a value object consisting of two sub-values ‹x› and ‹y› (the coordinates). Just from invoking ‹#Value›, a ‹Point› object will have a constructor that takes two arguments to set instance variables ‹@x› and ‹@y›, equality checks ‹#==› and ‹#eql?› (which are the same), a ‹#hash› method, a nice ‹#inspect› method, and two protected attribute readers ‹#x› and ‹#y›. We can thus already creat ‹Point›s: origo = Point.new(0, 0) The default of making the attribute readers protected is often good practice, but for a ‹Point› it probably makes sense to be able to access its coordinates: class Point public(*attributes) end This’ll make all attributes of ‹Point› public. You can of course choose to only make certain attributes public: class Point public :x end Note that this public is standard Ruby functionality. Adding a method to ‹Point› is of course also possible and very much Rubyish: class Point def distance(other) Math.sqrt((other.x - x)**2 + (other.y - y)**2) end end For some value object classes you might want to support optional attributes. This is done by providing a default value for the attribute, like so: class Money Value :amount, [:currency, :USD] end Here, the ‹currency› attribute will default to ‹:USD›. You can create ‹Money› via dollars = Money.new(2) but also kronor = Money.new(2, :SEK) All required attributes must come before any optional attributes. Splat attributes are also supported: class List Value :'*elements' end empty = List.new suits = List.new(:spades, :hearts, :diamonds, :clubs) Splat attributes are optional. Finally, block attributes are also available: class Block Value :'&block' end block = Block.new{ |e| e * 2 } Block attributes are optional. Comparison beyond ‹#==› is possible by specifingy the ‹:comparable› option to ‹#Value›, listing one or more attributes that should be included in the comparison: class Vector Value :a, :b, :comparable => :a end Note that equality (‹#==› and ‹#eql?›) is always defined based on all attributes, regardless of arguments to ‹:comparable›. Here we say that comparisons between ‹Vector›s should be made between the values of the ‹a› attribute only. We can also make comparisons between all attributes of a value object: class Vector Value :a, :b, :comparable => true end To sum things up, let’s use all possible arguments to ‹#Value› at once: class Method Value :file, :line, [:name, 'unnamed'], :'*args', :'&block', :comparable => [:file, :line] end A ‹Method› consists of file and line information, a possible name, some arguments, possibly a block, and is comparable on the file and line on which they appear. Check out the {full API documentation}¹ for a more explicit description, should you need it or should you want to extend it. ¹ See http://disu.se/software/value/api/ § Financing Currently, most of my time is spent at my day job and in my rather busy private life. Please motivate me to spend time on this piece of software by donating some of your money to this project. Yeah, I realize that requesting money to develop software is a bit, well, capitalistic of me. But please realize that I live in a capitalistic society and I need money to have other people give me the things that I need to continue living under the rules of said society. So, if you feel that this piece of software has helped you out enough to warrant a reward, please PayPal a donation to now@disu.se¹. Thanks! Your support won’t go unnoticed! ¹ Send a donation: https://www.paypal.com/cgi-bin/webscr?cmd=_donations&business=now%40disu%2ese&item_name=Value § Reporting Bugs Please report any bugs that you encounter to the {issue tracker}¹. ¹ See https://github.com/now/value/issues § Authors Nikolai Weibull wrote the code, the tests, the manual pages, and this README. § Licensing Value is free software: you may redistribute it and/or modify it under the terms of the {GNU Lesser General Public License, version 3}¹ or later², as published by the {Free Software Foundation}³. ¹ See http://disu.se/licenses/lgpl-3.0/ ² See http://gnu.org/licenses/ ³ See http://fsf.org/