universals 0.0.2

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 ADDED
@@ -0,0 +1,69 @@
1
+ Universals
2
+ ==========
3
+ Everyone knows that global variables are bad. Sometimes though there are values
4
+ that need to visible to all aspects of your code. Universals is a library that
5
+ provides a class that allows for the aggregation of application or library wide
6
+ data values. The Universe class becomes a centralized location for the storage
7
+ or retrieval of such values. This avoids the need to use global variables or to
8
+ pass such values down through the stack to the places they are actually used
9
+ while avoiding the namespace pollution of global variables.
10
+
11
+ Installing The Library
12
+ ----------------------
13
+ The Universals library is provided as a Ruby gem and thus can be installed with
14
+ a line such as...
15
+
16
+ $> gem install universals
17
+
18
+ Using The Library
19
+ -----------------
20
+ The library contains a single class called Universe. This class acts very much
21
+ like a Hash (with a few restrictions). Universe has mixed in Singleton and so
22
+ there should only ever be one instance of the class that can be accessed using
23
+ code such as the following...
24
+
25
+ Universals::Universe.instance
26
+
27
+ The value returned from this call can be treated like a Hash in that values can
28
+ be set under keys using the array assignment operator like so...
29
+
30
+ Universals::Universe.instance["my_value"] = "Blah-de-blah"
31
+
32
+ Note that key names must be a String object. In addition, as the class makes the
33
+ stored values available as properties on the Universe instance (see later for
34
+ more details), the key must conform to many of the rules for method names. It
35
+ can only start with a letter (upper or lower case) or an underscore and the
36
+ remainder of the name must be made up of letters, underscores or numbers. The
37
+ key may end with either '!' or '?'. Names ending with '=' or containing '[' or
38
+ ']' are explicitly excluded as they would be confusing. If you try to set a
39
+ value on a Universe instance that does not conform to these rules then you will
40
+ receive an exception for your trouble.
41
+
42
+ As was mention previously, the Universe class makes values stored within it
43
+ available as properties on the object itself. So, the value set in the previous
44
+ example could be accessed using code such as...
45
+
46
+ Universals::Universe.instance.my_value
47
+
48
+ Likewise, values can be set as if they were properties on the object. So, the
49
+ following are valid assignments...
50
+
51
+ Universals::Universe.instance.my_value = 12345
52
+ Universals::Universe.instance.other_value = "Something else."
53
+
54
+ As the Universe class is a singleton, any values assigned into it can be
55
+ retrieved anywhere. Note, that no effort has been made to make the Universe
56
+ class thread safe. It is recommended that you assign all of the values needed
57
+ to the object in a single place and thereafter treat the object as read only
58
+ if you want to use it in multi-threaded code.
59
+
60
+ Deferred Evaluation
61
+ -------------------
62
+ If you want to defer the evaluation of a value you can, instead of directly
63
+ storing the value under it's key, store a Proc that evaluates to the correct
64
+ value under the key. The next time this key is explicitly fetched from the
65
+ Universe instance the Proc will be called (with no parameters) and the value
66
+ it returns will be set under the key instead. Using this technique you can
67
+ defer the creation of items until they are actually used, allowing them to be
68
+ created at more appropriate points in the code and avoiding the possible
69
+ overhead associated with the values creation.
data/lib/universals.rb ADDED
@@ -0,0 +1,8 @@
1
+ # ! /usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2012, Peter Wood
4
+ # See the license.txt for details of the licensing of the code in this file.
5
+
6
+ require 'universals/version'
7
+ require 'universals/exceptions'
8
+ require 'universals/universe'
@@ -0,0 +1,40 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # Copyright (c), 2012 Peter Wood
4
+ # See the license.txt for details of the licensing of the code in this file.
5
+
6
+ require 'stringio'
7
+
8
+ module Universals
9
+ # This class provides the exception class used by the Universals library.
10
+ class UniversalsError < StandardError
11
+ # Attribute accessor/mutator declarations.
12
+ attr_accessor :verbose
13
+
14
+ # Constructor for the UniversalsError class.
15
+ #
16
+ # ==== Parameters
17
+ # message:: The message to be associated with the error.
18
+ # cause:: Any underlying exception to be associated with the error.
19
+ # Defaults to nil.
20
+ def initialize(message, cause=nil, verbose=true)
21
+ super(message)
22
+ @cause = cause
23
+ @verbose = verbose
24
+ end
25
+
26
+ # This method fetches a stringified interpretation of an exception.
27
+ def to_s()
28
+ text = StringIO.new
29
+ text << super
30
+ if @verbose
31
+ text << "\n" + self.backtrace.join("\n")
32
+ if !@cause.nil?
33
+ text << "\n\nCause: #{@cause}"
34
+ text << "\n" + @cause.backtrace.join("\n")
35
+ end
36
+ end
37
+ text.string
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,161 @@
1
+ #! /usr/bin/env ruby
2
+ #
3
+ # Copyright (c), 2012 Peter Wood
4
+ # See the license.txt for details of the licensing of the code in this file.
5
+
6
+ require 'singleton'
7
+
8
+ module Universals
9
+ # The Universals class includes the Ruby Singleton mixin and provides a
10
+ # single source location to store and retrieve data that is used across
11
+ # the entirety of an application or libraries code base. This avoids having
12
+ # to use global variables or to have to pass data elements around. The class
13
+ # behaves very much like a Hash, mapping keys to values. The class also
14
+ # makes the values stored within it available as properties, so all values
15
+ # stored within a Universe must be stored under String keys with names that
16
+ # conform to standard Ruby method naming criteria.
17
+ class Universe
18
+ # Mixin the singleton stuff.
19
+ include Singleton
20
+
21
+ # Mixin the enumerable stuff.
22
+ include Enumerable
23
+
24
+ # Constructor for the Universe class.
25
+ def initialize
26
+ @values = {}
27
+ end
28
+
29
+ # This method is used to check whether a property is stored under a given
30
+ # key within a Universe object.
31
+ #
32
+ # ==== Parameters
33
+ # key:: The key to perform the check for.
34
+ def has_property?(key)
35
+ @values.include?(key)
36
+ end
37
+
38
+ # This method fetches the value associated with a given key.
39
+ #
40
+ # ==== Parameters
41
+ # key:: The key for the value to be retrieved.
42
+ # default:: The default to return if the key does not exist within the
43
+ # Universe object. Defaults to nil.
44
+ def get_property(key, default=nil)
45
+ value = @values.fetch(key, default)
46
+ if value.respond_to?(:call)
47
+ value = value.call
48
+ @values[key] = value
49
+ end
50
+ value
51
+ end
52
+
53
+ # This method assigns a value under a specified key within a Universe
54
+ # object. Existing entries will be overwritten by this method.
55
+ def set_property(key, value)
56
+ validate_name(key)
57
+ @values[key] = value
58
+ end
59
+
60
+ # This method allows multiple values to be set on the Universe object
61
+ # in a single request.
62
+ #
63
+ # ==== Parameters
64
+ # values:: A Hash of the values to be set on the object. Keys should be
65
+ # adhere to the standard name requirements for the Universe
66
+ # object or an exception will be raised. Values specified in
67
+ # this way will override values already in the object.
68
+ def set(values={})
69
+ values.each {|name, value| set_property(name, value)}
70
+ end
71
+
72
+ # Implementation of the each() method for the Universe class.
73
+ def each(&block)
74
+ @values.each(&block)
75
+ end
76
+
77
+ # This method fetches a count of the number of items held within an
78
+ # instance of the Universe class.
79
+ def size
80
+ @values.size
81
+ end
82
+
83
+ # This method fetches the key associated with a value stored in the
84
+ # Universe instance.
85
+ #
86
+ # ==== Parameters
87
+ # value:: The value to retrieve the key for.
88
+ def key(value)
89
+ @values.key(value)
90
+ end
91
+
92
+ # This method fetches a collection of the keys stored within a Universe
93
+ # instance.
94
+ def keys
95
+ @values.keys
96
+ end
97
+
98
+ # This method fetches a collection of the values stored within a Universe
99
+ # instance.
100
+ def values
101
+ @values.values
102
+ end
103
+
104
+ # This method deletes all entries from a Universe instance.
105
+ def clear
106
+ @values.clear
107
+ end
108
+
109
+ # This method overrides the default respond_to?() method to provide
110
+ # customer property handling for Universe objects.
111
+ #
112
+ # ==== Parameters
113
+ # name:: The name of the method to perform the check for.
114
+ def respond_to?(name)
115
+ @hash.include?(name) || super(name)
116
+ end
117
+
118
+ # This method is invoked whenever a method invocation takes place
119
+ # against a Universe object but an existing explicit method cannot be
120
+ # found to meet the call.
121
+ #
122
+ # ==== Parameters
123
+ # name:: The name of the method invoked.
124
+ # arguments:: A collection of the arguments passed to the method call.
125
+ # block:: Any block associated with the method call.
126
+ def method_missing(name, *arguments, &block)
127
+ if @values.include?(name.to_s)
128
+ get_property(name.to_s)
129
+ elsif name.to_s[-1, 1] == "="
130
+ property = name.to_s
131
+ property = property[0, property.length - 1]
132
+ set_property(property, arguments[0])
133
+ self
134
+ else
135
+ super
136
+ end
137
+ end
138
+
139
+ # Class aliases.
140
+ alias :[] :get_property
141
+ alias :[]= :set_property
142
+ alias :include? :has_property?
143
+
144
+ private
145
+
146
+ # This method is used internally by the class to determine whether a key
147
+ # is valid for use with a Universe object.
148
+ def validate_name(name)
149
+ if !name.kind_of?(String)
150
+ raise UniversalsError.new("The key '#{name}' cannot be used in a "\
151
+ "Universe object as it is not a String.")
152
+ end
153
+
154
+ if /^[a-zA-Z_]+[a-zA-Z_0-9]*[\?!]?$/.match(name).nil?
155
+ raise UniversalsError.new("The key '#{name}' cannot be used in a "\
156
+ "Universe object as it is not a valid "\
157
+ "method name.")
158
+ end
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,11 @@
1
+ # ! /usr/bin/env ruby
2
+ #
3
+ # Copyright (c) 2012, Peter Wood
4
+ # See the license.txt for details of the licensing of the code in this file.
5
+
6
+ module Universals
7
+ MAJOR_VERSION = 0
8
+ MINOR_VERSION = 0
9
+ BUILD_VERSION = 2
10
+ VERSION = "#{MAJOR_VERSION}.#{MINOR_VERSION}.#{BUILD_VERSION}"
11
+ end
data/license.txt ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License
2
+
3
+ Copyright (c) 2011 Peter Wood
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.
metadata ADDED
@@ -0,0 +1,52 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: universals
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.0.2
5
+ prerelease:
6
+ platform: ruby
7
+ authors:
8
+ - Black North
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2013-01-21 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Universals provides a simple singleton class that can be used to store
15
+ and retrieve data that is used throughout and application and thereby avoid global
16
+ variables.
17
+ email: ruby@blacknorth.com
18
+ executables: []
19
+ extensions: []
20
+ extra_rdoc_files: []
21
+ files:
22
+ - lib/universals.rb
23
+ - lib/universals/version.rb
24
+ - lib/universals/universe.rb
25
+ - lib/universals/exceptions.rb
26
+ - license.txt
27
+ - README
28
+ homepage: https://github.com/free-beer/Universals
29
+ licenses: []
30
+ post_install_message:
31
+ rdoc_options: []
32
+ require_paths:
33
+ - lib
34
+ required_ruby_version: !ruby/object:Gem::Requirement
35
+ none: false
36
+ requirements:
37
+ - - ! '>='
38
+ - !ruby/object:Gem::Version
39
+ version: '0'
40
+ required_rubygems_version: !ruby/object:Gem::Requirement
41
+ none: false
42
+ requirements:
43
+ - - ! '>='
44
+ - !ruby/object:Gem::Version
45
+ version: '0'
46
+ requirements: []
47
+ rubyforge_project:
48
+ rubygems_version: 1.8.24
49
+ signing_key:
50
+ specification_version: 3
51
+ summary: A library to provide a source for application wide data.
52
+ test_files: []