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.
Files changed (4) hide show
  1. data/README +44 -0
  2. data/lib/composite.rb +41 -0
  3. data/test/test_composite.rb +41 -0
  4. 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)
@@ -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
+