Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Just an implementation of Visitor design patter in Ruby.
Branch: master
Pull request Compare This branch is even with dmitriy-kiriyenko:master.

Fetching latest commit…

Cannot retrieve the latest commit at this time

Failed to load latest commit information.
lib
spec
.gitignore
.rspec
.rvmrc
.travis.yml
Gemfile
MIT-LICENCE
README.md
Rakefile
visitor.gemspec

README.md

Visitor

Build
Status Code Climate

Sometimes in Ruby you need to attach the same method to various spectre of classes. This is usually required for conversion methods when you define #to_big_decimal or #to_lua on Numeric, String, Object, etc. While this way of doing things is the most Rubyish one, we don't like reopening core classes. More, there is also a problem on how to organize the code - by method or by class. Usually, as more natural, by class is picked and logically one method gets split into classes. In the meantime, If you add just one method in a gem, you reopen all core classes. In each specific gem.

Double dispatch to the rescue!

Here we add a base class to define visitors. The core idea we owe to Aaron "Tendelove" Patterson's article The Double Dispatch Dance. Read it - it'll give you the whole idea. We just added an option to define visitors by string class name to aviod possible missing constants and added a convenient add_accept_method! method.

Installation

# In your Gemfile
gem 'visitor'

Usage

class ToJsVisitor < Visitor::Base
  # Add Object#to_js as an accept method for this visitor
  add_accept_method! :to_js, :to => [Object]

  visitor_for String do |string|
    if string =~ /`([^`]+)`/
      $1
    else
      "\"#{string}\""
    end
  end

  # This will capture all Numeric descendants
  # Even if Numeric was a module, being included to a class
  visitor_for Numeric do |number|
    number.to_s
  end

  visitor_for NilClass do |_|
    'undefined'
  end

  visitor_for Enumerable do |array|
    "[#{array.map {|o| visit o}.join(", ")}]"
  end

  visitor_for Hash do |hash|
    "{#{hash.to_a.map{|key, value| "#{key}: #{visit value}"}.join(', ')}}"
  end

  # This is kind of default visitor
  visitor_for Object do |o|
    o.to_s
  end

end

This is the real code example from to_js gem.

TODOs

  • Add documentation. While it's missing - read the tests.

Authors

Contribution

  • Use and give feedback
  • Submit an issue
  • Provide a pull request
  • Bring your testimony on why visitors in Ruby suck and are totally unnecessary

Tests

  • Run with rake
  • Tested in 1.8.7, 1.9.2, 1.9.3. Thank you, travic-ci guys, you are awesome.

Licence

MIT (more about it)

Credits

Something went wrong with that request. Please try again.