Sean Huber variables

Build Status Code Climate Coverage

Variable objects for class and instance variables

Ruby already has Method objects, why not Variable objects as well?

Installation

gem install variables

Requirements

Ruby 1.8.7+

Usage

Let's experiment with a simple User class.

class User
  def initialize(name)
    @name = name
  end
end

Objects can have any number of instance variables.

user = User.new('Bob')              #=> #<User:0x007f8f6a84aa98>
user.instance_variable_get('@name') #=> "Bob"

Similar to Object#method, a handy instance_variable method is available for us to use.

name = user.instance_variable(:name) #=> #<InstanceVariable: #<User>@name>

But unlike Object#method, this method does not require a variable to actually be defined.

undefined = user.instance_variable(:undefined) #=> #<InstanceVariable: #<User>@undefined>

We can check if a variable is defined by using the defined? method.

name.defined?      #=> true
undefined.defined? #=> false

Once we have a Variable object, we can get its value.

name.get      #=> "Bob"
undefined.get #=> nil

Similar to Hash#fetch, the fetch method raises an exception if the variable is undefined.

name.fetch      #=> "Bob"
undefined.fetch #=> Variables::UndefinedVariable - undefined variable "undefined"

The fetch method optionally accepts a default value to return if the variable is undefined.

name.fetch(:default)      #=> "Bob"
undefined.fetch(:default) #=> :default

Default values can also be defined with a block which is yielded the Variable name.

name.fetch { |name| "#{name}-default" }      #=> "Bob"
undefined.fetch { |name| "#{name}-default" } #=> "@undefined-default"

We can update a Variable value by using the set method.

name.set('Steve')                   #=> "Steve"
user.instance_variable_get('@name') #=> "Steve"

The replace method is similar to set, but it returns the old value instead of the new value.

name.replace('Bob')                 #=> "Steve"
user.instance_variable_get('@name') #=> "Bob"

We can even temporarily replace a value for the duration of a block.

user.instance_variable_get('@name') #=> "Bob"

value = name.replace('Steve') do
  user.instance_variable_get('@name') #=> "Steve"

  'we can return a value here'
end

user.instance_variable_get('@name') #=> "Bob"

value.inspect #=> "we can return a value here"

Everything that we do with instance variables can be done with class variables as well!

example = User.class_variable(:example) #=> #<ClassVariable: User@@name>

example.defined? #=> false

example.set('testing') #=> "testing"

User.class_variable_get('@@example') #=> "testing"

Testing

bundle exec rspec

Contributing

  • Fork the project.
  • Make your feature addition or bug fix.
  • Add tests for it. This is important so I don't break it in a future version unintentionally.
  • Commit, do not mess with Rakefile, version, or history. (if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
  • Send me a pull request. Bonus points for topic branches.

License

MIT - Copyright © 2015 Sean Huber