Skip to content

Commit

Permalink
Documentation and more tests for Lotus::Utils::ClassAttribute
Browse files Browse the repository at this point in the history
  • Loading branch information
jodosha committed Jan 2, 2014
1 parent ca18ab3 commit aba53bf
Show file tree
Hide file tree
Showing 2 changed files with 131 additions and 7 deletions.
67 changes: 61 additions & 6 deletions lib/lotus/utils/class_attribute.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
module Lotus
module Utils
# Inheritable class level variable accessors.
# (see Lotus::Utils::ClassAttribute::ClassMethods)
module ClassAttribute
def self.included(base)
base.class_eval do
Expand All @@ -8,23 +10,76 @@ def self.included(base)
end

module ClassMethods
def class_attribute(*names)
# Public: Defines a class level accessor for the given attribute(s).
#
# A value set for a superclass is automatically available by their
# subclasses, unless a different value is explicitely set within the
# inheritance chain.
#
# @param attributes [Symbol] a single or multiple attribute name(s)
#
# Examples:
#
# require 'lotus/utils/class_attribute'
#
# class Vehicle
# include Lotus::Utils::ClassAttribute
# class_attribute :engines, :wheels
#
# self.engines = 0
# self.wheels = 0
# end
#
# class Car < Vehicle
# self.engines = 1
# self.wheels = 4
# end
#
# class Airplane < Vehicle
# self.engines = 4
# self.wheels = 16
# end
#
# class SmallAirplane < Airplane
# self.engines = 2
# self.wheels = 8
# end
#
# Vehicle.engines # => 0
# Vehicle.wheels # => 0
#
# Car.engines # => 1
# Car.wheels # => 4
#
# Airplane.engines # => 4
# Airplane.wheels # => 16
#
# SmallAirplane.engines # => 2
# SmallAirplane.wheels # => 8
def class_attribute(*attributes)
(class << self; self; end).class_eval do
attr_accessor *names
attr_accessor *attributes
end

@class_attributes ||= Set.new
@class_attributes.merge(names)
class_attributes.merge(attributes)
end

# Internal: Overrides `Class#inherited`.
def inherited(subclass)
@class_attributes.each do |attr|
value = send(attr).dup rescue nil
class_attributes.each do |attr|
value = send(attr)
value = value.dup rescue value
subclass.send("#{attr}=", value)
end

super
end

private
# Internal: accessor for class attributes.
def class_attributes
@class_attributes ||= Set.new
end
end
end
end
Expand Down
71 changes: 70 additions & 1 deletion test/class_attribute_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,47 @@ class ClassAttributeTest
end

class SubclassAttributeTest < ClassAttributeTest
self.functions = [:x, :y]
class_attribute :subattribute
self.functions = [:x, :y]
self.subattribute = 42
end

class SubSubclassAttributeTest < SubclassAttributeTest
end

class Vehicle
include Lotus::Utils::ClassAttribute
class_attribute :engines, :wheels

self.engines = 0
self.wheels = 0
end

class Car < Vehicle
self.engines = 1
self.wheels = 4
end

class Airplane < Vehicle
self.engines = 4
self.wheels = 16
end

class SmallAirplane < Airplane
self.engines = 2
self.wheels = 8
end
end

after do
[:ClassAttributeTest,
:SubclassAttributeTest,
:SubSubclassAttributeTest,
:Vehicle,
:Car,
:Airplane,
:SmallAirplane].each do |const|
Object.send :remove_const, const
end
end

Expand All @@ -32,4 +72,33 @@ class SubclassAttributeTest < ClassAttributeTest
SubclassAttributeTest.values = [3,2]
ClassAttributeTest.values.must_equal([1])
end

# it 'if the subclass value changes it affects subclasses' do
# values = [3,2]
# SubclassAttributeTest.values = values
# SubclassAttributeTest.values.must_equal(values)
# SubSubclassAttributeTest.values.must_equal(values)
# end

it 'if the subclass defines an attribute it should not be available for the superclass' do
-> { ClassAttributeTest.subattribute }.must_raise(NoMethodError)
end

it 'if the subclass defines an attribute it should be available for its subclasses' do
SubSubclassAttributeTest.subattribute.must_equal 42
end

it 'preserves values within the inheritance chain' do
Vehicle.engines.must_equal 0
Vehicle.wheels.must_equal 0

Car.engines.must_equal 1
Car.wheels.must_equal 4

Airplane.engines.must_equal 4
Airplane.wheels.must_equal 16

SmallAirplane.engines.must_equal 2
SmallAirplane.wheels.must_equal 8
end
end

0 comments on commit aba53bf

Please sign in to comment.