├── meta ├── license ├── version ├── created ├── package ├── project ├── released ├── requires ├── authors ├── summary ├── homepage ├── repository ├── contact └── abstract ├── .config └── syckle │ ├── automatic │ └── defaults │ └── rdoc │ └── template ├── .gitignore ├── task ├── grancher.syckle ├── ridoc.syckle ├── syntax.syckle ├── box.syckle ├── notes.syckle ├── stats.syckle ├── rdoc.syckle ├── testrb.syckle ├── vclog.syckle ├── rubyforge.syckle └── email.syckle ├── HISTORY ├── MANIFEST ├── LICENSE ├── README ├── lib └── inheritor.rb └── test └── test_inheritor.rb /meta/license: -------------------------------------------------------------------------------- 1 | MIT 2 | -------------------------------------------------------------------------------- /meta/version: -------------------------------------------------------------------------------- 1 | 1.0.1 2 | -------------------------------------------------------------------------------- /meta/created: -------------------------------------------------------------------------------- 1 | 2005-08-01 2 | -------------------------------------------------------------------------------- /meta/package: -------------------------------------------------------------------------------- 1 | inheritor 2 | -------------------------------------------------------------------------------- /meta/project: -------------------------------------------------------------------------------- 1 | rubyworks 2 | -------------------------------------------------------------------------------- /meta/released: -------------------------------------------------------------------------------- 1 | 2009-10-11 2 | -------------------------------------------------------------------------------- /meta/requires: -------------------------------------------------------------------------------- 1 | facets 2 | -------------------------------------------------------------------------------- /.config/syckle/automatic: -------------------------------------------------------------------------------- 1 | true 2 | -------------------------------------------------------------------------------- /meta/authors: -------------------------------------------------------------------------------- 1 | Thomas Sawyer 2 | -------------------------------------------------------------------------------- /meta/summary: -------------------------------------------------------------------------------- 1 | Inheritable Class Attributes 2 | -------------------------------------------------------------------------------- /.config/syckle/defaults/rdoc/template: -------------------------------------------------------------------------------- 1 | redfish 2 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | .cache 2 | log 3 | doc/rdoc 4 | doc/ri 5 | -------------------------------------------------------------------------------- /meta/homepage: -------------------------------------------------------------------------------- 1 | http://rubyworks.github.com/inheritor 2 | -------------------------------------------------------------------------------- /meta/repository: -------------------------------------------------------------------------------- 1 | http://github.com/rubyworks/inheritor.git 2 | -------------------------------------------------------------------------------- /meta/contact: -------------------------------------------------------------------------------- 1 | http://googlegroups.com/group/rubyworks-mailinglist/ 2 | -------------------------------------------------------------------------------- /task/grancher.syckle: -------------------------------------------------------------------------------- 1 | grancher: 2 | service: Grancher 3 | active: true 4 | 5 | -------------------------------------------------------------------------------- /task/ridoc.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | ridoc: 3 | service: RIDoc 4 | include: ~ 5 | exclude: ~ 6 | active : true 7 | 8 | -------------------------------------------------------------------------------- /task/syntax.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | syntax: 3 | service : Syntax 4 | loadpath : ~ 5 | exclude : ~ 6 | active : false 7 | 8 | -------------------------------------------------------------------------------- /task/box.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | rubygems: 3 | service: Box 4 | types : [gem, gz] 5 | include: [bin, demo, lib, meta, test, "[A-Z]*"] 6 | exclude: ~ 7 | active : true 8 | -------------------------------------------------------------------------------- /task/notes.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | notes: 3 | service : Notes 4 | loadpath : ~ 5 | labels : ~ 6 | output : ~ 7 | format : ~ 8 | active : false 9 | 10 | -------------------------------------------------------------------------------- /task/stats.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | codestats: 3 | service : Stats 4 | title : ~ 5 | loadpath : ~ 6 | exclude : ~ 7 | output : ~ 8 | active : true 9 | 10 | -------------------------------------------------------------------------------- /task/rdoc.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | rdoc: 3 | service : RDoc 4 | template : redfish 5 | include : ~ 6 | exclude : ~ 7 | main : ~ 8 | extra : ~ 9 | active : true 10 | 11 | -------------------------------------------------------------------------------- /task/testrb.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | testunit: 3 | service : Testrb 4 | tests : ~ 5 | exclude : ~ 6 | loadpath : ~ 7 | requires : ~ 8 | live : false 9 | active : false 10 | 11 | -------------------------------------------------------------------------------- /task/vclog.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | vclog: 3 | service : VClog 4 | format : html # xml, txt 5 | layout : rel # gnu 6 | typed : false 7 | output : ~ 8 | active : false 9 | 10 | -------------------------------------------------------------------------------- /HISTORY: -------------------------------------------------------------------------------- 1 | = HISTORY 2 | 3 | == 1.0.0 // 2009-07-01 4 | 5 | Initial stand-alone release as ported from Ruby Facets. 6 | 7 | Changes: 8 | 9 | * 1 Major Enhancement 10 | 11 | * Ported from Ruby Facets. 12 | 13 | -------------------------------------------------------------------------------- /task/rubyforge.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | rubyforge: 3 | service : Rubyforge 4 | unixname: <%= project %> 5 | groupid : ~ 6 | package : <%= package %> 7 | sitemap: 8 | doc/rdoc: <%= package %> 9 | active : false 10 | 11 | -------------------------------------------------------------------------------- /MANIFEST: -------------------------------------------------------------------------------- 1 | #!mast lib meta test [A-Z]* 2 | lib 3 | lib/inheritor.rb 4 | meta 5 | meta/abstract 6 | meta/authors 7 | meta/created 8 | meta/homepage 9 | meta/license 10 | meta/package 11 | meta/project 12 | meta/released 13 | meta/repository 14 | meta/summary 15 | meta/version 16 | test 17 | test/test_inheritor.rb 18 | LICENSE 19 | README 20 | HISTORY 21 | -------------------------------------------------------------------------------- /meta/abstract: -------------------------------------------------------------------------------- 1 | Inheritor providse a means to store and inherit data via 2 | the class heirarchy. An inheritor creates two methods 3 | one named after for the +key+ that provides a reader. And 4 | one named after +key!+ which provides the writer. Because 5 | of the unique nature of inheritor, the reader can not be used 6 | to modify the underlying store or it will not be passed on 7 | to the descendents. 8 | 9 | -------------------------------------------------------------------------------- /task/email.syckle: -------------------------------------------------------------------------------- 1 | --- 2 | announce: 3 | service : Email 4 | file : ~ 5 | subject : ~ 6 | mailto : ruby-talk@ruby-lang.org 7 | from : ENV[EMAIL_ACCOUNT] 8 | server : ENV[EMAIL_SERVER] 9 | port : ENV[EMAIL_PORT] 10 | account : ENV[EMAIL_ACCOUNT] 11 | domain : ENV[EMAIL_DOMAIN] 12 | login : ENV[EMAIL_LOGIN] 13 | secure : ENV[EMAIL_SECURE] 14 | active : true 15 | 16 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License 2 | 3 | Copyright (c) 2009 Thomas Sawyer 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in 13 | all copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN 21 | THE SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /README: -------------------------------------------------------------------------------- 1 | = Inheritor 2 | 3 | * http://rubyworks.github.com/inheritor 4 | * http://github.com/rubyworks/inheritor 5 | 6 | 7 | == DESCRIPTION 8 | 9 | Inheritor provides a means to store and inherit data along the class 10 | heirarchy. An inheritor creates two methods, one named after for the 11 | +key+ that provides a reader, and one named +key!+ which provides 12 | the writer. Because of the unique nature of Inheritor, the reader 13 | cannot be used to modify the underlying store b/c it is a calculated 14 | attribute, thus any modifications to the result would not be passed on 15 | to the descendents. 16 | 17 | The most notable feature of Inheritor is that it is dynamic. Unlike other 18 | solutions, such as ActiveSupport's +class_inheritable_accessor+, Inheritor 19 | dynamically generates the inherited value whenever the reader is called, 20 | as opposed to copying the parents variable value upon class creation or 21 | some other specific trigger. 22 | 23 | 24 | == FEATURES/ISSUES 25 | 26 | * Create inheritable attributes. 27 | * Works with modules, providing module method inheritance. 28 | * Easily handles any data and inheritance type. 29 | 30 | 31 | == RELEASE NOTES 32 | 33 | Please see HISTORY file. 34 | 35 | 36 | == SYNOPSIS 37 | 38 | To create an inheritable class variable provide the #inheritor method 39 | with the name of the variable, it's initial value, and the methdod 40 | to be used to process inheritence from descendent to descendent. 41 | 42 | class X 43 | inheritor :foo, [], :+ 44 | end 45 | 46 | class Y < X 47 | end 48 | 49 | X.x! << :a 50 | X.x => [:a] 51 | Y.x => [:a] 52 | 53 | Y.x! << :b 54 | X.x => [:a] 55 | Y.x => [:a, :b] 56 | 57 | 58 | == HOW TO INSTALL 59 | 60 | To install with RubyGems simply open a console and type: 61 | 62 | gem install inheritor 63 | 64 | Local installation requires Setup.rb (gem install setup), 65 | then download the tarball package and type: 66 | 67 | tar -xvzf inheritor-1.0.0.tgz 68 | cd inheritor-1.0.0 69 | sudo setup.rb all 70 | 71 | Windows users use 'ruby setup.rb all'. 72 | 73 | 74 | == COPYING 75 | 76 | (MIT License) 77 | 78 | Copyright (c) 2004 Thomas Sawyer 79 | 80 | This program is ditributed unser the terms of the MIT license. 81 | 82 | See LICENSE or COPYING file for details. 83 | 84 | -------------------------------------------------------------------------------- /lib/inheritor.rb: -------------------------------------------------------------------------------- 1 | # Inheritor, Copyright (c) 2005 Thomas Sawyer 2 | 3 | require 'facets/class_extension' 4 | 5 | class Object 6 | 7 | # Create an inheritor "class attribute". 8 | # 9 | # Inheritor providse a means to store and inherit data via 10 | # the class heirarchy. An inheritor creates two methods 11 | # one named after the key that provides a reader. And one 12 | # named after key! which provides the writer. (Because of 13 | # the unique nature of inheritor the reader and writer 14 | # can't be the same method.) 15 | # 16 | # class X 17 | # inheritor :foo, [], :+ 18 | # end 19 | # 20 | # class Y < X 21 | # end 22 | # 23 | # X.x! << :a 24 | # X.x => [:a] 25 | # Y.x => [:a] 26 | # 27 | # Y.x! << :b 28 | # X.x => [:a] 29 | # Y.x => [:a, :b] 30 | # 31 | # It is interesting to note that the inheritor would be much less useful 32 | # if Ruby allowed modules to be "inherited" at the class-level, or conversely 33 | # that the class-level is handled as a module instead. Because if it were, 34 | # using #super at the class-level would make it fairly easy to implement 35 | # this behavior by hand. 36 | # 37 | def inheritor(key, obj, op=nil) 38 | 39 | # inhertiance operator 40 | op = op ? op.to_sym : :add #NOTE: why #add ? 41 | 42 | # inheritor store a this level 43 | instance_variable_set("@#{key}", obj) 44 | 45 | #base = self 46 | deflambda = lambda do 47 | 48 | define_method( key ) do 49 | defined?(super) ? super.__send__(op,obj) : obj.dup 50 | end 51 | 52 | define_method( "#{key}!" ) do 53 | if instance_variable_defined?("@#{key}") 54 | instance_variable_get("@#{key}") 55 | else 56 | inheritor(key, obj.class.new, op) 57 | end 58 | # -- old version -- 59 | #if instance_variables.include?("@#{key}") 60 | # instance_variable_get("@#{key}") 61 | #else 62 | # if self != base 63 | # inheritor( key, obj.class.new, op ) 64 | # end 65 | #end 66 | end 67 | end 68 | 69 | # TODO: This is an issue if you try to include a module 70 | # into Module or Class itself. How to fix? 71 | 72 | # if the object is a module (not a class or other object) 73 | if self == Class or self == Module 74 | class_eval(&deflambda) 75 | elsif is_a?(Class) 76 | (class << self; self; end).class_eval(&deflambda) 77 | elsif is_a?(Module) 78 | #class_inherit &deflambda 79 | extend class_extension(&deflambda) 80 | else # other Object 81 | (class << self; self; end).class_eval(&deflambda) 82 | end 83 | 84 | obj 85 | end 86 | 87 | end 88 | -------------------------------------------------------------------------------- /test/test_inheritor.rb: -------------------------------------------------------------------------------- 1 | # Test inheritor.rb 2 | 3 | require 'inheritor' 4 | require 'test/unit' 5 | 6 | #class TC_Inheritor_01 < Test::Unit::TestCase 7 | # def setup 8 | # @a = [1] 9 | # @i = Inheritor.new( @a, [2], :+ ) 10 | # end 11 | # def test_01_001 12 | # assert_equal([2],@i) 13 | # end 14 | # def test_01_002 15 | # assert_equal([1,2],@i.inheritance) 16 | # end 17 | #end 18 | 19 | class TC_Inheritor_02 < Test::Unit::TestCase 20 | class C 21 | inheritor :koko, [1], :+ 22 | end 23 | class D < C 24 | inheritor :koko, [2], :+ 25 | end 26 | 27 | def test_02_001 28 | assert_equal( [1], C.koko! ) 29 | end 30 | def test_02_002 31 | assert_equal( [1], C.koko ) 32 | end 33 | def test_02_003 34 | assert_equal( [2], D.koko! ) 35 | end 36 | def test_02_004 37 | assert_equal( [1,2], D.koko ) 38 | end 39 | end 40 | 41 | class TC_Inheritor_03 < Test::Unit::TestCase 42 | class C 43 | inheritor :koko, [1], :+ 44 | end 45 | class D < C 46 | end 47 | 48 | def test_03_001 49 | assert_equal( [1], C.koko! ) 50 | end 51 | def test_03_002 52 | assert_equal( [1], C.koko ) 53 | end 54 | def test_03_003 55 | assert_equal( [], D.koko! ) 56 | end 57 | def test_03_004 58 | assert_equal( [1], D.koko ) 59 | end 60 | end 61 | 62 | class TC_Inheritor_04 < Test::Unit::TestCase 63 | class X 64 | inheritor :x, {:a=>1}, :merge 65 | end 66 | module M 67 | inheritor :x, {:b=>2}, :merge 68 | end 69 | class Y < X 70 | include M 71 | inheritor :x, {:c=>3}, :merge 72 | end 73 | 74 | def test_04_001 75 | assert_equal( {:a=>1}, X.x ) 76 | end 77 | def test_04_002 78 | assert_equal( 2, M.x[:b] ) 79 | end 80 | def test_04_003 81 | assert_equal( {:a=>1,:b=>2,:c=>3}, Y.x ) 82 | end 83 | def test_04_004 84 | assert_equal( 1, X.x[:a] ) 85 | assert_equal( nil, X.x[:b] ) 86 | assert_equal( nil, X.x[:c] ) 87 | end 88 | def test_04_005 ; assert_equal( 1, Y.x[:a] ) ; end 89 | def test_04_006 ; assert_equal( 2, Y.x[:b] ) ; end 90 | def test_04_007 ; assert_equal( 3, Y.x[:c] ) ; end 91 | def test_04_008 92 | Y.x![:d] = 4 93 | assert_equal( 4, Y.x[:d] ) 94 | end 95 | end 96 | 97 | class TC_Inheritor_05 < Test::Unit::TestCase 98 | class C 99 | inheritor :relations, [], :concat 100 | end 101 | class D < C 102 | #inheritor :relations, [], :concat 103 | end 104 | 105 | C.relations! << 1 106 | C.relations! << 2 107 | D.relations! << 3 108 | 109 | def test_05_001 110 | assert_equal( [1,2], C.relations ) 111 | assert_equal( [1,2,3], D.relations ) 112 | end 113 | end 114 | 115 | class TC_Inheritor_06 < Test::Unit::TestCase 116 | module MM 117 | inheritor :koko, [], :+ 118 | koko! << 1 119 | end 120 | class CC1 121 | include MM 122 | #inheritor :koko, [], :+ 123 | koko! << 2 124 | koko! << 3 125 | end 126 | class CC2 127 | include MM 128 | #inheritor :koko, [], :+ 129 | koko! << 4 130 | end 131 | 132 | def test_06_001 133 | assert_equal( [1], MM.koko ) 134 | end 135 | def test_06_002 136 | assert_equal( [1,2,3], CC1.koko ) 137 | end 138 | def test_06_003 139 | assert_equal( [1,4], CC2.koko ) 140 | end 141 | end 142 | 143 | --------------------------------------------------------------------------------