composite 0.3.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- data/README +44 -0
- data/lib/composite.rb +41 -0
- data/test/test_composite.rb +41 -0
- metadata +48 -0
data/README
ADDED
@@ -0,0 +1,44 @@
|
|
1
|
+
== Composite version 0.3.0
|
2
|
+
|
3
|
+
=== Overview
|
4
|
+
Mixin module to create classes where the 'whole'
|
5
|
+
object is seen as being composed of 'parts'.
|
6
|
+
Allowing access to some object both as composed
|
7
|
+
as well as in parts. The typical use case is a subclass
|
8
|
+
of String that is used to deal with a string that
|
9
|
+
has a certain format and supports accessor methods
|
10
|
+
to its parts, for example an URI/IRI, a BCP 47 language tag,
|
11
|
+
a name or address in a certain format, and so on.
|
12
|
+
|
13
|
+
=== Usage
|
14
|
+
class myComposite < BaseClass
|
15
|
+
def initialize (n)
|
16
|
+
super(n)
|
17
|
+
end
|
18
|
+
part :part1, :part2, ...
|
19
|
+
def compose
|
20
|
+
# calculate a value for the BaseClass object
|
21
|
+
# from @part1, @part2,...
|
22
|
+
end
|
23
|
+
def decompose
|
24
|
+
# calculate @part1, @part2,...
|
25
|
+
# from the value of BaseClass
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
The above provides methods part1, part1=, part2, part2=,...
|
30
|
+
for access to parts.
|
31
|
+
|
32
|
+
=== Performance
|
33
|
+
decompose is called on each access (both read and write)
|
34
|
+
to any of the parts, because it's impossible to predict
|
35
|
+
when the BaseClass object changes (all methods of the
|
36
|
+
BaseClass would need to be patched). If decompose takes
|
37
|
+
time, it may be possible to speed things up by saving a
|
38
|
+
copy of the BaseClass object, or its hash, internally
|
39
|
+
and do a comparison to see if anything has changed.
|
40
|
+
|
41
|
+
=== Copyright
|
42
|
+
Copyright (c) 2007 Martin J. Du"rst (duerst@it.aoyama.ac.jp)
|
43
|
+
Licensed under the same terms as Ruby. Absolutely no warranty.
|
44
|
+
(see http://www.ruby-lang.org/en/LICENSE.txt)
|
data/lib/composite.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
# :include: ../README
|
2
|
+
|
3
|
+
module Composite
|
4
|
+
def self.included(base) #:nodoc:
|
5
|
+
super
|
6
|
+
base.extend(ClassMethods)
|
7
|
+
end
|
8
|
+
|
9
|
+
# Assumes composite is up to date, and decomposes into parts.
|
10
|
+
# Virtual method, needs to be overwritten where module is included.
|
11
|
+
def decompose; raise NotImplementedError; end
|
12
|
+
# Assumes parts are up to date, and composes from parts.
|
13
|
+
# Virtual method, needs to be overwritten where module is included.
|
14
|
+
def compose; raise NotImplementedError; end
|
15
|
+
|
16
|
+
# Internal module to extend class that includes this module.
|
17
|
+
# This trick of getting around the fact that module methods
|
18
|
+
# aren't inherited when a module is included is from:
|
19
|
+
# http://wiki.rubyonrails.org/rails/pages/SimpleAccessControlExample
|
20
|
+
module ClassMethods
|
21
|
+
# Metaprogramming keyword to define 'part' instance variables
|
22
|
+
# that automatically call compose/decompose on access.
|
23
|
+
def part (*parts, &block)
|
24
|
+
parts.each do |aPart|
|
25
|
+
set_method = (aPart.to_s+'=').to_sym
|
26
|
+
get_method = aPart.to_sym
|
27
|
+
instance = ('@'+aPart.to_s).to_sym
|
28
|
+
send :define_method, get_method do ||
|
29
|
+
decompose
|
30
|
+
instance_variable_get instance
|
31
|
+
end
|
32
|
+
send :define_method, set_method do |a|
|
33
|
+
decompose
|
34
|
+
#call.block
|
35
|
+
instance_variable_set instance, a
|
36
|
+
compose
|
37
|
+
end
|
38
|
+
end
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
@@ -0,0 +1,41 @@
|
|
1
|
+
# some unit tests for the Composite module
|
2
|
+
# assumes that names are "Given_Name Family_Name",
|
3
|
+
# which is hopelessly non-internationalized, sorry!
|
4
|
+
#
|
5
|
+
# Copyright 2007 Martin J. Du"rst (duerst@it.aoyama.ac.jp);
|
6
|
+
# available under the same licence as Ruby itself
|
7
|
+
# (see http://www.ruby-lang.org/en/LICENSE.txt)
|
8
|
+
|
9
|
+
$:.unshift File.join(File.dirname(__FILE__), "..", "lib")
|
10
|
+
require 'Composite'
|
11
|
+
|
12
|
+
class Name < String
|
13
|
+
include Composite
|
14
|
+
def initialize (name)
|
15
|
+
super(name)
|
16
|
+
end
|
17
|
+
part :given, :family
|
18
|
+
def compose
|
19
|
+
replace(@given+' '+@family)
|
20
|
+
end
|
21
|
+
def decompose
|
22
|
+
@given, @family = self.split(' ')
|
23
|
+
end
|
24
|
+
end
|
25
|
+
|
26
|
+
require 'test/unit'
|
27
|
+
class TestComposite < Test::Unit::TestCase
|
28
|
+
def test_simple
|
29
|
+
n = Name.new('John Smith')
|
30
|
+
assert_equal('John', n.given)
|
31
|
+
assert_equal('Smith', n.family)
|
32
|
+
n.given = 'Jane'
|
33
|
+
assert_equal('Jane Smith', n)
|
34
|
+
n.family = 'Miller'
|
35
|
+
assert_equal('Jane Miller', n)
|
36
|
+
n.given = 'Bill'
|
37
|
+
assert_equal('Bill Miller', n)
|
38
|
+
n.given += '-Willy'
|
39
|
+
assert_equal('Bill-Willy Miller', n)
|
40
|
+
end
|
41
|
+
end
|
metadata
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
rubygems_version: 0.9.2
|
3
|
+
specification_version: 1
|
4
|
+
name: composite
|
5
|
+
version: !ruby/object:Gem::Version
|
6
|
+
version: 0.3.0
|
7
|
+
date: 2007-03-22 00:00:00 +09:00
|
8
|
+
summary: metaprogramming module to (de)compose a base class into/from parts
|
9
|
+
require_paths:
|
10
|
+
- lib
|
11
|
+
email: duerst@it.aoyama.ac.jp
|
12
|
+
homepage:
|
13
|
+
rubyforge_project:
|
14
|
+
description:
|
15
|
+
autorequire: composite
|
16
|
+
default_executable:
|
17
|
+
bindir: bin
|
18
|
+
has_rdoc: true
|
19
|
+
required_ruby_version: !ruby/object:Gem::Version::Requirement
|
20
|
+
requirements:
|
21
|
+
- - ">"
|
22
|
+
- !ruby/object:Gem::Version
|
23
|
+
version: 0.0.0
|
24
|
+
version:
|
25
|
+
platform: ruby
|
26
|
+
signing_key:
|
27
|
+
cert_chain:
|
28
|
+
post_install_message:
|
29
|
+
authors:
|
30
|
+
- Martin J. Du"rst
|
31
|
+
files:
|
32
|
+
- lib/composite.rb
|
33
|
+
- test/test_composite.rb
|
34
|
+
- README
|
35
|
+
test_files:
|
36
|
+
- test/test_composite.rb
|
37
|
+
rdoc_options: []
|
38
|
+
|
39
|
+
extra_rdoc_files:
|
40
|
+
- README
|
41
|
+
executables: []
|
42
|
+
|
43
|
+
extensions: []
|
44
|
+
|
45
|
+
requirements: []
|
46
|
+
|
47
|
+
dependencies: []
|
48
|
+
|