glue 0.19.0 → 0.20.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/CHANGELOG CHANGED
@@ -1,3 +1,44 @@
1
+ 12-07-2005 George Moschovitis <gm@navel.gr>
2
+
3
+ * lib/glue/helper.rb: moved here from nitro.
4
+
5
+ 11-07-2005 George Moschovitis <gm@navel.gr>
6
+
7
+ * doc/RELEASES: updated.
8
+
9
+ 04-07-2005 George Moschovitis <gm@navel.gr>
10
+
11
+ * test/glue/tc_configuration.rb: changes to work under rake.
12
+
13
+ 25-06-2005 George Moschovitis <gm@navel.gr>
14
+
15
+ * lib/glue/object.rb (#subclasses_of): small update in the
16
+ code.
17
+
18
+ 24-06-2005 George Moschovitis <gm@navel.gr>
19
+
20
+ * lib/glue/configuration.rb (#parse): handle namespaces,
21
+ fixed check for default param.
22
+
23
+ 23-06-2005 George Moschovitis <gm@navel.gr>
24
+
25
+ * test/glue/tc_configuration.rb: introduced.
26
+
27
+ * lib/glue/configuration.rb: introduced,
28
+ kinda works :),
29
+ (Configuration#settings): per owner filter,
30
+ use a hash to store settings.
31
+ setting the owner updates the configuration metadata,
32
+ reverse setting works too :-)
33
+ (#parse, #load, #setup): implemented.
34
+ the parsing support just ROCKS!
35
+ (Settings): alias for configuration.
36
+
37
+ * README: updated.
38
+
39
+ * lib/glue/annotation.rb: introduced and adapted [ahellesoy],
40
+ override Module.
41
+
1
42
  17-06-2005 George Moschovitis <gm@navel.gr>
2
43
 
3
44
  * lib/glue/autoreload.rb: added.
data/README CHANGED
@@ -1,10 +1,18 @@
1
- = Glue 0.17.0 README
1
+ = Glue 0.19.0 README
2
2
 
3
3
  Useful utilites and methods.
4
4
 
5
+
6
+ == Purpose
7
+
8
+ Useful libraries are stored here. An attempt is made to
9
+ graduate mature libraries to the more general Facets
10
+ ruby project.
11
+
12
+
5
13
  == Licence
6
14
 
7
- Copyright (c) 2004-2005, George 'tml' Moschovitis.
15
+ Copyright (c) 2004-2005, George 'gmosx' Moschovitis.
8
16
  Copyright (c) 2004-2005, Navel Ltd (http://www.navel.gr)
9
17
 
10
18
  Glue (http://www.rubyforge.org/projects/nitro) is copyrighted free
@@ -1,4 +1,45 @@
1
- == Version 0.19.0
1
+ == Version 0.20.0
2
+
3
+ * Brand new, self-documenting configuration system. There is a new
4
+ keyword for defining configuration settings:
5
+
6
+ Here is an example:
7
+
8
+ class Render
9
+ setting :template_extension, :default => 'xhtml', :doc => 'The default template extension'
10
+ end
11
+
12
+ class Session
13
+ setting :store, :default => 'memory', :doc => 'The session store'
14
+ end
15
+
16
+ You can configure the Application using ruby code or yaml files:
17
+
18
+ Render.template_extension = 'xhtml'
19
+ Session.store = 'drb'
20
+
21
+ or
22
+
23
+ Render:
24
+ template_extension: xhtml
25
+ Session:
26
+ store: drb
27
+
28
+ You can access all defined settings:
29
+
30
+ Configuration.settings.each { |s| ... }
31
+
32
+ You can view the settings of the application along with documentation
33
+ on the following url:
34
+
35
+ www.myapp.com/settings
36
+
37
+ * Flexob, many improvements.
38
+
39
+ * Many bug fixes.
40
+
41
+
42
+ == Version 0.19.0 was released on 31/05/2005.
2
43
 
3
44
  * Improved Logger.
4
45
 
@@ -61,7 +61,7 @@ module Glue
61
61
 
62
62
  # The version.
63
63
 
64
- Version = '0.19.0'
64
+ Version = '0.20.0'
65
65
 
66
66
  # Library path.
67
67
 
@@ -0,0 +1,33 @@
1
+ # Based on an original idea by Aslak Hellesoy.
2
+
3
+ require 'glue/hash'
4
+
5
+ class Module
6
+ def ann(anns)
7
+ @@anns ||= SafeHash.new
8
+ def self.method_missing(sym, *args) #:nodoc:
9
+ @@anns[sym]
10
+ end
11
+ t = Thread.current
12
+ t[:attr_anns] ||= {}
13
+ t[:attr_anns].merge!(anns)
14
+ end
15
+
16
+ alias old_attr_reader attr_reader #:nodoc:
17
+ def attr_reader(*syms) #:nodoc:
18
+ t = Thread.current
19
+ syms.each do |sym|
20
+ @@anns[sym] = t[:attr_anns]
21
+ end
22
+
23
+ t[:attr_anns] = nil
24
+ old_attr_reader(*syms)
25
+ end
26
+
27
+ def attr_accessor(*syms) #:nodoc:
28
+ attr_reader(*syms)
29
+ attr_writer(*syms)
30
+ end
31
+ end
32
+
33
+ # * George Moschovitis <gm@navel.gr>
@@ -33,13 +33,7 @@ class Module # :nodoc:
33
33
  def self.#{sym.id2name}
34
34
  @@#{sym}
35
35
  end
36
- =begin
37
- # gmosx: NOT NEEDED!
38
-
39
- def #{sym.id2name}
40
- @@#{sym}
41
- end
42
- =end
36
+
43
37
  end_eval
44
38
  end
45
39
  end
@@ -65,13 +59,7 @@ class Module # :nodoc:
65
59
  def self.set_#{sym.id2name}(obj)
66
60
  @@#{sym.id2name} = obj
67
61
  end
68
- =begin
69
- # gmosx: NOT NEEDED!
70
-
71
- def #{sym.id2name}=(obj)
72
- @@#{sym} = obj
73
- end
74
- =end
62
+
75
63
  end_eval
76
64
  end
77
65
  end
@@ -0,0 +1,126 @@
1
+ require 'yaml'
2
+
3
+ require 'facet/object/constant'
4
+
5
+ require 'glue/attribute'
6
+ require 'glue/hash'
7
+ require 'glue/flexob'
8
+
9
+ # A Configuration holds a group of Settings organized by
10
+ # Owners.
11
+ #--
12
+ # TODO: implement with annotations.
13
+ #++
14
+
15
+ class Configuration
16
+
17
+ # A hash of setting owners. Use double @'s to allow for
18
+ # the Settings alias.
19
+ #--
20
+ # TODO: find a better name.
21
+ #++
22
+
23
+ @@owners = Glue::SafeHash.new
24
+
25
+ # A datastructure to store Settings metadata.
26
+
27
+ class Setting
28
+ attr_accessor :owner, :name, :type, :value, :options
29
+
30
+ def initialize(owner, name, options)
31
+ raise ArgumentError.new('A default value is required') unless options.key?(:default)
32
+ @owner, @name = owner, name
33
+ @options = options
34
+ @value = options[:default]
35
+ @type = options[:type] = options[:type] || @value.class
36
+ end
37
+
38
+ def value=(value)
39
+ @value = value
40
+ constant(@owner).module_eval %{
41
+ @@#{@name} = #{value.inspect}
42
+ }
43
+ end
44
+
45
+ def to_s
46
+ @value.to_s
47
+ end
48
+ end
49
+
50
+ class << self
51
+
52
+ def setup(options)
53
+ options.each do |owner, ss|
54
+ owner = constant(owner)
55
+ ss.each do |name, s|
56
+ @@owners[owner][name.to_sym].value = s
57
+ owner.module_eval %{
58
+ @@#{name} = #{s.inspect}
59
+ }
60
+ end
61
+ end
62
+ end
63
+
64
+ def parse(options)
65
+ temp = YAML::load(options)
66
+ options = {}
67
+ temp.each { |k, v| options[constant(k.gsub(/\./, '::').to_sym)] = v }
68
+ setup(options)
69
+ end
70
+
71
+ def load(filename)
72
+ parse(File.read(filename))
73
+ end
74
+
75
+ def add_setting(owner, name, options)
76
+ s = @@owners[owner] || {}
77
+ s[name] = Setting.new(owner, name, options)
78
+ @@owners[owner] = s
79
+ end
80
+
81
+ def settings(owner = nil)
82
+ if owner
83
+ @@owners[owner]
84
+ else
85
+ @@owners.values.inject([]) { |memo, obj| memo.concat(obj.values) }
86
+ end
87
+ end
88
+ alias_method :all, :settings
89
+ alias_method :[], :settings
90
+
91
+ def method_missing(sym)
92
+ if sym.to_s =~ /[A-Z]/ # facet's capitalized? is buggy at the moment.
93
+ Flexob.new(self[constant(sym)])
94
+ end
95
+ end
96
+ end
97
+
98
+ end
99
+
100
+ # Alias for the Configuration class (shorter).
101
+
102
+ class Settings < Configuration
103
+ end
104
+
105
+ class Module
106
+
107
+ # Defines a configuration setting.
108
+ #--
109
+ # TODO: implement with annotations.
110
+ #++
111
+
112
+ def setting(sym, options = {})
113
+ Configuration.add_setting(self, sym, options)
114
+ module_eval %{
115
+ mattr_accessor sym, options[:default]
116
+
117
+ def self.#{sym.id2name}=(obj)
118
+ @@#{sym.id2name} = obj
119
+ Configuration[#{self}][:#{sym}].value = obj
120
+ end
121
+ }
122
+ end
123
+
124
+ end
125
+
126
+ # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,31 @@
1
+ require 'facet/module/by_name'
2
+
3
+ require 'glue/object'
4
+ require 'glue/attribute'
5
+
6
+ module Glue
7
+
8
+ # Helpers are standard Ruby modules that contain utility
9
+ # methods. By using the special 'helper'
10
+ # macro provided by HelperSupport, the utility methods are
11
+ # included as private methods.
12
+
13
+ module Helpers
14
+
15
+ def self.append_features(base)
16
+ base.module_eval do
17
+ def self.helper(*modules)
18
+ for mod in modules
19
+ symbols = mod.instance_methods.collect { |m| m.to_sym }
20
+ self.send(:include, mod)
21
+ self.send(:private, *symbols)
22
+ end
23
+ end
24
+ end
25
+ end
26
+
27
+ end
28
+
29
+ end
30
+
31
+ # * George Moschovitis <gm@navel.gr>
@@ -1,26 +1,26 @@
1
- # * George Moschovitis <gm@navel.gr>
2
- # (c) 2004-2005 Navel, all rights reserved.
3
- # $Id: object.rb 1 2005-04-11 11:04:30Z gmosx $
4
-
5
- # Code from RubyOnRails (http://www.rubyonrails.com)
1
+ # Original code from RubyOnRails (http://www.rubyonrails.com)
2
+ #--
3
+ # TODO: suggest inclusion in Facets.
4
+ #++
6
5
 
7
6
  class Object #:nodoc:
8
7
  def remove_subclasses_of(superclass)
9
- subclasses_of(superclass).each { |subclass| Object.send(:remove_const, subclass) rescue nil }
8
+ subclasses_of(superclass).each do |subclass|
9
+ Object.send(:remove_const, subclass) rescue nil
10
+ end
10
11
  end
11
12
 
12
13
  def subclasses_of(superclass)
13
14
  subclasses = []
14
- ObjectSpace.each_object(Class) do |k|
15
- next if !k.ancestors.include?(superclass) || superclass == k || k.to_s.include?("::") || subclasses.include?(k.to_s)
16
- subclasses << k.to_s
15
+ ObjectSpace.each_object(Class) do |c|
16
+ if c.ancestors.include?(superclass) and superclass != c
17
+ subclasses << c
18
+ end
17
19
  end
18
- subclasses
20
+ return subclasses
19
21
  end
20
22
  end
21
23
 
22
- # Code from RubyOnRails (http://www.rubyonrails.com)
23
-
24
24
  class Class #:nodoc:
25
25
  def remove_subclasses
26
26
  Object.remove_subclasses_of(self)
@@ -29,4 +29,7 @@ class Class #:nodoc:
29
29
  def subclasses
30
30
  Object.subclasses_of(self)
31
31
  end
32
+ alias_method :descendants, :subclasses
32
33
  end
34
+
35
+ # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,5 @@
1
+ # Just an alias for glue/configuration.
2
+
3
+ require 'glue/configuration'
4
+
5
+ # * George Moschovitis <gm@navel.gr>
@@ -0,0 +1,192 @@
1
+ require 'uri'
2
+ require 'cgi'
3
+
4
+ require 'glue/string'
5
+
6
+ module Glue
7
+
8
+ # URI utilities collection.
9
+ #
10
+ # === Design
11
+ #
12
+ # Implement as a module to avoid class polution. You can still
13
+ # use Ruby's advanced features to include the module in your
14
+ # class. Passing the object to act upon allows to check for nil,
15
+ # which isn't possible if you use self.
16
+ #
17
+ # The uris passed as parameters are typically strings.
18
+ #--
19
+ # gmosx, TODO: deprecate this.
20
+ #++
21
+
22
+ module UriUtils
23
+
24
+ # Decode the uri components.
25
+
26
+ def self.decode(uri)
27
+ # gmosx: hmm is this needed?
28
+ # guard against invalid filenames for example pictures with
29
+ # spaces uploaded by users
30
+ escaped_uri = uri.gsub(/ /, "+")
31
+
32
+ if md = URI::REGEXP::REL_URI.match(escaped_uri)
33
+
34
+ path = "#{md[5]}#{md[6]}"
35
+ type = File.extname(path)
36
+ query_string = md[7]
37
+
38
+ # real_path = "#{$root_dir}/#{path}"
39
+
40
+ parameters = UriUtils.query_string_to_hash(query_string)
41
+ path.gsub!(/\+/, " ")
42
+
43
+ return [path, type, parameters, query_string]
44
+
45
+ end # match
46
+
47
+ # this is usefull for uncovering bugs!
48
+ raise ArgumentError.new("the parameter '#{uri}' is not a valid uri")
49
+ end
50
+
51
+ # Extend the basic query string parser provided by the cgi module.
52
+ # converts single valued params (the most common case) to
53
+ # objects instead of arrays
54
+ #
55
+ # Input:
56
+ # the query string
57
+ #
58
+ # Output:
59
+ # hash of parameters, contains arrays for multivalued parameters
60
+ # (multiselect, checkboxes , etc)
61
+ # If no query string is provided (nil or "") returns an empty hash.
62
+
63
+ def self.query_string_to_hash(query_string)
64
+ return {} unless query_string
65
+
66
+ query_parameters = CGI::parse(query_string)
67
+
68
+ query_parameters.each { |key, val|
69
+ # replace the array with an object
70
+ query_parameters[key] = val[0] if 1 == val.length
71
+ }
72
+
73
+ # set default value to nil! cgi sets this to []
74
+ query_parameters.default = nil
75
+
76
+ return query_parameters
77
+ end
78
+
79
+ # Given a hash with parameter/value pairs construct a
80
+ # standard query string. This method only encodes simple
81
+ # types (Numeric, String) to avoid query string polution
82
+ # with marshal, etc.
83
+ #
84
+ # gmosx, FIXME: only numeric and strings are passed to
85
+ # the latest code, so update old code and optimize this!
86
+ #
87
+ # Input:
88
+ # the parameter hash
89
+ #
90
+ # Output:
91
+ # the query string
92
+
93
+ def self.hash_to_query_string(parameters)
94
+ return nil unless parameters
95
+ pairs = []
96
+ parameters.each { |param, value|
97
+ # only encode simple classes !
98
+
99
+ if value.is_a?(Numeric) or value.is_a?(String)
100
+ pairs << "#{param}=#{value}"
101
+ end
102
+ }
103
+ return pairs.join(";")
104
+ end
105
+
106
+ # This method returns the query string of a uri
107
+ #
108
+ # Input:
109
+ # the uri
110
+ #
111
+ # Output:
112
+ # the query string.
113
+ # returns nil if no query string
114
+
115
+ def self.get_query_string(uri)
116
+ return nil unless uri
117
+ # gmosx: INVESTIGATE ruby's URI seems to differently handle
118
+ # abs and rel uris.
119
+ if md = URI::REGEXP::ABS_URI.match(uri)
120
+ return md[8]
121
+ elsif md = URI::REGEXP::REL_URI.match(uri)
122
+ return md[7]
123
+ end
124
+ return nil
125
+ end
126
+
127
+ # Removes the query string from a uri
128
+ #
129
+ # Input:
130
+ # the uri
131
+ #
132
+ # Output:
133
+ # the chomped uri.
134
+
135
+ def self.chomp_query_string(uri)
136
+ return nil unless uri
137
+ query_string = self.get_query_string(uri)
138
+ return uri.dup.chomp("?#{query_string}")
139
+ end
140
+
141
+ # Get a uri and a hash of parameters. Inject the hash values
142
+ # as parameters in the query sting path. Returns the full
143
+ # uri.
144
+ #
145
+ # Input:
146
+ # the uri to filter (String)
147
+ # hash of parameters to update
148
+ #
149
+ # Output:
150
+ # the full updated query string
151
+ #
152
+ # === TODO:
153
+ # optimize this a litle bit.
154
+
155
+ def self.update_query_string(uri, parameters)
156
+ query_string = self.get_query_string(uri)
157
+ rest = uri.dup.gsub(/\?#{query_string}/, "")
158
+
159
+ hash = self.query_string_to_hash(query_string)
160
+ hash.update(parameters)
161
+ query_string = self.hash_to_query_string(hash)
162
+
163
+ if Glue::StringUtils.valid?(query_string)
164
+ return "#{rest}?#{query_string}"
165
+ else
166
+ return rest
167
+ end
168
+ end
169
+
170
+ # TODO: find a better name.
171
+ # Gets the request uri, injects extra parameters in the query string
172
+ # and returns a new uri. The request object is not modified.
173
+ # There is always a qs string so an extra test is skipped.
174
+
175
+ def self.update_request_uri(request, parameters)
176
+ hash = request.parameters.dup()
177
+ hash.update(parameters)
178
+
179
+ # use this in hash_to_querystring.
180
+ query_string = hash.collect { |k, v|
181
+ "#{k}=#{v}"
182
+ }.join(";")
183
+
184
+ return "#{request.translated_uri}?#{query_string}"
185
+ end
186
+
187
+ end
188
+
189
+ end
190
+
191
+ # * George Moschovitis <gm@navel.gr>
192
+
@@ -0,0 +1,125 @@
1
+ $:.unshift File.join(File.dirname(__FILE__), '..', '..', 'lib')
2
+
3
+ require 'test/unit'
4
+ require 'glue/configuration'
5
+
6
+ # Hack: To make compatible with rake test.
7
+
8
+ class Dummy
9
+ setting :root_dir, :default => '/home/gmosx', :doc => 'The root directory for the app'
10
+ setting :conn_count, :default => 5, :type => Fixnum
11
+ end
12
+
13
+ class Another
14
+ setting :max_age, :default => 4, :doc => 'Maximum allowed age'
15
+ end
16
+
17
+ class Configuration
18
+ def self.clear_all_settings
19
+ @@owners = Hash.new
20
+ end
21
+ end
22
+
23
+ class TC_Configuration < Test::Unit::TestCase # :nodoc: all
24
+
25
+ class Internal
26
+ setting :radius, :default => 4
27
+ end
28
+
29
+ def setup
30
+ # gmosx: A hack to make compatible with rake. All code in this
31
+ # method is not needed if you only run this test (or in your
32
+ # real aplications of course).
33
+
34
+ Configuration.clear_all_settings
35
+
36
+ Dummy.class_eval do
37
+ setting :root_dir, :default => '/home/gmosx', :doc => 'The root directory for the app'
38
+ setting :conn_count, :default => 5, :type => Fixnum
39
+ end
40
+
41
+ Another.class_eval do
42
+ setting :max_age, :default => 4, :doc => 'Maximum allowed age'
43
+ end
44
+
45
+ Internal.class_eval do
46
+ setting :radius, :default => 4
47
+ end
48
+ end
49
+
50
+ def test_all
51
+ assert_equal 4, Configuration.settings.size
52
+ assert_equal 4, Configuration.all.size
53
+
54
+ assert_equal 2, Configuration.settings(Dummy).size
55
+ assert_equal 1, Configuration.settings(Another).size
56
+
57
+ assert_equal Fixnum, Configuration.settings(Dummy)[:conn_count].type
58
+ assert_equal String, Configuration[Dummy][:root_dir].type
59
+
60
+ assert_equal '/home/gmosx', Dummy.root_dir
61
+ assert_equal 4, Another.max_age
62
+
63
+ Dummy.root_dir = '/changed/dir'
64
+ assert_equal '/changed/dir', Dummy.root_dir
65
+ assert_equal '/changed/dir', Configuration[Dummy][:root_dir].value
66
+
67
+ Another.max_age = 99
68
+ assert_equal 99, Configuration[Another][:max_age].value
69
+
70
+ # test reverse setting.
71
+
72
+ Configuration[Another][:max_age].value = 69
73
+ assert_equal 69, Configuration[Another][:max_age].value
74
+ assert_equal 69, Another.max_age
75
+
76
+ # setup
77
+
78
+ Configuration.setup(
79
+ Dummy => {
80
+ :root_dir => '/gmosx/2',
81
+ :conn_count => 12
82
+ },
83
+ Another => {
84
+ :max_age => 2
85
+ },
86
+ TC_Configuration::Internal => {
87
+ :radius => 99
88
+ }
89
+ )
90
+
91
+ assert_equal '/gmosx/2', Dummy.root_dir
92
+ assert_equal '/gmosx/2', Configuration[Dummy][:root_dir].value
93
+ assert_equal 2, Another.max_age
94
+
95
+ Configuration.parse <<-end_val
96
+ Another:
97
+ max_age: 5
98
+ TC_Configuration.Internal:
99
+ radius: 99
100
+ Dummy:
101
+ root_dir: /gmosx/99
102
+ conn_count: 33
103
+ end_val
104
+
105
+ assert_equal '/gmosx/99', Dummy.root_dir
106
+ assert_equal '/gmosx/99', Configuration[Dummy][:root_dir].value
107
+ assert_equal 5, Another.max_age
108
+
109
+ # cooler ;-)
110
+
111
+ assert_equal String, Configuration.Dummy[:root_dir].type
112
+ assert_equal String, Configuration.Dummy.root_dir.type
113
+
114
+ # alias
115
+
116
+ assert_equal String, Settings.Dummy.root_dir.type
117
+ assert_equal 5, Settings.Another.max_age.value
118
+
119
+ # Handle namespace
120
+
121
+ assert_equal 99, Internal.radius
122
+ assert_equal 99, TC_Configuration::Internal.radius
123
+ end
124
+
125
+ end
@@ -0,0 +1,97 @@
1
+ require 'test/unit'
2
+ require 'glue/uri'
3
+
4
+ class Dummy # :nodoc: all
5
+ attr_accessor :test1, :test2
6
+ end
7
+
8
+ class TC_Uri < Test::Unit::TestCase # :nodoc: all
9
+ include Glue
10
+
11
+ def test_query_string_to_hash
12
+ # bad query string
13
+
14
+ assert_equal(0, UriUtils.query_string_to_hash("").length)
15
+ assert_equal(0, UriUtils.query_string_to_hash(nil).length)
16
+
17
+ # single valued
18
+
19
+ parameters = UriUtils.query_string_to_hash("koko=2&lala=3")
20
+ assert_equal("2", parameters["koko"])
21
+ assert_equal("3", parameters["lala"])
22
+
23
+ parameters = UriUtils.query_string_to_hash("koko=2;lala=3")
24
+ assert_equal("2", parameters["koko"])
25
+ assert_equal("3", parameters["lala"])
26
+
27
+ # multivalued
28
+
29
+ parameters = UriUtils.query_string_to_hash("koko=2;lala=3&koko=5")
30
+ assert_equal(2, parameters["koko"].length)
31
+ assert_equal("2", parameters["koko"][0])
32
+ assert_equal("3", parameters["lala"])
33
+ assert_equal("5", parameters["koko"][1])
34
+
35
+ # non existing value
36
+ assert_equal(nil, parameters["non-existing-value"])
37
+ end
38
+
39
+ def test_hash_to_query_string
40
+ hash = { "koko" => 1, "lala" => 2}
41
+ qs = "koko=1;lala=2"
42
+ assert_equal(qs, UriUtils.hash_to_query_string(hash))
43
+
44
+ assert_equal(nil, UriUtils.hash_to_query_string(nil))
45
+
46
+ # bug: dont encode complex objects
47
+ hash = { "a" => 2, "b" => 3, "c" => Dummy.new }
48
+ qs = "a=2;b=3"
49
+ assert_equal(qs, UriUtils.hash_to_query_string(hash))
50
+ end
51
+
52
+ def test_get_query_string
53
+ uri = "people/gmosx.sx?koko=1;lala=2"
54
+ assert_equal("koko=1;lala=2", UriUtils.get_query_string(uri))
55
+
56
+ uri = "http://www.navel.gr/people/gmosx.sx?koko=1&lala=2"
57
+ assert_equal("koko=1&lala=2", UriUtils.get_query_string(uri))
58
+
59
+ uri = "http://www.navel.gr:8080/people/gmosx.sx?koko=1;lala=2"
60
+ assert_equal("koko=1;lala=2", UriUtils.get_query_string(uri))
61
+ end
62
+
63
+ def test_chomp_query_string
64
+ uri = "people/gmosx.sx"
65
+ assert_equal("people/gmosx.sx", UriUtils.chomp_query_string(uri))
66
+
67
+ uri = "people/gmosx.sx?koko=1;lala=2"
68
+ assert_equal("people/gmosx.sx", UriUtils.chomp_query_string(uri))
69
+
70
+ uri = "http://www.navel.gr/people/gmosx.sx?koko=1&lala=2"
71
+ assert_equal("http://www.navel.gr/people/gmosx.sx", UriUtils.chomp_query_string(uri))
72
+
73
+ uri = "http://www.navel.gr:8080/people/gmosx.sx?koko=1;lala=2"
74
+ assert_equal("http://www.navel.gr:8080/people/gmosx.sx", UriUtils.chomp_query_string(uri))
75
+
76
+ assert_equal(nil, UriUtils.chomp_query_string(nil))
77
+ end
78
+
79
+ def test_update_query_string
80
+ uri = "ko/index.sx?koko=1"
81
+ hash = {"lala" => 2, "kaka" => 3}
82
+ assert_equal("ko/index.sx?koko=1;lala=2;kaka=3", UriUtils.update_query_string(uri, hash))
83
+
84
+ uri = "http://www.navel.gr:8080/ko/index.sx?koko=1"
85
+ hash = {"lala" => 2, "kaka" => 3}
86
+ assert_equal("http://www.navel.gr:8080/ko/index.sx?koko=1;lala=2;kaka=3", UriUtils.update_query_string(uri, hash))
87
+
88
+ uri = "http://www.navel.gr"
89
+ hash = {"lala" => 2, "kaka" => 3}
90
+ assert_equal("http://www.navel.gr?lala=2;kaka=3", UriUtils.update_query_string(uri, hash))
91
+
92
+ # bug: no ? when passed an empty hash
93
+ uri = "http://www.navel.gr"
94
+ assert_equal("http://www.navel.gr", UriUtils.update_query_string(uri, {}))
95
+ end
96
+
97
+ end
metadata CHANGED
@@ -3,8 +3,8 @@ rubygems_version: 0.8.10
3
3
  specification_version: 1
4
4
  name: glue
5
5
  version: !ruby/object:Gem::Version
6
- version: 0.19.0
7
- date: 2005-06-17
6
+ version: 0.20.0
7
+ date: 2005-07-12
8
8
  summary: Glue utilities
9
9
  require_paths:
10
10
  - lib
@@ -27,10 +27,10 @@ platform: ruby
27
27
  authors:
28
28
  - George Moschovitis
29
29
  files:
30
+ - README
30
31
  - CHANGELOG
31
32
  - Rakefile
32
33
  - INSTALL
33
- - README
34
34
  - install.rb
35
35
  - doc/RELEASES
36
36
  - doc/LICENSE
@@ -47,19 +47,25 @@ files:
47
47
  - lib/glue/sanitize.rb
48
48
  - lib/glue/number.rb
49
49
  - lib/glue/autoreload.rb
50
+ - lib/glue/uri.rb
50
51
  - lib/glue/aspects.rb
51
52
  - lib/glue/misc.rb
52
53
  - lib/glue/time.rb
54
+ - lib/glue/annotation.rb
53
55
  - lib/glue/attribute.rb
54
56
  - lib/glue/string.rb
55
57
  - lib/glue/object.rb
56
58
  - lib/glue/mixins.rb
57
59
  - lib/glue/pool.rb
60
+ - lib/glue/configuration.rb
61
+ - lib/glue/helper.rb
62
+ - lib/glue/settings.rb
58
63
  - lib/html/document.rb
59
64
  - lib/html/node.rb
60
65
  - lib/html/version.rb
61
66
  - lib/html/tokenizer.rb
62
67
  - test/glue
68
+ - test/glue/tc_configuration.rb
63
69
  - test/glue/tc_strings.rb
64
70
  - test/glue/tc_validation.rb
65
71
  - test/glue/tc_numbers.rb
@@ -71,6 +77,7 @@ files:
71
77
  - test/glue/tc_hash.rb
72
78
  - test/glue/tc_attribute.rb
73
79
  - test/glue/tc_property.rb
80
+ - test/glue/tc_uri.rb
74
81
  test_files: []
75
82
  rdoc_options:
76
83
  - "--main"
@@ -80,10 +87,10 @@ rdoc_options:
80
87
  - "--all"
81
88
  - "--inline-source"
82
89
  extra_rdoc_files:
90
+ - README
83
91
  - CHANGELOG
84
92
  - Rakefile
85
93
  - INSTALL
86
- - README
87
94
  executables: []
88
95
  extensions: []
89
96
  requirements: []