url 0.1.2 → 0.2.0

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