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.