universals 0.0.2

Sign up to get free protection for your applications and to get access to all the features.
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: []