Yesterday I looked at the Request side of RestClient so I’m reading through the RestClient::Response
class today. RestClient::Request#execute
returns this response object from it’s #process_result
.
1 |
response = Response.new(Request.decode(res['content-encoding'], res.body), res, args) |
The Code
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 |
module RestClient # A Response from RestClient, you can access the response body, the code or the headers. # class Response < AbstractResponse attr_reader :body WARNING_MESSAGE = '[warning] The Response is no more a String and the Response content is now accessed through Response.body, please update your code' def initialize body, net_http_res, args super net_http_res, args @body = body || "" end def method_missing symbol, *args if body.respond_to? symbol warn WARNING_MESSAGE body.send symbol, *args else super end end def == o if super true else equal_body = (body == o) if equal_body warn WARNING_MESSAGE end equal_body end end def to_s body.to_s end def size body.size end end end |
RestClient::Response
is a pretty small class because there is a lot of common logic shared in it’s parent class RestClient::AbstractResponse
.
RestClient::Response#initialize
1 2 3 4 |
def initialize body, net_http_res, args super net_http_res, args @body = body || "" end |
#initialize
isn’t doing very much here, just calling it’s parent class (AbstractResponse
) and initializing the @body
attribute.
RestClient::Response#method_missing
1 2 3 4 5 6 7 8 |
def method_missing symbol, *args if body.respond_to? symbol warn WARNING_MESSAGE body.send symbol, *args else super end end |
This #method_missing
is setting up a proxy to the body. Based on the warning message here, I think RestClient used to return a string but now it’s returning the Response
object instead. Using #method_missing
this way is interesting, it keeps backwards compatibility and gives other developers time to update their own code.
RestClient::Response#==
1 2 3 4 5 6 7 8 9 10 11 |
def == o if super true else equal_body = (body == o) if equal_body warn WARNING_MESSAGE end equal_body end end |
This comparison method is doing two things. First it’s checking if the two objects are the same object (using super
). If that fails, it checks if the body contents are equal; if so it warns about the backwards compatibility (above) and then returns the results of that comparison.
RestClient::Response#to_s and RestClient::Response#size
1 2 3 4 5 6 7 |
def to_s body.to_s end def size body.size end |
Both of these methods are just delegated to the body object. At first I thought the #method_missing
call would handle #to_s
but then I remembered that all Ruby objects respond to #to_s
. This would prevent #method_missing
from being called and Response
would just return a string like:
#<RestClient::Response:0xb6f9e5dc>
Tomorrow I’ll look into AbstractResponse
class, since that’s where a lot of the processing logic for a Response
is at.