url 0.1.2 → 0.2.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/README.rdoc CHANGED
@@ -33,7 +33,7 @@ You can quickly and easily make requests from those urls without having to worry
33
33
  A {URL::Response} object is returned from {URL#post}, {URL#get}, or {URL#delete}. This is basically a string with a few additional methods including:
34
34
 
35
35
  The time the request took in seconds
36
- The http code of the response and whether the request was successful or not (code == 200).
36
+ The http code of the response and whether the request was successful or not (code == 2xx).
37
37
 
38
38
  response.time # => 1.6
39
39
  response.code # => 200
@@ -52,10 +52,35 @@ You can make GET, POST, or DELETE requests without doing any special formatting.
52
52
  url.params.delete(:message)
53
53
  url.delete
54
54
 
55
+ === JSON
56
+
57
+ If you've initialized the Yajl, JSON, or Active Service gems you can call .json on any response object.
58
+
59
+ url = URL.new('https://graph.facebook.com/37901410')
60
+ url.get.json # => => {"name"=>"Tal Atlas", "gender"=>"male", "id"=>"37901410", "last_name"=>"Atlas", "locale"=>"en_US", "link"=>"http://www.facebook.com/talatlas", "first_name"=>"Tal"}
61
+
62
+ === Make Custom Objects
63
+
64
+ Make objects designed around specific urls
65
+
66
+ class FacebookURL < URL('http://www.facebook.com/__test_me__/foo/__test_again__')
67
+ allow_changed :subdomain
68
+ allow_params :foo, :bar
69
+ end
70
+
71
+ This will create a FacebookURL object where you can only change the subdomain, the params foo and bar, and the parts of the paths tagged
72
+ test_me and test_again. This object has the getters and setters: subdomain, foo, bar, test_me, and test_again. You can then call .to_s,
73
+ .get, .post, or .delete.
74
+
75
+ The object has an instance variable defined as @url which is a url object you can manipulate.
76
+
55
77
  == TODO
78
+ * Fast Dup method
56
79
  * More Documentation
57
80
  * More specs
58
81
  * Make faster
82
+ * JSON support
83
+ * More robust subdomain/path methods
59
84
 
60
85
  == Note on Patches/Pull Requests
61
86
 
data/Rakefile CHANGED
@@ -10,23 +10,17 @@ begin
10
10
  gem.email = "me@tal.by"
11
11
  gem.homepage = "http://github.com/talby/url"
12
12
  gem.authors = ["Tal Atlas"]
13
- gem.add_development_dependency "rspec", ">= 1.2.9"
13
+ gem.add_development_dependency "rspec", "~> 2.0"
14
14
  end
15
15
  Jeweler::GemcutterTasks.new
16
16
  rescue LoadError
17
17
  puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
18
18
  end
19
19
 
20
- require 'spec/rake/spectask'
21
- Spec::Rake::SpecTask.new(:spec) do |spec|
22
- spec.libs << 'lib' << 'spec'
23
- spec.spec_files = FileList['spec/**/*_spec.rb']
24
- end
25
-
26
- Spec::Rake::SpecTask.new(:rcov) do |spec|
27
- spec.libs << 'lib' << 'spec'
28
- spec.pattern = 'spec/**/*_spec.rb'
29
- spec.rcov = true
20
+ require 'rspec/core/rake_task'
21
+ RSpec::Core::RakeTask.new do |t|
22
+ t.rspec_opts = ["-c", "-f progress", "-r ./spec/spec_helper.rb"]
23
+ t.pattern = 'spec/**/*_spec.rb'
30
24
  end
31
25
 
32
26
  task :spec => :check_dependencies
data/VERSION.yml CHANGED
@@ -1,5 +1,4 @@
1
- ---
1
+ ---
2
+ :minor: 2
3
+ :patch: 0
2
4
  :major: 0
3
- :minor: 1
4
- :patch: 2
5
- :build:
@@ -0,0 +1,107 @@
1
+ module URL::Classer
2
+ VAR_MATCHER = /__([A-Za-z]?[A-Za-z_]*[A-Za-z])__/
3
+
4
+ module ClassMethods
5
+ def allowed_params
6
+ @allowed_params ||= []
7
+ end
8
+ private
9
+ def allow_changed *args
10
+ args.flatten!
11
+ def_delegators :@url, :subdomains if args.include?(:subdomain)
12
+ def_delegators :@url, :subdomain if args.include?(:subdomains)
13
+ def_delegators :@url, :[], :[]= if args.include?(:params)
14
+ def_delegators :@url, *args
15
+ end
16
+
17
+ def allow_params *args
18
+ args.flatten.each do |arg|
19
+ arg = arg.to_sym
20
+ self.allowed_params << arg
21
+ define_method arg do
22
+ @url.params[arg]
23
+ end
24
+
25
+ define_method "#{arg}=" do |val|
26
+ @url.params[arg] = val
27
+ end
28
+ end
29
+ end
30
+
31
+ def overrideable_path_val v
32
+ v = v.to_s.downcase
33
+ define_method v do
34
+ @var_map[v]
35
+ end
36
+
37
+ define_method "#{v}=" do |val|
38
+ @var_map[v] = val
39
+
40
+ p = self.class.const_get(:URL).path.dup
41
+
42
+ @var_map.each do |key,value|
43
+ p.gsub!("__#{key}__", value.to_s)
44
+ end
45
+
46
+ @url.path = p
47
+
48
+ val
49
+ end
50
+ end
51
+
52
+ end
53
+
54
+ module InstanceMethods
55
+ def initialize(opts={})
56
+ @url = self.class.const_get(:URL).dup
57
+
58
+ @var_map = {}
59
+
60
+ opts.each do |op,v|
61
+ send("#{op}=",v)
62
+ end
63
+ end
64
+
65
+ def to_s
66
+ @url.to_s
67
+ end
68
+
69
+ def dup
70
+ n_url = @url.dup
71
+ n = super
72
+ n.instance_variable_set(:@url, n_url)
73
+ n
74
+ end
75
+
76
+ end
77
+
78
+ def self.included(receiver)
79
+ receiver.extend Forwardable
80
+ receiver.send :def_delegators, :@url, :get, :post, :delete, :inspect
81
+
82
+ receiver.extend ClassMethods
83
+ receiver.send :include, InstanceMethods
84
+ end
85
+ end
86
+
87
+ def URL url
88
+ if url.is_a?(URL)
89
+ url = url.dup
90
+ else
91
+ url = ::URL.new(url)
92
+ end
93
+
94
+ klass = Class.new do
95
+ include URL::Classer
96
+
97
+ vars = url.path.scan(URL::Classer::VAR_MATCHER).flatten
98
+
99
+ vars.each do |var|
100
+ overrideable_path_val(var)
101
+ end
102
+ end
103
+
104
+ klass.const_set(:URL, url.freeze)
105
+
106
+ klass
107
+ end
@@ -0,0 +1,9 @@
1
+ class URL
2
+ class ASJSONHandler < JSONHandler
3
+
4
+ def parse
5
+ ActiveSupport::JSON.decode(@str)
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,9 @@
1
+ class URL
2
+ class BaseJSONHandler < JSONHandler
3
+
4
+ def parse
5
+ JSON.parse(@str)
6
+ end
7
+
8
+ end
9
+ end
@@ -0,0 +1,59 @@
1
+ class URL
2
+ # Net::HTTP Handler
3
+ class NetHandler < RequestHandler
4
+ def get(args={})
5
+ http = http_obj
6
+ request = Net::HTTP::Get.new(make_path + url.params.to_s)
7
+ t = Time.now
8
+ resp = http.request(request)
9
+ make_str(resp,Time.now-t)
10
+ end
11
+
12
+ def post(args={})
13
+ http = http_obj
14
+ request = Net::HTTP::Post.new(make_path)
15
+ request.set_form_data(url.params)
16
+ t = Time.now
17
+ resp = http.request(request)
18
+ make_str(resp,Time.now-t)
19
+ end
20
+
21
+ def delete(args={})
22
+ http = http_obj
23
+ request = Net::HTTP::Delete.new(make_path + url.params.to_s)
24
+ t = Time.now
25
+ resp = http.request(request)
26
+ make_str(resp,Time.now-t)
27
+ end
28
+
29
+ private
30
+
31
+ def make_path
32
+ url.path
33
+ end
34
+
35
+ def make_str(resp,time)
36
+ hsh = {
37
+ :code => resp.code.to_i,
38
+ :time => time,
39
+ :body => resp.body,
40
+ :response => resp,
41
+ :url => url.to_s
42
+ }
43
+
44
+ Response.new(hsh)
45
+ end
46
+
47
+ def http_obj
48
+ uri = url.to_uri
49
+ http = Net::HTTP.new(uri.host,uri.port)
50
+
51
+ if url.scheme == 'https'
52
+ http.use_ssl = true
53
+ http.verify_mode = OpenSSL::SSL::VERIFY_NONE
54
+ end
55
+
56
+ http
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,37 @@
1
+ class URL
2
+ # Typhoeus handler
3
+ class TyHandler < RequestHandler
4
+
5
+ def get(args={})
6
+ resp = Typhoeus::Request.get(url.to_s)
7
+
8
+ make_str(resp)
9
+ end
10
+
11
+ def post(args={})
12
+ resp = Typhoeus::Request.post(url.to_s(:params => false), :params => url.params)
13
+
14
+ make_str(resp)
15
+ end
16
+
17
+ def delete(args={})
18
+ resp = Typhoeus::Request.delete(url.to_s)
19
+ make_str(resp)
20
+ end
21
+
22
+ private
23
+
24
+ def make_str(resp)
25
+ hsh = {
26
+ :code => resp.code,
27
+ :time => resp.time,
28
+ :body => resp.body,
29
+ :response => resp,
30
+ :url => url.to_s
31
+ }
32
+
33
+ Response.new(hsh)
34
+ end
35
+
36
+ end
37
+ end
@@ -0,0 +1,13 @@
1
+ class URL
2
+ class YajlHandler < JSONHandler
3
+
4
+ def parse
5
+ parser.parse(@str.to_s)
6
+ end
7
+
8
+ private
9
+ def parser
10
+ @parser ||= Yajl::Parser.new
11
+ end
12
+ end
13
+ end
data/lib/url/handlers.rb CHANGED
@@ -13,100 +13,37 @@ class URL
13
13
  # :url => url.to_s
14
14
  # }
15
15
  # Response.new(hsh)
16
- class Handler
16
+ class RequestHandler
17
17
  attr_reader :url
18
18
  def initialize(url)
19
19
  @url = url
20
20
  end
21
- end
22
-
23
- # Typhoeus handler
24
- class TyHandler < Handler
25
21
 
26
22
  def get(args={})
27
- resp = Typhoeus::Request.get(url.to_s)
28
-
29
- make_str(resp)
23
+ raise Exception, "You need to implement #{self.class}#get"
30
24
  end
31
25
 
32
26
  def post(args={})
33
- resp = Typhoeus::Request.post(url.to_s(:params => false), :params => url.params)
34
-
35
- make_str(resp)
27
+ raise Exception, "You need to implement #{self.class}#post"
36
28
  end
37
29
 
38
- def delete
39
- resp = Typhoeus::Request.delete(url.to_s)
40
- make_str(resp)
41
- end
42
-
43
- private
44
-
45
- def make_str(resp)
46
- hsh = {
47
- :code => resp.code,
48
- :time => resp.time,
49
- :body => resp.body,
50
- :response => resp,
51
- :url => url.to_s
52
- }
53
-
54
- Response.new(hsh)
30
+ def delete(args={})
31
+ raise Exception, "You need to implement #{self.class}#delete"
55
32
  end
56
-
57
33
  end
58
34
 
59
- # Net::HTTP Handler
60
- class NetHandler < Handler
61
- def get(args={})
62
- http = http_obj
63
- request = Net::HTTP::Get.new(url.path + url.params.to_s)
64
- t = Time.now
65
- resp = http.request(request)
66
- make_str(resp,Time.now-t)
35
+ class JSONHandler
36
+ attr_reader :str
37
+ def initialize(str)
38
+ @str = str
67
39
  end
68
40
 
69
- def post(args={})
70
- http = http_obj
71
- request = Net::HTTP::Post.new(url.path)
72
- request.set_form_data(url.params)
73
- t = Time.now
74
- resp = http.request(request)
75
- make_str(resp,Time.now-t)
41
+ def parse
42
+ raise Exception, "You need to implement #{self.class}#parse"
76
43
  end
77
44
 
78
- def delete(args={})
79
- http = http_obj
80
- request = Net::HTTP::Delete.new(url.path + url.params.to_s)
81
- t = Time.now
82
- resp = http.request(request)
83
- make_str(resp,Time.now-t)
84
- end
85
-
86
- private
87
-
88
- def make_str(resp,time)
89
- hsh = {
90
- :code => resp.code.to_i,
91
- :time => time,
92
- :body => resp.body,
93
- :response => resp,
94
- :url => url.to_s
95
- }
96
-
97
- Response.new(hsh)
98
- end
99
-
100
- def http_obj
101
- uri = url.to_uri
102
- http = Net::HTTP.new(uri.host,uri.port)
103
-
104
- if url.scheme == 'https'
105
- http.use_ssl = true
106
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
107
- end
108
-
109
- http
110
- end
111
45
  end
112
- end
46
+
47
+ end
48
+
49
+ Dir[File.join(File.dirname(__FILE__),'handlers','*.rb')].each {|f| require f}
@@ -1,68 +1,50 @@
1
- require "delegate"
2
-
3
1
  class URL
4
2
 
5
- # The Response class is a deleegate to string which also contains metadata about the request.
6
- # These methods are also available
7
- # * body
8
- # * code - http code
9
- # * response - the original response object from whatever handler you chose
10
- # * time - time taken to make call
11
- # * success? - whether the http code is 200
12
- # * url - the URL the object was gotten from
13
- class Response < DelegateClass(String)
14
- # The time taken for the request
15
- # @returns [Integer]
16
- attr_reader :time
17
-
18
- # The http code return
19
- # @returns [Integer] eg. 200, 404, 500, 503
20
- attr_reader :code
21
-
22
- # The response object generated by the handler
23
- # @returns [Net::HTTPResponse,Typhoeus::Response]
24
- attr_reader :response
25
-
26
- # The url which generated this response
27
- # @returns [String]
28
- attr_reader :url
29
-
30
- # @param [String] body The body of the response object, main string
31
- # @param [Hash] args Additional arguments: :time,:code,:response,:url
32
- def initialize(str,args={})
33
- if str.is_a?(Hash)
34
- args = str
35
- str = args[:body]
36
- end
37
-
38
- raise unless str
39
- super(str)
40
- args.each do |key, value|
41
- instance_variable_set "@#{key}", value
42
- end
3
+ # A hash where all keys are symbols
4
+ class Mash < Hash
5
+ # Set the value of a param
6
+ def []=(k,v)
7
+ k = k.to_s.to_sym unless k.is_a?(Symbol)
8
+ super(k,v)
43
9
  end
44
10
 
45
- # Compares {Response#code} to 200
46
- # @returns [true,false]
47
- def success?
48
- return @successful if @successful
49
-
50
- code == 200
11
+ # Read the value of a param
12
+ def [](k)
13
+ k = k.to_s.to_sym unless k.is_a?(Symbol)
14
+ super(k)
51
15
  end
52
16
  end
53
17
 
54
- class ParamsHash < Hash
18
+ class ParamsHash < Mash
55
19
 
56
20
  # Merges the array into a parameter string of the form <tt>?key=value&foo=bar</tt>
57
21
  def to_s
58
22
  return '' if empty?
59
23
  '?' + to_a.inject(Array.new) do |ret,param|
60
- val = param[1].to_s
61
-
62
- val = CGI.escape(val)# if val =~ /(\/|\?|\s)/
24
+ key = param[0].to_s
25
+ val = param[1]
63
26
 
64
27
  if param && val
65
- ret << %{#{param[0].to_s}=#{val}}
28
+ if val.is_a?(Hash)
29
+ # TODO: Make this recusrive
30
+ val.each do |param_key,param_val|
31
+ param_key = CGI.escape("#{key}[#{param_key}]")
32
+ param_val = CGI.escape(param_val.to_s)
33
+ ret << %Q{#{param_key}=#{param_val}}
34
+ end
35
+ elsif val.is_a?(Array)
36
+ # TODO: Make this recusrive
37
+ val.each_with_index do |param_val,i|
38
+ param_key = CGI.escape("#{key}[]")
39
+ param_val = CGI.escape(param_val.to_s)
40
+ ret << %Q{#{param_key}=#{param_val}}
41
+ end
42
+ else
43
+ val = val.to_s
44
+
45
+ val = CGI.escape(val)# if val =~ /(\/|\?|\s)/
46
+ ret << %{#{param[0].to_s}=#{val}}
47
+ end
66
48
  elsif param
67
49
  ret << param[0].to_s
68
50
  end
@@ -0,0 +1,60 @@
1
+ require "delegate"
2
+
3
+ class URL
4
+
5
+ # The Response class is a deleegate to string which also contains metadata about the request.
6
+ # These methods are also available
7
+ # * body
8
+ # * code - http code
9
+ # * response - the original response object from whatever handler you chose
10
+ # * time - time taken to make call
11
+ # * success? - whether the http code is 2xx
12
+ # * url - the URL the object was gotten from
13
+ class Response < DelegateClass(String)
14
+ # The time taken for the request
15
+ # @returns [Integer]
16
+ attr_reader :time
17
+
18
+ # The http code return
19
+ # @returns [Integer] eg. 200, 404, 500, 503
20
+ attr_reader :code
21
+
22
+ # The response object generated by the handler
23
+ # @returns [Net::HTTPResponse,Typhoeus::Response]
24
+ attr_reader :response
25
+
26
+ # The url which generated this response
27
+ # @returns [String]
28
+ attr_reader :url
29
+
30
+ # @param [String] body The body of the response object, main string
31
+ # @param [Hash] args Additional arguments: :time,:code,:response,:url
32
+ def initialize(str,args={})
33
+ if str.is_a?(Hash)
34
+ args = str
35
+ str = args[:body]
36
+ end
37
+
38
+ raise unless str
39
+ super(str)
40
+ args.each do |key, value|
41
+ instance_variable_set "@#{key}", value
42
+ end
43
+ end
44
+
45
+ # Compares {Response#code} to 2xx
46
+ # @returns [true,false]
47
+ def success?
48
+ return @successful if @successful
49
+
50
+ (200..299).include?(code)
51
+ end
52
+
53
+ def json
54
+ raise StandardError, 'No JSON library initialized' unless URL.json_handler
55
+ URL.json_handler.new(self).parse
56
+ end
57
+
58
+ end
59
+
60
+ end
data/lib/url.rb CHANGED
@@ -2,8 +2,11 @@ require "net/http"
2
2
  require "net/https"
3
3
  require 'uri'
4
4
  require 'cgi'
5
+ require 'forwardable'
5
6
 
6
- files = Dir.glob(File.join(File.dirname(__FILE__),'url','**','*.rb'))
7
+
8
+ files = Dir.glob(File.join(File.dirname(__FILE__),'url','*.rb'))
9
+ files.delete_if {|f| f =~ /url\/(classer)\.rb/}
7
10
  files.each { |f| require f }
8
11
 
9
12
  # Main class for managing urls
@@ -20,12 +23,45 @@ files.each { |f| require f }
20
23
  # url.params[:foo] = 'bar'
21
24
  # url.to_s # => 'https://my.mail.google.com/mail/?foo=bar&shva=1#mbox'
22
25
  class URL
23
- attr_reader :string, :params
26
+ extend Forwardable
27
+ attr_reader :string
28
+
29
+ # The params for the request
30
+ # @returns [URL::ParamsHash]
31
+ attr_reader :params
24
32
 
25
33
  # Attributes of the URL which are editable
26
- attr_accessor :subdomain, :domain, :path, :scheme, :format, :port, :hash
34
+ # @returns [String]
35
+ attr_accessor :domain, :scheme, :format, :port, :hash
36
+
37
+ # The path for the request
38
+ # @returns [URL::Path]
39
+ attr_reader :path
40
+
41
+ # Set the path for the request
42
+ def path=str
43
+ if str.nil? || str.empty?
44
+ str = '/'
45
+ end
46
+
47
+ @path = str
48
+ end
49
+
50
+ # Returns array of subdomains
51
+ # @returns [URL::Subdomain]
52
+ attr_reader :subdomain
27
53
  alias_method :subdomains, :subdomain
28
54
 
55
+ # @param [Array,String] subdomain An array or string for subdomain
56
+ def subdomain=(s)
57
+ if s.is_a?(String)
58
+ s = s.split('.')
59
+ end
60
+
61
+ @subdomain = s
62
+ end
63
+ alias_method :subdomains=, :subdomain=
64
+
29
65
  # Creates a new URL object
30
66
  # @param [String] URL the starting url to work with
31
67
  def initialize str
@@ -33,7 +69,7 @@ class URL
33
69
  sp = URI.split(@string)
34
70
  @scheme = sp[0]
35
71
  @port = sp[3]
36
- @path = sp[5]
72
+ self.path = sp[5]
37
73
  @format = @path.gsub(/(.+\.)/,'')
38
74
  @hash = sp[8]
39
75
 
@@ -54,18 +90,20 @@ class URL
54
90
  @domain = nil
55
91
  @subdomain = nil
56
92
  end
93
+
94
+ @params = ParamsHash.new
57
95
  if sp[7]
58
- @params = sp[7].gsub('?','').split('&').inject(ParamsHash.new) do |result,param|
59
- key,value = param.split('=')
96
+ sp[7].gsub('?','').split('&').each do |myp|
97
+ key,value = myp.split('=')
60
98
  value = CGI.unescape(value) if value
61
- result[key.to_sym] = value if key
62
- result
99
+ @params[key.to_sym] = value if key
63
100
  end
64
- else
65
- @params = ParamsHash.new
66
101
  end
67
102
  end
68
103
 
104
+ def_delegators :@params, :[], :[]=
105
+
106
+ # The full hostname (not including port) for the URL
69
107
  def host
70
108
  [@subdomain,@domain].flatten.compact.join('.')
71
109
  end
@@ -97,8 +135,41 @@ class URL
97
135
 
98
136
  class << self
99
137
  # Define the request handler to use. If Typhoeus is setup it will use {TyHandler} otherwise will default back to Net::HTTP with {NetHandler}
100
- # @return [Handler]
101
- attr_accessor :req_handler
138
+ # @return [RequstHandler]
139
+ def req_handler
140
+ return @req_handler if @req_handler
141
+
142
+ if defined?(Typhoeus)
143
+ URL.req_handler = URL::TyHandler
144
+ else
145
+ URL.req_handler = URL::NetHandler
146
+ end
147
+ end
148
+
149
+ # Define the request handler to use. If Typhoeus is setup it will use {TyHandler} otherwise will default back to Net::HTTP with {NetHandler}
150
+ # @param [RequstHandler]
151
+ # @return [RequstHandler]
152
+ def req_handler=r
153
+ raise ArgumentError, 'Must be a subclass of URL::RequestHandler' unless r.nil? || r < RequestHandler
154
+ @req_handler = r
155
+ end
156
+
157
+ def json_handler
158
+ return @json_handler if @json_handler
159
+
160
+ if defined?(Yajl)
161
+ URL.json_handler = URL::YajlHandler
162
+ elsif defined?(JSON)
163
+ URL.json_handler = URL::BaseJSONHandler
164
+ elsif defined?(ActiveSupport::JSON)
165
+ URL.json_handler = URL::ASJSONHandler
166
+ end
167
+ end
168
+
169
+ def json_handler=r
170
+ raise ArgumentError, 'Must be a subclass of URL::JSONHandler' unless r.nil? || r < JSONHandler
171
+ @json_handler = r
172
+ end
102
173
  end
103
174
 
104
175
  # Performs a get request for the current URL
@@ -120,18 +191,30 @@ class URL
120
191
  end
121
192
 
122
193
  def inspect
123
- "#<URL #{to_s}>"
194
+ "#<#{self.class} #{to_s}>"
124
195
  end
125
196
 
126
- if defined?(Typhoeus)
127
- URL.req_handler = TyHandler
128
- else
129
- URL.req_handler = NetHandler
197
+ def dup
198
+ URL.new(to_s)
130
199
  end
131
200
 
132
- private
201
+ # The request handler for this
202
+ # @return [Handler]
133
203
  def req_handler
134
- self.class.req_handler.new(self)
204
+ (@req_handler||self.class.req_handler).new(self)
205
+ end
206
+
207
+ def =~ reg
208
+ to_s =~ reg
135
209
  end
210
+
211
+ # Sets the handler to use for this request
212
+ # @param [RequstHandler]
213
+ # @return [RequstHandler]
214
+ def req_handler=r
215
+ raise ArgumentError, 'Must be a subclass of URL::Handler' unless r < RequestHandler
216
+ @req_handler = r
217
+ end
218
+
136
219
  end
137
220
 
@@ -0,0 +1,66 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+ require 'url/classer'
3
+
4
+ describe "URL()" do
5
+
6
+ before(:all) do
7
+ class FacebookURL < URL('http://www.facebook.com/__test_me__/foo/__test_again__')
8
+ allow_changed :subdomain
9
+ allow_params :foo, :bar
10
+ end
11
+ end
12
+
13
+ it "should create a class" do
14
+ url = 'http://www.facebook.com'
15
+ lambda {class FacebookURL2 < URL(url); end}.should_not raise_error
16
+
17
+ FacebookURL2.new.to_s.should == 'http://www.facebook.com/'
18
+ FacebookURL2.new.should be_a(URL::Classer)
19
+ end
20
+
21
+ context '.new' do
22
+ subject {FacebookURL.new}
23
+
24
+ it "shoud work like whatever" do
25
+ subject.subdomain << 'us'
26
+ subject.to_s.should =~ /^http:\/\/www\.us\.facebook.com/
27
+
28
+ u = FacebookURL.new
29
+ u.to_s.should =~ /^http:\/\/www\.facebook.com/
30
+ end
31
+
32
+ it "should dup" do
33
+ subject.subdomain << 'us'
34
+ d = subject.dup
35
+ d.subdomain.should == ['www','us']
36
+
37
+ d.subdomain << '1'
38
+ d.subdomain.should == ['www','us','1']
39
+ subject.subdomain.should == ['www','us']
40
+ end
41
+
42
+ it "should allow params" do
43
+ subject.foo = 1
44
+ subject.foo.should == 1
45
+ subject.to_s.should =~ /foo=1/
46
+ end
47
+
48
+ it "should set vars" do
49
+ subject.test_me = 'foobar'
50
+ subject.test_me.should == 'foobar'
51
+
52
+ subject.test_again = 'abc'
53
+ subject.to_s.should == "http://www.facebook.com/foobar/foo/abc"
54
+
55
+ subject.test_again = 'aaa'
56
+ subject.to_s.should == "http://www.facebook.com/foobar/foo/aaa"
57
+ end
58
+
59
+ it "should set vars in create" do
60
+ u = FacebookURL.new(:test_me => 'foobar', :test_again => 'abc')
61
+
62
+ u.to_s.should == "http://www.facebook.com/foobar/foo/abc"
63
+ end
64
+ end
65
+
66
+ end
@@ -0,0 +1,69 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '/spec_helper')
2
+
3
+ shared_examples_for "all requests" do
4
+ it "should work" do
5
+ @resp.should be_success
6
+ end
7
+
8
+ it "should have a response of the correct class" do
9
+ @resp.response.should be_a(@resp_class)
10
+ end
11
+
12
+ it "shoudl have all attribures" do
13
+ @resp.time.should be_a(Float)
14
+ @resp.code.should be_a(Integer)
15
+ @resp.url.should be_a(String)
16
+ end
17
+ end
18
+
19
+ shared_examples_for "all builds" do
20
+
21
+
22
+ before do
23
+ @url = URL.new('http://www.omgpop.com')
24
+ end
25
+
26
+ describe "#get" do
27
+ before do
28
+ @resp = @url.get
29
+ end
30
+ it_should_behave_like "all requests"
31
+ end
32
+
33
+ describe "#post" do
34
+ before do
35
+ @resp = @url.post
36
+ end
37
+ it_should_behave_like "all requests"
38
+ end
39
+
40
+ describe "#delete" do
41
+ before do
42
+ @resp = @url.delete
43
+ end
44
+ it_should_behave_like "all requests"
45
+ end
46
+ end
47
+
48
+ describe "Typhoeus", URL do
49
+ before(:all) do
50
+ require 'typhoeus'
51
+ URL.req_handler = URL::TyHandler
52
+ @resp_class = Typhoeus::Response
53
+ end
54
+
55
+ it_should_behave_like "all builds"
56
+
57
+ end
58
+
59
+
60
+ describe "Net::HTTP", URL do
61
+ before(:all) do
62
+ require 'net/http'
63
+ URL.req_handler = URL::NetHandler
64
+ @resp_class = Net::HTTPResponse
65
+ end
66
+
67
+ it_should_behave_like "all builds"
68
+
69
+ end
data/spec/json_spec.rb ADDED
@@ -0,0 +1,13 @@
1
+ require 'json'
2
+ require File.dirname(__FILE__) + '/spec_helper'
3
+
4
+ describe URL do
5
+ context "A json response" do
6
+ subject { URL.new('https://graph.facebook.com/37901410') }
7
+
8
+ it "should parse json" do
9
+ subject.get.json.should be_a(Hash)
10
+ end
11
+ end
12
+
13
+ end
data/spec/spec_helper.rb CHANGED
@@ -1,9 +1,5 @@
1
1
  $LOAD_PATH.unshift(File.dirname(__FILE__))
2
2
  $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
3
3
  require 'url'
4
- require 'spec'
5
- require 'spec/autorun'
4
+ require 'rspec'
6
5
 
7
- Spec::Runner.configure do |config|
8
-
9
- end
data/spec/url_spec.rb CHANGED
@@ -28,7 +28,11 @@ describe URL do
28
28
 
29
29
  describe '#to_s' do
30
30
  it "should roundtrip" do
31
- @url.to_s.should == 'https://mail.google.com:8080/foo/bar/baz?q=one&foo=bar'
31
+ s = @url.to_s
32
+ s.should include 'https://mail.google.com:8080/foo/bar/baz?'
33
+ s.should include 'q=one'
34
+ s.should include 'foo=bar'
35
+ s.should include '&'
32
36
  end
33
37
 
34
38
  it "should change and add params" do
@@ -46,72 +50,80 @@ describe URL do
46
50
  end
47
51
  end
48
52
 
49
- end
50
-
51
- shared_examples_for "all requests" do
52
- it "should work" do
53
- @resp.should be_success
54
- end
55
-
56
- it "should have a response of the correct class" do
57
- @resp.response.should be_a(@resp_class)
58
- end
59
53
 
60
- it "shoudl have all attribures" do
61
- @resp.time.should be_a(Float)
62
- @resp.code.should be_a(Integer)
63
- @resp.url.should be_a(String)
54
+ it "should should modify params easily" do
55
+ @url[:foo] = '123'
56
+ @url['foo'].should == '123'
57
+ @url.to_s.should include('foo=123')
58
+
59
+ @url['foo'] = '345'
60
+ @url[:foo].should == '345'
61
+ @url.to_s.should include('foo=345')
64
62
  end
65
- end
66
-
67
- shared_examples_for "all builds" do
68
63
 
69
-
70
- before do
71
- @url = URL.new('http://www.omgpop.com/')
64
+ it "should should accept arbitrary req handlers" do
65
+ class TestReq < URL::TyHandler; end
66
+ @url.req_handler = TestReq
67
+ @url.req_handler.should be_a(URL::RequestHandler)
68
+ @url.req_handler.should be_instance_of(TestReq)
72
69
  end
73
70
 
74
- describe "#get" do
75
- before do
76
- @resp = @url.get
77
- end
78
- it_should_behave_like "all requests"
71
+ it "should should make sure there's always a path" do
72
+ @url.path = nil
73
+ @url.path.should == '/'
74
+
75
+ @url.path = ''
76
+ @url.path.should == '/'
79
77
  end
80
78
 
81
- describe "#post" do
82
- before do
83
- @resp = @url.post
84
- end
85
- it_should_behave_like "all requests"
79
+ it "should match =~" do
80
+ (@url =~ /mail\.google\.com/).should == (@url.to_s =~ /mail\.google\.com/)
86
81
  end
87
82
 
88
- describe "#delete" do
89
- before do
90
- @resp = @url.delete
91
- end
92
- it_should_behave_like "all requests"
93
- end
94
83
  end
95
84
 
96
- describe "Typhoeus", URL do
97
- before(:all) do
98
- require 'typhoeus'
99
- URL.req_handler = URL::TyHandler
100
- @resp_class = Typhoeus::Response
85
+ describe URL::ParamsHash, '#to_s' do
86
+ it "should make a param string" do
87
+ hsh = URL::ParamsHash.new
88
+
89
+ hsh[:foo] = 'bar'
90
+ hsh[1] = 2
91
+
92
+ str = hsh.to_s
93
+
94
+ # str.should match(/^?/)
95
+ str.should include('foo=bar')
96
+ str.should include('1=2')
101
97
  end
102
98
 
103
- it_should_behave_like "all builds"
104
-
105
- end
106
-
107
-
108
- describe "Net::HTTP", URL do
109
- before(:all) do
110
- require 'net/http'
111
- URL.req_handler = URL::NetHandler
112
- @resp_class = Net::HTTPResponse
113
- end\
114
-
115
- it_should_behave_like "all builds"
99
+ it "should make a param string with an array or hash" do
100
+ hsh = URL::ParamsHash.new
101
+
102
+ hsh[:test] = [*1..3]
103
+ hsh[:hash] = {:one => 1, :two => 2}
104
+
105
+ str = hsh.to_s
106
+
107
+ str.should include CGI.escape('hash[one]')+'=1'
108
+ str.should include CGI.escape('hash[two]')+'=2'
109
+ str.should include CGI.escape('test[]')+'=1'
110
+ str.should include CGI.escape('test[]')+'=2'
111
+ str.should include CGI.escape('test[]')+'=3'
112
+ end
116
113
 
114
+ it "should recursively make objects" do
115
+ pending('implementation')
116
+ hsh = URL::ParamsHash.new
117
+
118
+ hsh[:test] = [{:foo => 'bar', :bar => 'baz'},{:foo => 'baz'}]
119
+ hsh[:hash] = {:one => {'o' => 1}, :two => 2}
120
+
121
+ str = hsh.to_s
122
+
123
+ str.should include CGI.escape('test[][foo]')+'=bar'
124
+ str.should include CGI.escape('test[][bar]')+'=baz'
125
+ str.should include CGI.escape('test[][foo]')+'=baz'
126
+ str.should include CGI.escape('hash[one][o]')+'=1'
127
+ str.should include CGI.escape('hash[two]')+'=2'
128
+ end
117
129
  end
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: url
3
3
  version: !ruby/object:Gem::Version
4
- hash: 31
4
+ hash: 23
5
5
  prerelease: false
6
6
  segments:
7
7
  - 0
8
- - 1
9
8
  - 2
10
- version: 0.1.2
9
+ - 0
10
+ version: 0.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Tal Atlas
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2010-11-24 00:00:00 -05:00
18
+ date: 2011-01-31 00:00:00 -05:00
19
19
  default_executable:
20
20
  dependencies:
21
21
  - !ruby/object:Gem::Dependency
@@ -24,14 +24,13 @@ dependencies:
24
24
  requirement: &id001 !ruby/object:Gem::Requirement
25
25
  none: false
26
26
  requirements:
27
- - - ">="
27
+ - - ~>
28
28
  - !ruby/object:Gem::Version
29
- hash: 13
29
+ hash: 3
30
30
  segments:
31
- - 1
32
31
  - 2
33
- - 9
34
- version: 1.2.9
32
+ - 0
33
+ version: "2.0"
35
34
  type: :development
36
35
  version_requirements: *id001
37
36
  description: A simple url object to allow for OO based manipulation and usage of a url
@@ -45,14 +44,23 @@ extra_rdoc_files:
45
44
  - README.rdoc
46
45
  files:
47
46
  - .document
48
- - .gitignore
49
47
  - LICENSE
50
48
  - README.rdoc
51
49
  - Rakefile
52
50
  - VERSION.yml
53
51
  - lib/url.rb
52
+ - lib/url/classer.rb
54
53
  - lib/url/handlers.rb
54
+ - lib/url/handlers/as_json_handler.rb
55
+ - lib/url/handlers/base_json_handler.rb
56
+ - lib/url/handlers/net_handler.rb
57
+ - lib/url/handlers/ty_handler.rb
58
+ - lib/url/handlers/yajl_handler.rb
55
59
  - lib/url/helper_classes.rb
60
+ - lib/url/response.rb
61
+ - spec/classer_spec.rb
62
+ - spec/handler_spec.rb
63
+ - spec/json_spec.rb
56
64
  - spec/spec.opts
57
65
  - spec/spec_helper.rb
58
66
  - spec/url_spec.rb
@@ -61,8 +69,8 @@ homepage: http://github.com/talby/url
61
69
  licenses: []
62
70
 
63
71
  post_install_message:
64
- rdoc_options:
65
- - --charset=UTF-8
72
+ rdoc_options: []
73
+
66
74
  require_paths:
67
75
  - lib
68
76
  required_ruby_version: !ruby/object:Gem::Requirement
@@ -91,5 +99,8 @@ signing_key:
91
99
  specification_version: 3
92
100
  summary: A URL object
93
101
  test_files:
102
+ - spec/classer_spec.rb
103
+ - spec/handler_spec.rb
104
+ - spec/json_spec.rb
94
105
  - spec/spec_helper.rb
95
106
  - spec/url_spec.rb
data/.gitignore DELETED
@@ -1,24 +0,0 @@
1
- ## MAC OS
2
- .DS_Store
3
-
4
- ## TEXTMATE
5
- *.tmproj
6
- tmtags
7
-
8
- ## EMACS
9
- *~
10
- \#*
11
- .\#*
12
-
13
- ## VIM
14
- *.swp
15
-
16
- ## PROJECT::GENERAL
17
- coverage
18
- rdoc
19
- pkg
20
-
21
- ## PROJECT::SPECIFIC
22
- .yardoc/*
23
- .yard/*
24
- doc/*