wrest 3.0.0 → 4.0.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (76) hide show
  1. checksums.yaml +5 -5
  2. data/CHANGELOG +3 -0
  3. data/LICENCE +1 -1
  4. data/README.md +29 -28
  5. data/bin/wrest +2 -1
  6. data/bin/wrest_shell.rb +10 -8
  7. data/lib/wrest/async_request/event_machine_backend.rb +3 -1
  8. data/lib/wrest/async_request/thread_backend.rb +5 -2
  9. data/lib/wrest/async_request/thread_pool.rb +4 -2
  10. data/lib/wrest/async_request.rb +7 -6
  11. data/lib/wrest/cache_proxy.rb +39 -28
  12. data/lib/wrest/caching/memcached.rb +21 -18
  13. data/lib/wrest/caching/redis.rb +22 -22
  14. data/lib/wrest/caching.rb +16 -14
  15. data/lib/wrest/callback.rb +19 -16
  16. data/lib/wrest/components/container/alias_accessors.rb +51 -47
  17. data/lib/wrest/components/container/typecaster.rb +146 -96
  18. data/lib/wrest/components/container.rb +171 -152
  19. data/lib/wrest/components/mutators/base.rb +43 -34
  20. data/lib/wrest/components/mutators/camel_to_snake_case.rb +7 -3
  21. data/lib/wrest/components/mutators/{xml_mini_type_caster.rb → xml_type_caster.rb} +29 -16
  22. data/lib/wrest/components/mutators.rb +21 -19
  23. data/lib/wrest/components/translators/content_types.rb +20 -16
  24. data/lib/wrest/components/translators/json.rb +19 -16
  25. data/lib/wrest/components/translators/txt.rb +19 -15
  26. data/lib/wrest/components/translators/xml/conversions.rb +56 -0
  27. data/lib/wrest/components/translators/xml.rb +60 -18
  28. data/lib/wrest/components/translators.rb +7 -6
  29. data/lib/wrest/components.rb +11 -8
  30. data/lib/wrest/core_ext/hash/conversions.rb +10 -10
  31. data/lib/wrest/core_ext/hash.rb +4 -2
  32. data/lib/wrest/core_ext/string/conversions.rb +14 -13
  33. data/lib/wrest/core_ext/string.rb +5 -3
  34. data/lib/wrest/exceptions.rb +4 -2
  35. data/lib/wrest/hash_with_case_insensitive_access.rb +8 -8
  36. data/lib/wrest/hash_with_indifferent_access.rb +442 -0
  37. data/lib/wrest/http_codes.rb +20 -19
  38. data/lib/wrest/http_shared/headers.rb +2 -0
  39. data/lib/wrest/http_shared/standard_headers.rb +2 -2
  40. data/lib/wrest/http_shared/standard_tokens.rb +8 -6
  41. data/lib/wrest/http_shared.rb +5 -3
  42. data/lib/wrest/multipart.rb +20 -11
  43. data/lib/wrest/native/connection_factory.rb +15 -11
  44. data/lib/wrest/native/delete.rb +15 -11
  45. data/lib/wrest/native/get.rb +60 -56
  46. data/lib/wrest/native/options.rb +15 -11
  47. data/lib/wrest/native/patch.rb +16 -12
  48. data/lib/wrest/native/post.rb +15 -11
  49. data/lib/wrest/native/post_multipart.rb +22 -18
  50. data/lib/wrest/native/put.rb +16 -12
  51. data/lib/wrest/native/put_multipart.rb +22 -18
  52. data/lib/wrest/native/redirection.rb +13 -12
  53. data/lib/wrest/native/request.rb +144 -108
  54. data/lib/wrest/native/response.rb +87 -78
  55. data/lib/wrest/native/session.rb +49 -40
  56. data/lib/wrest/native.rb +14 -12
  57. data/lib/wrest/test/request_patches.rb +10 -3
  58. data/lib/wrest/test.rb +3 -1
  59. data/lib/wrest/uri/builders.rb +14 -12
  60. data/lib/wrest/uri.rb +70 -52
  61. data/lib/wrest/uri_template.rb +11 -7
  62. data/lib/wrest/utils.rb +129 -0
  63. data/lib/wrest/version.rb +3 -1
  64. data/lib/wrest.rb +31 -33
  65. data/lib/wrest_no_ext.rb +2 -0
  66. metadata +98 -48
  67. data/lib/wrest/components/mutators/xml_simple_type_caster.rb +0 -37
  68. data/lib/wrest/xml_mini/jdom/xpath_filter.rb +0 -17
  69. data/lib/wrest/xml_mini/jdom.rb +0 -6
  70. data/lib/wrest/xml_mini/libxml/xpath_filter.rb +0 -12
  71. data/lib/wrest/xml_mini/libxml.rb +0 -8
  72. data/lib/wrest/xml_mini/nokogiri/xpath_filter.rb +0 -15
  73. data/lib/wrest/xml_mini/nokogiri.rb +0 -7
  74. data/lib/wrest/xml_mini/rexml/xpath_filter.rb +0 -15
  75. data/lib/wrest/xml_mini/rexml.rb +0 -8
  76. data/lib/wrest/xml_mini.rb +0 -8
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2009 Sidu Ponnappa
2
4
 
3
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -8,56 +10,58 @@
8
10
  # See the License for the specific language governing permissions and limitations under the License.
9
11
 
10
12
  module Wrest
11
- module Components::Container
12
- module AliasAccessors
13
- def self.included(klass) #:nodoc:
14
- klass.extend AliasAccessors::ClassMethods
15
- end
13
+ module Components
14
+ module Container
15
+ module AliasAccessors
16
+ def self.included(klass) # :nodoc:
17
+ klass.extend AliasAccessors::ClassMethods
18
+ end
16
19
 
17
- def self.build_aliased_attribute_getter(attribute_name, alias_name) #:nodoc:
18
- "def #{alias_name};#{attribute_name};end;"
19
- end
20
+ def self.build_aliased_attribute_getter(attribute_name, alias_name) # :nodoc:
21
+ "def #{alias_name};#{attribute_name};end;"
22
+ end
20
23
 
21
- def self.build_aliased_attribute_setter(attribute_name, alias_name) #:nodoc:
22
- "def #{alias_name}=(value);self.#{attribute_name}=value;end;"
23
- end
24
+ def self.build_aliased_attribute_setter(attribute_name, alias_name) # :nodoc:
25
+ "def #{alias_name}=(value);self.#{attribute_name}=value;end;"
26
+ end
24
27
 
25
- def self.build_aliased_attribute_queryer(attribute_name, alias_name) #:nodoc:
26
- "def #{alias_name}?;self.#{attribute_name}?;end;"
27
- end
28
-
29
- module ClassMethods
30
- # Creates an alias set of getter, setter and query methods for
31
- # attributes that aren't quite the way you'd like them to be; this
32
- # is especially useful when you have no control over the source web
33
- # sevice/resource.
34
- #
35
- # For example, lets say that a particular resource exposes a
36
- # User's age as 'a' and sex as 's'. Typically, you'd have to access it as
37
- # user.a and user.s whereas you's like to access it as user.age and user.sex.
38
- # This is where alias_accessors comes into the picture. Your User class would
39
- # look somethig like this:
40
- #
41
- # class User
42
- # include Wrest::Components::Container
43
- #
44
- # alias_accessors :a => :age,
45
- # :s => :sex
46
- # end
47
- # This would create the methods user.age, user.age= and user.age? which delegates
48
- # to user.a, user.a= and user.a? respectively.
49
- #
50
- # See examples/wow_realm_status.rb for a working example.
51
- #
52
- # WARNING: If you try to create an alias with the same name as the attribute,
53
- # and then use it, you _will_ cause an infinite loop.
54
- def alias_accessors(alias_map)
55
- alias_map.each do |attribute_name, alias_name|
56
- self.class_eval(
57
- AliasAccessors.build_aliased_attribute_getter(attribute_name, alias_name) +
58
- AliasAccessors.build_aliased_attribute_setter(attribute_name, alias_name) +
59
- AliasAccessors.build_aliased_attribute_queryer(attribute_name, alias_name)
60
- )
28
+ def self.build_aliased_attribute_queryer(attribute_name, alias_name) # :nodoc:
29
+ "def #{alias_name}?;self.#{attribute_name}?;end;"
30
+ end
31
+
32
+ module ClassMethods
33
+ # Creates an alias set of getter, setter and query methods for
34
+ # attributes that aren't quite the way you'd like them to be; this
35
+ # is especially useful when you have no control over the source web
36
+ # sevice/resource.
37
+ #
38
+ # For example, lets say that a particular resource exposes a
39
+ # User's age as 'a' and sex as 's'. Typically, you'd have to access it as
40
+ # user.a and user.s whereas you's like to access it as user.age and user.sex.
41
+ # This is where alias_accessors comes into the picture. Your User class would
42
+ # look somethig like this:
43
+ #
44
+ # class User
45
+ # include Wrest::Components::Container
46
+ #
47
+ # alias_accessors :a => :age,
48
+ # :s => :sex
49
+ # end
50
+ # This would create the methods user.age, user.age= and user.age? which delegates
51
+ # to user.a, user.a= and user.a? respectively.
52
+ #
53
+ # See examples/wow_realm_status.rb for a working example.
54
+ #
55
+ # WARNING: If you try to create an alias with the same name as the attribute,
56
+ # and then use it, you _will_ cause an infinite loop.
57
+ def alias_accessors(alias_map)
58
+ alias_map.each do |attribute_name, alias_name|
59
+ class_eval(
60
+ AliasAccessors.build_aliased_attribute_getter(attribute_name, alias_name) +
61
+ AliasAccessors.build_aliased_attribute_setter(attribute_name, alias_name) +
62
+ AliasAccessors.build_aliased_attribute_queryer(attribute_name, alias_name)
63
+ )
64
+ end
61
65
  end
62
66
  end
63
67
  end
@@ -1,3 +1,5 @@
1
+ # frozen_string_literal: true
2
+
1
3
  # Copyright 2009 Sidu Ponnappa
2
4
 
3
5
  # Licensed under the Apache License, Version 2.0 (the "License");
@@ -8,118 +10,166 @@
8
10
  # See the License for the specific language governing permissions and limitations under the License.
9
11
 
10
12
  module Wrest
11
- module Components::Container
12
- # An extension to Container that adds support for specifying
13
- # how the values associated with certain attribute keys
14
- # should be typecast.
15
- #
16
- # This extension can be used in situations where the attributes
17
- # hash consists of just strings with no associated tup information.
18
- # For example, params recieved from a web browser may contain
19
- # attributes like
20
- # 'id' => '4', 'dateofbirth' => '1984-04-05'
21
- # and we'd like to have these cast to an integer and a date
22
- # respectively, rather than have to deal with them as strings.
23
- module Typecaster
24
- def self.included(klass) #:nodoc:
25
- klass.extend Typecaster::ClassMethods
26
- klass.class_eval{ include Typecaster::InstanceMethods }
27
- klass.send(:alias_method, :initialize_without_typecasting, :initialize)
28
- klass.send(:alias_method, :initialize, :initialize_with_typecasting)
29
- end
13
+ module Components
14
+ module Container
15
+ # An extension to Container that adds support for specifying
16
+ # how the values associated with certain attribute keys
17
+ # should be typecast.
18
+ #
19
+ # This extension can be used in situations where the attributes
20
+ # hash consists of just strings with no associated tup information.
21
+ # For example, params recieved from a web browser may contain
22
+ # attributes like
23
+ # 'id' => '4', 'dateofbirth' => '1984-04-05'
24
+ # and we'd like to have these cast to an integer and a date
25
+ # respectively, rather than have to deal with them as strings.
26
+ module Typecaster
27
+ PARSING = {
28
+ 'symbol' => proc { |symbol| symbol.to_s.to_sym },
29
+ 'date' => proc { |date| ::Date.parse(date) },
30
+ 'datetime' => proc { |time|
31
+ begin
32
+ Time.xmlschema(time).utc
33
+ rescue StandardError
34
+ ::DateTime.parse(time).utc
35
+ end
36
+ },
37
+ 'integer' => proc { |integer| integer.to_i },
38
+ 'float' => proc { |float| float.to_f },
39
+ 'decimal' => proc do |number|
40
+ if number.is_a?(String)
41
+ number.to_d
42
+ else
43
+ BigDecimal(number)
44
+ end
45
+ end,
46
+ 'boolean' => proc { |boolean| %w[1 true].include?(boolean.to_s.strip) },
47
+ 'string' => proc { |string| string.to_s },
48
+ 'yaml' => proc { |yaml|
49
+ begin
50
+ YAML.safe_load(yaml)
51
+ rescue StandardError
52
+ yaml
53
+ end
54
+ },
55
+ 'base64Binary' => proc { |bin| ::Base64.decode64(bin) },
56
+ 'binary' => proc { |bin, entity| _parse_binary(bin, entity) },
57
+ 'file' => proc { |file, entity| _parse_file(file, entity) },
58
+ 'double' => proc { |float| float.to_f },
59
+ 'dateTime' => proc { |time|
60
+ begin
61
+ Time.xmlschema(time).utc
62
+ rescue StandardError
63
+ ::DateTime.parse(time).utc
64
+ end
65
+ }
66
+ }.freeze
30
67
 
31
- module Helpers
32
- def as_base64Binary
33
- ActiveSupport::XmlMini::PARSING['base64Binary']
68
+ def self.included(klass)
69
+ # :nodoc:
70
+ klass.extend Typecaster::ClassMethods
71
+ klass.class_eval { include Typecaster::InstanceMethods }
72
+ klass.send(:alias_method, :initialize_without_typecasting, :initialize)
73
+ klass.send(:alias_method, :initialize, :initialize_with_typecasting)
34
74
  end
35
75
 
36
- def as_boolean
37
- ActiveSupport::XmlMini::PARSING['boolean']
38
- end
76
+ module Helpers
77
+ def as_base64_binary
78
+ PARSING['base64Binary']
79
+ end
39
80
 
40
- def as_decimal
41
- ActiveSupport::XmlMini::PARSING['decimal']
42
- end
81
+ def as_boolean
82
+ PARSING['boolean']
83
+ end
43
84
 
44
- def as_date
45
- ActiveSupport::XmlMini::PARSING['date']
46
- end
85
+ def as_decimal
86
+ PARSING['decimal']
87
+ end
47
88
 
48
- def as_datetime
49
- ActiveSupport::XmlMini::PARSING['datetime']
50
- end
89
+ def as_date
90
+ PARSING['date']
91
+ end
51
92
 
52
- def as_float
53
- ActiveSupport::XmlMini::PARSING['float']
54
- end
93
+ def as_datetime
94
+ PARSING['datetime']
95
+ end
55
96
 
56
- def as_integer
57
- ActiveSupport::XmlMini::PARSING['integer']
58
- end
97
+ def as_float
98
+ PARSING['float']
99
+ end
59
100
 
60
- def as_symbol
61
- ActiveSupport::XmlMini::PARSING['symbol']
62
- end
101
+ def as_integer
102
+ PARSING['integer']
103
+ end
63
104
 
64
- def as_yaml
65
- ActiveSupport::XmlMini::PARSING['yaml']
66
- end
67
- end
105
+ def as_symbol
106
+ PARSING['symbol']
107
+ end
68
108
 
69
- module ClassMethods
70
- # Accepts a set of attribute-name/lambda pairs which are used
71
- # to typecast string values injected through the constructor.
72
- # Typically needed when populating an +Container+
73
- # directly from request params. Typecasting kicks in for
74
- # a given value _only_ if it is a String, Hash or Array, the
75
- # three classes that deserilisation can produce.
76
- #
77
- # Typecast information is inherited by subclasses; however be
78
- # aware that explicitly invoking +typecast+ in a subclass will
79
- # discard inherited typecast information leaving only the casts
80
- # defined in the subclass.
81
- #
82
- # Note that this _will_ increase the time needed to initialize
83
- # instances.
84
- #
85
- # Common typecasts such as integer, float, datetime etc. are
86
- # available through predefined helpers. See TypecastHelpers
87
- # for a full list.
88
- #
89
- # Example:
90
- #
91
- # class Demon
92
- # include Wrest::Components::Container
93
- # include Wrest::Components::Container::Typecaster
94
- #
95
- # typecast :age => as_integer,
96
- # :chi => lambda{|chi| Chi.new(chi)}
97
- # end
98
- #
99
- # kai_wren = Demon.new('age' => '1500', 'chi' => '1024')
100
- # kai_wren.age # => 1500
101
- # kai_wren.chi # => #<Chi:0x113af8c @count="1024">
102
- def typecast(cast_map)
103
- @typecast_map = @typecast_map ? @typecast_map.merge(cast_map.symbolize_keys) : cast_map.symbolize_keys
109
+ def as_yaml
110
+ PARSING['yaml']
111
+ end
104
112
  end
105
113
 
106
- def typecast_map #:nodoc:
107
- if defined?(@typecast_map)
108
- @typecast_map
109
- elsif superclass != Object && superclass.respond_to?(:typecast_map)
110
- superclass.typecast_map
111
- else
112
- {}
114
+ module ClassMethods
115
+ # Accepts a set of attribute-name/lambda pairs which are used
116
+ # to typecast string values injected through the constructor.
117
+ # Typically needed when populating an +Container+
118
+ # directly from request params. Typecasting kicks in for
119
+ # a given value _only_ if it is a String, Hash or Array, the
120
+ # three classes that deserilisation can produce.
121
+ #
122
+ # Typecast information is inherited by subclasses; however be
123
+ # aware that explicitly invoking +typecast+ in a subclass will
124
+ # discard inherited typecast information leaving only the casts
125
+ # defined in the subclass.
126
+ #
127
+ # Note that this _will_ increase the time needed to initialize
128
+ # instances.
129
+ #
130
+ # Common typecasts such as integer, float, datetime etc. are
131
+ # available through predefined helpers. See TypecastHelpers
132
+ # for a full list.
133
+ #
134
+ # Example:
135
+ #
136
+ # class Demon
137
+ # include Wrest::Components::Container
138
+ # include Wrest::Components::Container::Typecaster
139
+ #
140
+ # typecast :age => as_integer,
141
+ # :chi => lambda{|chi| Chi.new(chi)}
142
+ # end
143
+ #
144
+ # kai_wren = Demon.new('age' => '1500', 'chi' => '1024')
145
+ # kai_wren.age # => 1500
146
+ # kai_wren.chi # => #<Chi:0x113af8c @count="1024">
147
+ def typecast(cast_map)
148
+ @typecast_map = @typecast_map ? @typecast_map.merge(cast_map.transform_keys(&:to_sym)) : cast_map.transform_keys(&:to_sym)
149
+ end
150
+
151
+ def typecast_map # :nodoc:
152
+ if defined?(@typecast_map)
153
+ @typecast_map
154
+ elsif superclass != Object && superclass.respond_to?(:typecast_map)
155
+ superclass.typecast_map
156
+ else
157
+ {}
158
+ end
113
159
  end
114
160
  end
115
- end
116
161
 
117
- module InstanceMethods # :nodoc:
118
- def initialize_with_typecasting(attributes = {}) # :nodoc:
119
- initialize_without_typecasting(attributes)
120
- self.class.typecast_map.each do |key, typecaster|
121
- value = @attributes[key]
122
- @attributes[key] = typecaster.call(value) if (value.is_a?(String) || value.is_a?(Hash) || value.is_a?(Array))
162
+ module InstanceMethods # :nodoc:
163
+ def initialize_with_typecasting(attributes = {})
164
+ # :nodoc:
165
+ initialize_without_typecasting(attributes)
166
+ self.class.typecast_map.each do |key, typecaster|
167
+ value = @attributes[key]
168
+ if value.is_a?(String) || value.is_a?(Hash) || value.is_a?(Array)
169
+ @attributes[key] =
170
+ typecaster.call(value)
171
+ end
172
+ end
123
173
  end
124
174
  end
125
175
  end