Class: Request
- Includes:
- Chainable, CodeEvents
- Defined in:
- lib/source/redshift/request.rb
Defined Under Namespace
Classes: HTML, HeaderError, HttpMethodError, JSON
Constant Summary collapse
- METHODS =
%w(GET POST PUT DELETE)
- OPTIONS =
{ :url => '', :data => {}, :link => 'ignore', :async => true, :format => nil, :method => 'post', :encoding => 'utf-8', :is_success => nil, :emulation => true, :url_encoded => true, :eval_scripts => false, :eval_response => false, :headers => { 'X-Requested-With' => 'XMLHttpRequest', 'Accept' => 'text/javascript, text/html, application/xml, text/xml, */*' } }
Instance Method Summary collapse
-
#cancel ⇒ Object
call-seq: req.cancel -> req.
-
#check(*args, &block) ⇒ Object
call-seq: req.check(arg, …) { |request,args_array| block } -> true or false.
-
#execute(options = {}) ⇒ Object
call-seq: req.execute(options = {}) -> req.
-
#failure! ⇒ Object
call-seq: req.failure! -> req.
-
#headers ⇒ Object
call-seq: req.headers -> hash.
-
#initialize(options = {}) ⇒ Request
constructor
call-seq: Request.new(options = {}) -> request.
-
#on_state_change ⇒ Object
call-seq: req.on_state_change -> proc.
-
#process_scripts(str) ⇒ Object
call-seq: req.process_scripts(str) -> string or object.
-
#success!(text, xml) ⇒ Object
call-seq: req.success!(text, xml) -> req.
-
#success? ⇒ Boolean
call-seq: req.success? -> true or false.
Methods included from Chainable
#call_chain, #chain, #clear_chain
Methods included from CodeEvents
Constructor Details
#initialize(options = {}) ⇒ Request
call-seq:
Request.new(options = {}) -> request
Returns a new request with the given options.
33 34 35 36 37 38 39 40 |
# File 'lib/source/redshift/request.rb', line 33 def initialize( = {}) `this.__xhr__ = typeof(ActiveXObject)=='undefined' ? new XMLHttpRequest : new ActiveXObject('MSXML2.XMLHTTP')` @options = OPTIONS.merge() `#{@options[:headers]}.__xhr__=this.__xhr__` # MooTools sets the ResponseHeaders in the xhr # def (@options[:headers]).[](name) # only during execution, but allows you to get # `this.__xhr__.getResponseHeader(name)` # at them at any time. I'm not sure whether it # end # is necessary for us to emulate this exactly. end |
Instance Method Details
#cancel ⇒ Object
call-seq:
req.cancel -> req
Cancels the request, fires its “cancel” callback, and returns req.
47 48 49 50 51 52 53 54 55 |
# File 'lib/source/redshift/request.rb', line 47 def cancel return self unless @running @running = false `this.__xhr__.abort` `this.__xhr__.onreadystatechange=function(){;}` `this.__xhr__=typeof(ActiveXObject)=='undefined' ? new XMLHttpRequest : new ActiveXObject('MSXML2.XMLHTTP')` self.fire(:cancel) return self end |
#check(*args, &block) ⇒ Object
call-seq:
req.check(arg, ...) { |request,args_array| block } -> true or false
returns true
when Request object is not running or gets cancelled, otherwise returns false. also, seems equipped to ‘chain’ some additional function after itself
63 64 65 66 67 68 69 70 71 72 73 74 |
# File 'lib/source/redshift/request.rb', line 63 def check(*args, &block) return true unless @running case @options[:link] when 'cancel' self.cancel return true when 'chain' # self.chain(&block(self,args)) return false end return false end |
#execute(options = {}) ⇒ Object
call-seq:
req.execute(options = {}) -> req
Returns req
immediately if the request is already running. Otherwise, opens a connection and sends the data provided with the specified options.
82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/source/redshift/request.rb', line 82 def execute( = {}) # return self unless self.check(options) @options.update() raise(TypeError, 'can\'t convert %s to a String' % @options[:url].inspect) unless [String].include?(@options[:url].class) raise(TypeError, 'can\'t convert %s to a String' % @options[:method].inspect) unless [String, Symbol].include?(@options[:method].class) raise(TypeError, 'can\'t convert %s to a Hash' % @options[:data].inspect) unless [Hash].include?(@options[:data].class) raise(HttpMethodError, 'invalid HTTP method "%s" for %s' % [@options[:method],self]) unless METHODS.include?(method = @options[:method].to_s.upcase) @running = true data = @options[:data].to_query_string url = @options[:url] if @options[:format] format = "format=%s" % @options[:format] data = data.empty? ? format : [format, data].join('&') end if @options[:emulation] && %w(PUT DELETE).include?(method) _method = "_method=%s" % method data = data.empty? ? _method : [_method, data].join('&') method = 'POST' end if @options[:url_encoded] && method == 'POST' encoding = @options[:encoding] ? "; charset=%s" % @options[:encoding] : "" self.headers['Content-type'] = "application/x-www-form-urlencoded" + encoding end if data && method == 'GET' separator = url.include?('?') ? "&" : "?" url = [url, data].join(separator) data = nil end `this.__xhr__.open(method.__value__, url.__value__, #{@options[:async]})` `this.__xhr__.onreadystatechange = #{self.on_state_change}.__block__` @options[:headers].each do |k,v| `this.__xhr__.setRequestHeader(k.__value__,v.__value__)` # raise(HeaderError, "#{k} => #{v}") end self.fire(:request) `this.__xhr__.send($T(data)?data.__value__:'')` self.on_state_change.call unless @options[:async] return self end |
#failure! ⇒ Object
call-seq:
req.failure! -> req
Fires req’s “response” and “failure” callbacks, then returns req.
135 136 137 |
# File 'lib/source/redshift/request.rb', line 135 def failure! self.fire(:response).fire(:failure, @xhr); end |
#headers ⇒ Object
call-seq:
req.headers -> hash
Returns req’s HTTP headers as a Hash
.
144 145 146 |
# File 'lib/source/redshift/request.rb', line 144 def headers @options[:headers] end |
#on_state_change ⇒ Object
call-seq:
req.on_state_change -> proc
Returns a Proc
object
153 154 155 156 157 158 159 160 161 162 163 164 165 166 167 168 169 170 171 172 173 174 175 |
# File 'lib/source/redshift/request.rb', line 153 def on_state_change Proc.new do `var xhr=this.__xhr__` `if(xhr.readyState!=4||!#{@running}){return nil;}` @running = false @status = 0 `try{#{@status}=xhr.status}catch(e){;}` if self.success? @response = {:text => `$q(xhr.responseText)`, :xml => `xhr.responseXML`} self.success!(self.process_scripts(@response[:text]), @response[:xml]) else @response = {:text => nil, :xml => nil}; self.failure! end `xhr.onreadystatechange=function(){;}` return nil end end |
#process_scripts(str) ⇒ Object
call-seq:
req.process_scripts(str) -> string or object
If the HTTP response consists of JavaScript alone or if req’s eval_response
option is set to true
, evaluates the entire text of the response as JavaScript and returns the result.
Otherwise, returns a copy of str with any <script>
tags and their content removed. If req’s eval_scripts
option is set to true
, evaluates the removed scripts.
188 189 190 191 |
# File 'lib/source/redshift/request.rb', line 188 def process_scripts(str) return Document.execute_js(str) if @options[:eval_response] || `/(ecma|java)script/.test(this.__xhr__.getResponseHeader('Content-Type'))` return str.strip_scripts(@options[:eval_scripts]) end |
#success!(text, xml) ⇒ Object
call-seq:
req.success!(text, xml) -> req
Fires req’s “response” and “success” callbacks, then returns req.
198 199 200 |
# File 'lib/source/redshift/request.rb', line 198 def success!(text, xml) self.fire(:response, [text, xml]).fire(:success, [text, xml]).call_chain end |
#success? ⇒ Boolean
call-seq:
req.success? -> true or false
Returns true
if req’s status is in the 200s, false
otherwise.
207 208 209 |
# File 'lib/source/redshift/request.rb', line 207 def success? `#{@status}>=200&&#{@status}<300` end |