Merge pull request #160 from jaimeiniesta/replace_hpricot_with_nokogiri

Replace hpricot with nokogiri
This commit is contained in:
Robin Ward 2013-02-14 07:55:19 -08:00
commit cba4c9051a
26 changed files with 3672 additions and 33 deletions

View File

@ -20,7 +20,6 @@ gem 'fastimage'
gem 'fog', require: false gem 'fog', require: false
gem 'has_ip_address' gem 'has_ip_address'
gem 'hiredis' gem 'hiredis'
gem 'hpricot'
gem 'i18n-js' gem 'i18n-js'
gem 'jquery-rails' gem 'jquery-rails'
gem 'multi_json' gem 'multi_json'
@ -71,6 +70,10 @@ group :assets do
gem 'uglifier' gem 'uglifier'
end end
group :test do
gem "fakeweb", "~> 1.3.0"
end
group :test, :development do group :test, :development do
gem 'certified' gem 'certified'
gem 'fabrication' gem 'fabrication'

View File

@ -151,6 +151,7 @@ GEM
multi_json (~> 1.0) multi_json (~> 1.0)
fabrication (2.5.4) fabrication (2.5.4)
facter (1.6.17) facter (1.6.17)
fakeweb (1.3.0)
faraday (0.8.5) faraday (0.8.5)
multipart-post (~> 1.1) multipart-post (~> 1.1)
fast_xs (0.8.0) fast_xs (0.8.0)
@ -192,7 +193,6 @@ GEM
highline (1.6.15) highline (1.6.15)
hike (1.2.1) hike (1.2.1)
hiredis (0.4.5) hiredis (0.4.5)
hpricot (0.8.6)
httpauth (0.2.0) httpauth (0.2.0)
i18n (0.6.1) i18n (0.6.1)
i18n-js (2.1.2) i18n-js (2.1.2)
@ -456,6 +456,7 @@ DEPENDENCIES
ember-rails! ember-rails!
eventmachine eventmachine
fabrication fabrication
fakeweb (~> 1.3.0)
fast_xs fast_xs
fastimage fastimage
fog fog
@ -464,7 +465,6 @@ DEPENDENCIES
guard-spork guard-spork
has_ip_address has_ip_address
hiredis hiredis
hpricot
i18n-js i18n-js
image_optim image_optim
jasminerice jasminerice

39
TESTING.md Normal file
View File

@ -0,0 +1,39 @@
# Discourse Developer Testing Guide
Some notes about testing Discourse:
## FakeWeb
We use the [FakeWeb](https://github.com/chrisk/fakeweb) gem to fake external web
requests.
For example, check out the specs on `specs/components/oneboxer`.
This has several advantages to making real requests:
* We freeze the expected response from the remote server.
* We don't need a network connection to run the specs.
* It's faster.
So, if you need to define a spec that makes a web request, you'll have to record
the real response to a fixture file, and tell FakeWeb to respond with it for the
URI of your request.
Check out `spec/components/oneboxer/amazon_onebox_spec.rb` for an example on
this.
### Recording responses
To record the actual response from the remote server, you can use curl and save the response to a file. We use the `-i` option to include headers in the output
curl -i http://en.m.wikipedia.org/wiki/Ruby > wikipedia.response
If you need to specify the User-Agent to send to the server, you can use `-A`:
curl -i -A 'Mozilla/5.0 (iPhone; CPU iPhone OS 5_0_1 like Mac OS X) AppleWebKit/534.46 (KHTML, like Gecko) Version/5.1 Mobile/9A405 Safari/7534.48.3' http://en.m.wikipedia.org/wiki/Ruby > wikipedia.response
If the remote server is responding with a redirect, you'll need to fake both the
original request and the one for the destination. Check out the
`wikipedia.response` and `wikipedia_redirected.response` files in
`spec/fixtures/oneboxer` for an example. You can also consider working directly
with the final URL for simplicity.

View File

@ -4,7 +4,6 @@ require_dependency 'rate_limiter'
require_dependency 'post_revisor' require_dependency 'post_revisor'
require 'archetype' require 'archetype'
require 'hpricot'
require 'digest/sha1' require 'digest/sha1'
class Post < ActiveRecord::Base class Post < ActiveRecord::Base

View File

@ -31,7 +31,7 @@ The following Ruby Gems are used in Discourse:
* [vestal_versions](https://rubygems.org/gems/vestal_versions) * [vestal_versions](https://rubygems.org/gems/vestal_versions)
* [coffee-rails](https://rubygems.org/gems/coffee-rails) * [coffee-rails](https://rubygems.org/gems/coffee-rails)
* [uglifier](https://rubygems.org/gems/uglifier) * [uglifier](https://rubygems.org/gems/uglifier)
* [hpricot](https://rubygems.org/gems/hpricot) * [nokogiri](https://rubygems.org/gems/nokogiri)
* [uuidtools](https://rubygems.org/gems/uuidtools) * [uuidtools](https://rubygems.org/gems/uuidtools)
* [rinku](https://rubygems.org/gems/rinku) * [rinku](https://rubygems.org/gems/rinku)
* [ruby-openid](https://rubygems.org/gems/ruby-openid) * [ruby-openid](https://rubygems.org/gems/ruby-openid)
@ -48,3 +48,4 @@ The following Ruby Gems are used in Discourse:
* [rb-inotify](https://rubygems.org/gems/rb-inotify) * [rb-inotify](https://rubygems.org/gems/rb-inotify)
* [terminal-notifier-guard](https://rubygems.org/gems/terminal-notifier-guard) * [terminal-notifier-guard](https://rubygems.org/gems/terminal-notifier-guard)
* [pry-rails](https://rubygems.org/gems/pry-rails) * [pry-rails](https://rubygems.org/gems/pry-rails)
* [fakeweb](https://rubygems.org/gems/fakeweb)

View File

@ -9,7 +9,7 @@ class CookedPostProcessor
@dirty = false @dirty = false
@opts = opts @opts = opts
@post = post @post = post
@doc = Hpricot(post.cooked) @doc = Nokogiri::HTML(post.cooked)
end end
def dirty? def dirty?

View File

@ -34,7 +34,7 @@ module Oneboxer
if Whitelist.allowed?(url) if Whitelist.allowed?(url)
page_html = open(url).read page_html = open(url).read
if page_html.present? if page_html.present?
doc = Hpricot(page_html) doc = Nokogiri::HTML(page_html)
# See if if it has an oembed thing we can use # See if if it has an oembed thing we can use
(doc/"link[@type='application/json+oembed']").each do |oembed| (doc/"link[@type='application/json+oembed']").each do |oembed|
@ -56,7 +56,7 @@ module Oneboxer
# Parse URLs out of HTML, returning the document when finished. # Parse URLs out of HTML, returning the document when finished.
def self.each_onebox_link(string_or_doc) def self.each_onebox_link(string_or_doc)
doc = string_or_doc doc = string_or_doc
doc = Hpricot(doc) if doc.is_a?(String) doc = Nokogiri::HTML(doc) if doc.is_a?(String)
onebox_links = doc.search("a.onebox") onebox_links = doc.search("a.onebox")
if onebox_links.present? if onebox_links.present?

View File

@ -22,19 +22,19 @@ module Oneboxer
end end
def parse(data) def parse(data)
hp = Hpricot(data) html_doc = Nokogiri::HTML(data)
result = {} result = {}
result[:title] = hp.at("h1") result[:title] = html_doc.at("h1")
result[:title] = result[:title].inner_html if result[:title].present? result[:title] = result[:title].inner_html if result[:title].present?
image = hp.at(".main-image img") image = html_doc.at(".main-image img")
result[:image] = image['src'] if image result[:image] = image['src'] if image
result[:by_info] = hp.at("#by-line") result[:by_info] = html_doc.at("#by-line")
result[:by_info] = BaseOnebox.remove_whitespace(result[:by_info].inner_html) if result[:by_info].present? result[:by_info] = BaseOnebox.remove_whitespace(result[:by_info].inner_html) if result[:by_info].present?
summary = hp.at("#description-and-details-content") summary = html_doc.at("#description-and-details-content")
result[:text] = summary.inner_html if summary.present? result[:text] = summary.inner_html if summary.present?
result result

View File

@ -12,20 +12,20 @@ module Oneboxer
def parse(data) def parse(data)
hp = Hpricot(data) html_doc = Nokogiri::HTML(data)
result = {} result = {}
m = hp.at("h1.doc-banner-title") m = html_doc.at("h1.doc-banner-title")
result[:title] = m.inner_text if m result[:title] = m.inner_text if m
m = hp.at("div#doc-original-text") m = html_doc.at("div#doc-original-text")
if m if m
result[:text] = BaseOnebox.replace_tags_with_spaces(m.inner_html) result[:text] = BaseOnebox.replace_tags_with_spaces(m.inner_html)
result[:text] = result[:text][0..MAX_TEXT] result[:text] = result[:text][0..MAX_TEXT]
end end
m = hp.at("div.doc-banner-icon img") m = html_doc.at("div.doc-banner-icon img")
result[:image] = m['src'] if m result[:image] = m['src'] if m
result result

View File

@ -17,17 +17,17 @@ module Oneboxer
def parse(data) def parse(data)
hp = Hpricot(data) html_doc = Nokogiri::HTML(data)
result = {} result = {}
m = hp.at("h1") m = html_doc.at("h1")
result[:title] = m.inner_text if m result[:title] = m.inner_text if m
m = hp.at("h4 ~ p") m = html_doc.at("h4 ~ p")
result[:text] = m.inner_text[0..MAX_TEXT] if m result[:text] = m.inner_text[0..MAX_TEXT] if m
m = hp.at(".product img.artwork") m = html_doc.at(".product img.artwork")
result[:image] = m['src'] if m result[:image] = m['src'] if m
result result

View File

@ -9,7 +9,7 @@ module Oneboxer
page_html = open(@url).read page_html = open(@url).read
return nil if page_html.blank? return nil if page_html.blank?
doc = Hpricot(page_html) doc = Nokogiri::HTML(page_html)
# Flikrs oembed just stopped returning images for no reason. Let's use opengraph instead. # Flikrs oembed just stopped returning images for no reason. Let's use opengraph instead.
open_graph = Oneboxer.parse_open_graph(doc) open_graph = Oneboxer.parse_open_graph(doc)

View File

@ -20,23 +20,23 @@ module Oneboxer
def parse(data) def parse(data)
hp = Hpricot(data) html_doc = Nokogiri::HTML(data)
result = {} result = {}
title = hp.at('title').inner_html title = html_doc.at('title').inner_html
result[:title] = title.gsub!(/ - Wikipedia, the free encyclopedia/, '') if title.present? result[:title] = title.gsub!(/ - Wikipedia, the free encyclopedia/, '') if title.present?
# get the first image > 150 pix high # get the first image > 150 pix high
images = hp.search("img").select { |img| img['height'].to_i > 150 } images = html_doc.search("img").select { |img| img['height'].to_i > 150 }
result[:image] = "http:#{images[0]["src"]}" unless images.empty? result[:image] = "http:#{images[0]["src"]}" unless images.empty?
# remove the table from mobile layout, as it can contain paras in some rare cases # remove the table from mobile layout, as it can contain paras in some rare cases
hp.search("table").remove html_doc.search("table").remove
# get all the paras # get all the paras
paras = hp.search("p") paras = html_doc.search("p")
text = "" text = ""
unless paras.empty? unless paras.empty?

View File

@ -19,7 +19,10 @@ describe CookedPostProcessor do
end end
it 'inserts the onebox' do it 'inserts the onebox' do
@cpp.html.should == "GANGNAM STYLE" @cpp.html.should == <<EXPECTED
<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN" "http://www.w3.org/TR/REC-html40/loose.dtd">
<html><body>GANGNAM STYLE</body></html>
EXPECTED
end end
end end

View File

@ -0,0 +1,44 @@
# encoding: utf-8
require 'spec_helper'
require 'oneboxer'
require 'oneboxer/amazon_onebox'
describe Oneboxer::AmazonOnebox do
before(:each) do
@o = Oneboxer::AmazonOnebox.new("http://www.amazon.com/Ruby-Programming-Language-David-Flanagan/dp/0596516177")
FakeWeb.register_uri(:get, @o.translate_url, :response => fixture_file('oneboxer/amazon.response'))
end
it "translates the URL" do
@o.translate_url.should == "http://www.amazon.com/gp/aw/d/0596516177"
end
it "generates the expected onebox for Amazon" do
@o.onebox.should == expected_amazon_result
end
private
def expected_amazon_result
<<EXPECTED
<div class='onebox-result'>
<div class='source'>
<div class='info'>
<a href='http://www.amazon.com/Ruby-Programming-Language-David-Flanagan/dp/0596516177' target="_blank">
<img class='favicon' src="/assets/favicons/amazon.png"> amazon.com
</a>
</div>
</div>
<div class='onebox-result-body'>
<img src="http://ecx.images-amazon.com/images/I/716dULgyHNL._SY180_.jpg" class="thumbnail">
<h3><a href="http://www.amazon.com/Ruby-Programming-Language-David-Flanagan/dp/0596516177" target="_blank">The Ruby Programming Language (Paperback)</a></h3>
<h4>David Flanagan, Yukihiro Matsumoto</h4>
The Ruby Programming Language is the authoritative guide to Ruby ...
</div>
<div class='clearfix'></div>
</div>
EXPECTED
end
end

View File

@ -0,0 +1,41 @@
# encoding: utf-8
require 'spec_helper'
require 'oneboxer'
require 'oneboxer/android_app_store_onebox'
describe Oneboxer::AndroidAppStoreOnebox do
before(:each) do
@o = Oneboxer::AndroidAppStoreOnebox.new("https://play.google.com/store/apps/details?id=com.moosoft.parrot")
FakeWeb.register_uri(:get, @o.translate_url, :response => fixture_file('oneboxer/android.response'))
end
it "generates the expected onebox for Android App Store" do
@o.onebox.should == expected_android_app_store_result
end
private
def expected_android_app_store_result
<<EXPECTED
<div class='onebox-result'>
<div class='source'>
<div class='info'>
<a href='https://play.google.com/store/apps/details?id=com.moosoft.parrot' target="_blank">
<img class='favicon' src="/assets/favicons/google_play.png"> google.com
</a>
</div>
</div>
<div class='onebox-result-body'>
<img src="https://lh5.ggpht.com/wrYYVu74XNUu2WHk0aSZEqgdCDCNti9Fl0_dJnhgR6jY04ajQgVg5ABMatfcTDsB810=w124" class="thumbnail">
<h3><a href="https://play.google.com/store/apps/details?id=com.moosoft.parrot" target="_blank">Talking Parrot</a></h3>
Listen to the parrot repeat what you say. A Fun application for all ages. Upgrade to Talking Parrot Pro to save sounds, set them as your ringtone and control recording.
Press the MENU button to access the settings where you can change the record time and repeat count.
This app uses anonymous usage stats to understand and improve performance.
Comments and feedback welcome.
</div>
<div class='clearfix'></div>
</div>
EXPECTED
end
end

View File

@ -0,0 +1,38 @@
# encoding: utf-8
require 'spec_helper'
require 'oneboxer'
require 'oneboxer/apple_app_onebox'
describe Oneboxer::AppleAppOnebox do
before(:each) do
@o = Oneboxer::AppleAppOnebox.new("https://itunes.apple.com/us/app/minecraft-pocket-edition-lite/id479651754")
FakeWeb.register_uri(:get, @o.translate_url, :response => fixture_file('oneboxer/apple.response'))
end
it "generates the expected onebox for Apple app" do
@o.onebox.should == expected_apple_app_result
end
private
def expected_apple_app_result
<<EXPECTED
<div class='onebox-result'>
<div class='source'>
<div class='info'>
<a href='https://itunes.apple.com/us/app/minecraft-pocket-edition-lite/id479651754' target="_blank">
<img class='favicon' src="/assets/favicons/apple.png"> apple.com
</a>
</div>
</div>
<div class='onebox-result-body'>
<img src="http://a5.mzstatic.com/us/r1000/087/Purple/99/2f/dd/mzl.erzwvjsi.175x175-75.jpg" class="thumbnail">
<h3><a href="https://itunes.apple.com/us/app/minecraft-pocket-edition-lite/id479651754" target="_blank">Minecraft Pocket Edition Lite</a></h3>
Imagine it, build it. Create worlds on the go with Minecraft - Pocket EditionThis is the Lite version of Minecraft - Pocket Edition. Minecraft - Pocket Edition allows you to build on the go. Use blocks to create masterpieces as you travel, hangout with friends, sit at the park, the possibilities are endless. Move beyond the limits of your computer and play Minecraft everywhere you go.Limitations of the Lite version* The world is not saved between sessions* Multiplayer worlds can not be copied to
</div>
<div class='clearfix'></div>
</div>
EXPECTED
end
end

View File

@ -0,0 +1,21 @@
# encoding: utf-8
require 'spec_helper'
require 'oneboxer'
require 'oneboxer/flickr_onebox'
describe Oneboxer::FlickrOnebox do
before(:each) do
@o = Oneboxer::FlickrOnebox.new("http://www.flickr.com/photos/jaimeiniesta/3303881265")
FakeWeb.register_uri(:get, @o.translate_url, :response => fixture_file('oneboxer/flickr.response'))
end
it "generates the expected onebox for Flickr" do
@o.onebox.should == expected_flickr_result
end
private
def expected_flickr_result
"<a href='http://www.flickr.com/photos/jaimeiniesta/3303881265' target='_blank'><img src='http://farm4.staticflickr.com/3419/3303881265_c6924748e8_z.jpg' alt=''></a>"
end
end

View File

@ -0,0 +1,39 @@
# encoding: utf-8
require 'spec_helper'
require 'oneboxer'
require 'oneboxer/wikipedia_onebox'
describe Oneboxer::WikipediaOnebox do
before(:each) do
@o = Oneboxer::WikipediaOnebox.new("http://en.wikipedia.org/wiki/Ruby")
FakeWeb.register_uri(:get, @o.translate_url, :response => fixture_file('oneboxer/wikipedia.response'))
FakeWeb.register_uri(:get, 'http://en.m.wikipedia.org/wiki/Ruby', :response => fixture_file('oneboxer/wikipedia_redirected.response'))
end
it "generates the expected onebox for Wikipedia" do
@o.onebox.should == expected_wikipedia_result
end
private
def expected_wikipedia_result
<<EXPECTED
<div class='onebox-result'>
<div class='source'>
<div class='info'>
<a href='http://en.wikipedia.org/wiki/Ruby' target="_blank">
<img class='favicon' src="/assets/favicons/wikipedia.png"> wikipedia.org
</a>
</div>
</div>
<div class='onebox-result-body'>
<img src="http://upload.wikimedia.org/wikipedia/commons/thumb/8/80/Ruby_-_Winza%2C_Tanzania.jpg/220px-Ruby_-_Winza%2C_Tanzania.jpg" class="thumbnail">
<h3><a href="http://en.wikipedia.org/wiki/Ruby" target="_blank">Ruby</a></h3>
A ruby is a pink to blood-red colored gemstone, a variety of the mineral corundum (aluminium oxide). The red color is caused mainly by the presence of the element chromium. Its name comes from ruber, Latin for red. Other varieties of gem-quality corundum are called sapphires. The ruby is considered one of the four precious stones, together with the sapphire, the emerald, and the diamond. Prices of rubies are primarily determined by color. The brightest and most valuable "red" called pigeon blood-...
</div>
<div class='clearfix'></div>
</div>
EXPECTED
end
end

View File

@ -145,16 +145,16 @@ describe Oneboxer do
it 'yields each url and element when given a string' do it 'yields each url and element when given a string' do
result = Oneboxer.each_onebox_link(@html) do |url, element| result = Oneboxer.each_onebox_link(@html) do |url, element|
element.is_a?(Hpricot::Elem).should be_true element.is_a?(Nokogiri::XML::Element).should be_true
url.should == 'http://discourse.org' url.should == 'http://discourse.org'
end end
result.kind_of?(Hpricot::Doc).should be_true result.kind_of?(Nokogiri::HTML::Document).should be_true
end end
it 'yields each url and element when given a doc' do it 'yields each url and element when given a doc' do
doc = Hpricot(@html) doc = Nokogiri::HTML(@html)
Oneboxer.each_onebox_link(doc) do |url, element| Oneboxer.each_onebox_link(doc) do |url, element|
element.is_a?(Hpricot::Elem).should be_true element.is_a?(Nokogiri::XML::Element).should be_true
url.should == 'http://discourse.org' url.should == 'http://discourse.org'
end end
end end

818
spec/fixtures/oneboxer/amazon.response vendored Normal file
View File

@ -0,0 +1,818 @@
HTTP/1.1 200 OK
Date: Wed, 13 Feb 2013 09:47:01 GMT
Server: Server
x-amz-id-1: 0WP9Y459PHTN10MNJVR2
p3p: policyref="http://www.amazon.com/w3c/p3p.xml",CP="CAO DSP LAW CUR ADM IVAo IVDo CONo OTPo OUR DELi PUBi OTRi BUS PHY ONL UNI PUR FIN COM NAV INT DEM CNT STA HEA PRE LOC GOV OTC "
x-frame-options: SAMEORIGIN
x-amz-id-2: 0rIBgfbZSgwp0OgDU7U4QRx4GkZYUfpT1KWBFnMhwQFtpJT04o1NQEg3vs45N9OwaUbXxndyiZk=
Vary: Accept-Encoding,User-Agent
Cneonction: close
Content-Type: text/html; charset=UTF-8
Set-cookie: x-wl-uid=17QmuFayq7DO9CJ7Wqf46nzJaoa3gK4r9pTrw4rwtsHREAL7I+xpYhSUBfwzTTZR09yg01TKKL04=; path=/; domain=.amazon.com; expires=Tue, 01-Jan-2036 08:00:01 GMT
Set-cookie: session-id-time=2082787201l; path=/; domain=.amazon.com; expires=Tue, 01-Jan-2036 08:00:01 GMT
Set-cookie: session-id=176-4101438-5479234; path=/; domain=.amazon.com; expires=Tue, 01-Jan-2036 08:00:01 GMT
Transfer-Encoding: chunked
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript">var ue_t0=ue_t0||+new Date();</script>
<script type='text/javascript'>
var ue_csm = window;
ue_csm.ue_hob=ue_csm.ue_hob||+new Date();(function(a){a.ue_err={ec:0,pec:0,ts:0,erl:[],mxe:50,startTimer:function(){a.ue_err.ts++;setInterval(function(){a.ue&&(a.ue_err.pec<a.ue_err.ec)&&a.uex("at");a.ue_err.pec=a.ue_err.ec},10000)}};a.ueLogError=(function(){function b(c,e,d){if(a.ue_err.ec>a.ue_err.mxe){return}a.ue_err.ec++;a.ue.log({m:c,f:e,l:d,s:""},"jserr");return false}window.onerror=b;return function(c){if(a.ue_err.ec>a.ue_err.mxe){return}a.ue_err.ec++;a.ue_err.erl.push(c)}})()})(ue_csm);ue_csm.ue_hoe=+new Date();
var ue_id='0WP9Y459PHTN10MNJVR2',
ue_sid='176-4101438-5479234',
ue_mid='ATVPDKIKX0DER',
ue_sn='www.amazon.com',
ue_url='/gp/aw/d/0596516177/uedata/nvp/unsticky/176-4101438-5479234/NoPageType/ntpoffrw',
ue_furl='fls-na.amazon.com',
ue_pr=0,
ue_navtiming=1,
ue_tofc=1,
ue_log_idx=0,
ue_tsinc=0,
ue_fcsn=1,
ue_pageviz=0;
if (!window.ue_csm) {var ue_csm = window;}
ue_csm.ue_hob=ue_csm.ue_hob||+new Date();(function(f,a){f.ueinit=(f.ueinit||0)+1;f.ue={t0:a.aPageStart||f.ue_t0,id:f.ue_id,url:f.ue_url,a:"",b:"",h:{},r:{ld:0,oe:0,ul:0},s:1,t:{},sc:{},iel:[],ielf:[],fc_idx:{},viz:[],v:26};f.ue.tagC=function(){var h=[];return function(i){if(i){h.push(i)}return h.slice(0)}};f.ue.tag=f.ue.tagC();f.ue.ifr=((a.top!==a.self)||(a.frameElement))?1:0;function c(j,m,o,l){var n=l||(new Date()).getTime();var h=!m&&typeof o!="undefined";if(h){return}if(j){var k=m?e("t",m)||e("t",m,{}):f.ue.t;k[j]=n;for(var i in o){e(i,m,o[i])}}return n}function e(i,j,k){var l,h;if(i){l=h=f.ue;if(j&&j!=l.id){h=l.sc[j];if(!h){h={};k?(l.sc[j]=h):h}}l=k?(h[i]=k):h[i]}return l}function d(l,m,k,i,h){var j="on"+k;var n=m[j];if(typeof(n)=="function"){if(l){f.ue.h[l]=n}}else{n=function(){}}m[j]=h?function(o){i(o);n(o)}:function(o){n(o);i(o)};m[j].isUeh=1}function g(o,k,n){function j(L,J){var H=[L],C=0,I={};if(J){H.push("m=1");I[J]=1}else{I=f.ue.sc}var A;for(var B in I){var D=e("wb",B),G=e("t",B)||{},F=e("t0",B)||f.ue.t0;if(J||D==2){var K=D?C++:"";H.push("sc"+K+"="+B);for(var E in G){if(E.length<=3&&G[E]){H.push(E+K+"="+(G[E]-F))}}H.push("t"+K+"="+G[o]);if(e("ctb",B)||e("wb",B)){A=1}}}if(!l&&A){H.push("ctb=1")}return H.join("&")}function r(C,B,E,A){if(C==""){return}var D=new Image();if(f.ue.b){D.onload=function(){if(f.ue.b==""){return}var G=f.ue.b;f.ue.b="";r(G,B,E,1)}}var F=!f.ue_tofc||(f.ue_tofc==1&&!A)||!f.ue.log||!window.amznJQ||(!A&&!E);if(F){f.ue.iel.push(D);D.src=C}if(f.ue_tofc&&f.ue.log&&(E||A)){f.ue.log(C,"uedata",{n:1});f.ue.ielf.push(C)}if(f.ue_err&&!f.ue_err.ts){f.ue_err.startTimer()}}function x(A){if(!ue.collected){var C=A.timing;if(C){f.ue.t.na_=C.navigationStart;f.ue.t.ul_=C.unloadEventStart;f.ue.t._ul=C.unloadEventEnd;f.ue.t.rd_=C.redirectStart;f.ue.t._rd=C.redirectEnd;f.ue.t.fe_=C.fetchStart;f.ue.t.lk_=C.domainLookupStart;f.ue.t._lk=C.domainLookupEnd;f.ue.t.co_=C.connectStart;f.ue.t._co=C.connectEnd;f.ue.t.sc_=C.secureConnectionStart;f.ue.t.rq_=C.requestStart;f.ue.t.rs_=C.responseStart;f.ue.t._rs=C.responseEnd;f.ue.t.dl_=C.domLoading;f.ue.t.di_=C.domInteractive;f.ue.t.de_=C.domContentLoadedEventStart;f.ue.t._de=C.domContentLoadedEventEnd;f.ue.t._dc=C.domComplete;f.ue.t.ld_=C.loadEventStart;f.ue.t._ld=C.loadEventEnd}var B=A.navigation;if(B){f.ue.t.ty=B.type+f.ue.t0;f.ue.t.rc=B.redirectCount+f.ue.t0;if(f.ue.tag){f.ue.tag(B.redirectCount?"redirect":"nonredirect")}}f.ue.collected=1}}var z=!k&&typeof n!="undefined";if(z){return}for(var h in n){e(h,k,n[h])}c("pc",k,n);var t=e("id",k)||f.ue.id;var m=f.ue.url+"?"+o+"&v="+f.ue.v+"&id="+t;var l=e("ctb",k)||e("wb",k);if(l){m+="&ctb="+l}if(f.ueinit>1){m+="&ic="+f.ueinit}var w=a.performance||a.webkitPerformance;var u=f.ue.bfini;if(u&&u>1){m+="&bft="+(u-1)}else{if(w&&w.navigation&&w.navigation.type==2){m+="&bft=1"}}if(f.ue._fi&&o=="at"&&(!k||k==t)){m+=f.ue._fi()}var i;if((o=="ld"||o=="ul")&&(!k||k==t)){if(o=="ld"){if(a.onbeforeunload&&a.onbeforeunload.isUeh){a.onbeforeunload=null}if(document.ue_backdetect&&document.ue_backdetect.ue_back){document.ue_backdetect.ue_back.value++}if(f._uess){i=f._uess()}if(f.ue_navtiming&&w&&w.timing){e("ctb",t,"1");if(f.ue_navtiming==1){f.ue.t.tc=w.timing.navigationStart}}}if(w){x(w)}if(f.ue_hob&&f.ue_hoe){f.ue.t.hob=f.ue_hob;f.ue.t.hoe=f.ue_hoe}if(f.ue.ifr){m+="&ifr=1"}}c(o,k,n);var s=(o=="ld"&&k&&e("wb",k));if(s){e("wb",k,2)}var v=1;for(var q in f.ue.sc){if(e("wb",q)==1){v=0;break}}if(s){if(f.ue.s!=0||!v){return}m=j(m,null)}else{if(v){var y=j(m,null);if(y!=m){f.ue.b=y}}if(i){m+=i}m=j(m,k||f.ue.id)}if(f.ue.b||s){for(var q in f.ue.sc){if(e("wb",q)==2){delete f.ue.sc[q]}}}var p=0;if(!s){f.ue.s=0;if(f.ue_err&&f.ue_err.ec>0){m+="&ec="+f.ue_err.ec}p=e("ctb",k);e("t",k,{})}if(f.ue_tofc&&f.ue.tag&&p){f.ue.tag("ue_tofc")}if(!window.amznJQ&&f.ue.tag){f.ue.tag("noAmznJQ")}if(m&&f.ue.tag&&f.ue.tag().length>0){m+="&csmtags="+f.ue.tag().join("|");f.ue.tag=f.ue.tagC()}if(m&&f.ue_pageviz&&f.ue.viz.length>0){m+="&viz="+f.ue.viz.join("|");f.ue.viz=[]}f.ue.a=m;r(m,o,p,s)}function b(){var j=f.ue.r;function i(l){return function(){if(!j[l]){j[l]=1;g(l)}}}f.onLd=i("ld");f.onLdEnd=i("ld");var h={beforeunload:i("ul"),stop:function(){g("os")}};for(var k in h){d(0,window,k,h[k])}if(f.ue_pageviz){ue_viz&&ue_viz()}if(a.addEventListener){a.addEventListener("load",f.onLd,false)}else{if(a.attachEvent){a.attachEvent("onload",f.onLd)}}f.ue._uep=function(){new Image().src=(f.ue_md?f.ue_md:"http://uedata.amazon.com/uedata/?tp=")+(+new Date)};if(f.ue_pr&&(f.ue_pr==2||f.ue_pr==4)){f.ue._uep()}if(f.queue){f.queue.replay=function(){while((nextArr=f.queue.remove("ue"))){nextArr[0].apply(this,nextArr.slice(1))}};f.queue.replay()}c("ue")}ue.reset=function(i,h){if(!i){return}f.ue_cel&&f.ue_cel.reset();f.ue.t0=+new Date();f.ue.rid=i;f.ue.id=i;f.ue.fc_idx={};f.ue.viz=[]};f.uei=b;f.ueh=d;f.ues=e;f.uet=c;f.uex=g;b()})(ue_csm,window);ue_csm.ue_hoe=+new Date();
ue_csm.ue_hob=ue_csm.ue_hob||+new Date();(function(b){var a=b.ue;a.rid=b.ue_id;a.sid=b.ue_sid;a.mid=b.ue_mid;a.furl=b.ue_furl;a.sn=b.ue_sn;a.lr=[];a.log=function(e,d,c){if(a.lr.length==500){return}a.lr.push(["l",e,d,c,a.d(),a.rid])};a.d=function(c){return +new Date-(c?0:a.t0)}})(ue_csm);ue_csm.ue_hoe=+new Date();
</script>
<link rel="stylesheet" href="http://z-ecx.images-amazon.com/images/G/01/AUIClients/AnywhereDetailCSS_v1.3097025c4c1c0b68e600509002cf76416ef3b6e8.min._V375565103_.css"/><meta charset="utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge,chrome=1">
<meta name="viewport" content="width=device-width,user-scalable=no,initial-scale=1.0,maximum-scale=1.0">
<title>The Ruby Programming Language:Amazon:Books</title>
<meta name="keywords" content="The Ruby Programming Language,ARRAY(0xafb993c0),O'Reilly Media,Computer Books: Languages,Object-oriented programming (Computer science),Computers - Languages / Programming,Object-oriented pro,Ruby (Computer program language),Computers,Computers / Programming / General,Computers / Programming Languages / General,Computers / Software Development &amp; Engineering / General,Computers : Software Development &amp; Engineering - General,Software Development &amp; Engineering - General,COM051000,COM051010,Programming &amp; scripting languages: general,Programming languages,Programming Languages - General,Computing: Professional &amp; Programming,Computers &amp; Internet - General,Computer Programming Languages" /><meta name="description" content="Amazon:The Ruby Programming Language" /><link href="http://g-ecx.images-amazon.com/images/G/01/anywhere/a_smile_57x57._V156379828_.png" rel="apple-touch-icon" />
<style>
#main-image-compute-height {
margin-top: 131.386861313869%;
}
@media (max-width:390px) {
#main-image-container {
max-width: 137px;
}
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY180_.jpg);
}
}
@media (max-width:390px) and (-webkit-min-device-pixel-ratio:1.5) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY270_.jpg);
}
}
@media (max-width:390px) and (-webkit-min-device-pixel-ratio:2) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY360_.jpg);
}
}
@media (max-width:390px) and (-webkit-min-device-pixel-ratio:3) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY540_.jpg);
}
}
@media (min-width:391px) and (max-width:500px) {
#main-image-container {
max-width: 152px;
}
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY200_.jpg);
}
}
@media (min-width:391px) and (max-width:500px) and (-webkit-min-device-pixel-ratio:1.5) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY300_.jpg);
}
}
@media (min-width:391px) and (max-width:500px) and (-webkit-min-device-pixel-ratio:2) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY400_.jpg);
}
}
@media (min-width:391px) and (max-width:500px) and (-webkit-min-device-pixel-ratio:3) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY600_.jpg);
}
}
@media (min-width: 501px) and (max-width: 767px) {
#main-image-container {
max-width: 229px;
}
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY300_.jpg);
}
}
@media (min-width: 501px) and (max-width: 767px) and (-webkit-min-device-pixel-ratio:1.5) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY450_.jpg);
}
}
@media (min-width: 501px) and (max-width: 767px) and (-webkit-min-device-pixel-ratio:2) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY600_.jpg);
}
}
@media (min-width: 501px) and (max-width: 767px) and (-webkit-min-device-pixel-ratio:3) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SY900_.jpg);
}
}
@media (min-width:768px) {
#main-image-container {
max-width: 368px;
}
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SX368_.jpg);
}
}
@media (min-width:768px) and (-webkit-min-device-pixel-ratio:1.5) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SX552_.jpg);
}
}
@media (min-width:768px) and (-webkit-min-device-pixel-ratio:2) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SX736_.jpg);
}
}
@media (min-width:768px) and (-webkit-min-device-pixel-ratio:3) {
.main-image {
background-image: url(http://ecx.images-amazon.com/images/I/716dULgyHNL._SX1104_.jpg);
}
}
</style>
<script type="text/javascript">
if (window.amznJQ) {
amznJQ.addLogical('csm-base', [ "http://z-ecx.images-amazon.com/images/G/01/browser-scripts/csm-base/csm-base-min-170757555._V1_.js" ]);
amznJQ.available('csm-base', function() {});
}
</script>
</head>
<body>
<div class="a-container">
<div style='display:none' class='main-image'></div><div id="a-navbar" class="a-section a-row">
<div id="nav-inner" class="a-span12">
<div id="navbar-icons">
<a href="/gp/aw/ref=aw_he_gw/176-4101438-5479234" title="Amazon.com"><span class="s_logo" title="Amazon.com" id="logo"></span></a><a href="/gp/aw/c/ref=aw_he_c/176-4101438-5479234" title="Shopping Cart"><i id="navbar-icon-cart" class="navbar-icon cart"></i></a>
</div>
<div id="navbar-breadcrumb">
</div>
</div>
</div>
<div id="a-content">
<div id="udp">
<div class="a-row">
<h1>The Ruby Programming Language (Paperback)</h1>
<span id='by-line' class='a-text a-nowrap a-span6'>David Flanagan, Yukihiro Matsumoto</span><div id='rating-stars' class='a-span6 a-right a-row-last'>
<span class="review-stars a-right a-nowrap">
<a href="/gp/aw/cr/0596516177/ref=mw_dp_cr/176-4101438-5479234"><span class="s_ratingStar_50" title="5.0 stars"></span></a>
<span class="review-count a-color-secondary a-size-normal a-text-normal">62</span>
</span>
</div>
<hr/>
</div>
<div class="a-row">
<script>
var atfMarkers = 0;
</script>
<div id="image-block" class="a-section a-center">
<style>
#main-image-container {
display: inline-block;
position: relative;
width: 100%;
vertical-align: top;
}
#main-image {
position: absolute;
top: 0;
bottom: 0;
left: 0;
right: 0;
background-position: center;
background-size: 100%;
background-repeat: no-repeat;
}
</style>
<a href="/gp/aw/d/0596516177/ref=mw_dp_img/176-4101438-5479234?is=l" class='aw-no-tap-highlight'>
<div id='main-image-container'>
<div id='main-image-compute-height'></div>
<div id='main-image' class='main-image'><img src="http://ecx.images-amazon.com/images/I/716dULgyHNL._SY180_.jpg" width="100%" onload="if (typeof uet == 'function') { uet('af'); };this.onload=null;" id="previous-image" height="100%" border="0" /></div>
</div>
<div>Larger image</div>
</a>
</div>
<hr id="image-block-divider" />
<script>
var mainImageCopy;
(function () {
mainImageCopy = new Image();
mainImageCopy.onabort = mainImageCopy.onerror = mainImageCopy.onload = function () {
var pi = document.getElementById('previous-image');
if (pi.onload) {
if (typeof uet == 'function') { uet('af'); };
pi.onload = null;
}
pi.style.display = 'none';
};
var cs = document.defaultView.getComputedStyle(
document.getElementById('main-image'),
null
);
var src = cs['background-image'] || cs['backgroundImage'];
if (src) mainImageCopy.src = src.substr(4, src.length - 5);
})();
</script>
<div id="price-block" class="a-section a-row-last">
<table id="prices" class="a-nostyle">
<tr>
<td class="a-color-secondary a-right aw-table-label">List Price:</td>
<td id="list-price" class="a-color-secondary a-text-strike aw-table-data">$39.99</td>
</tr>
<tr>
<td class="a-color-secondary a-right aw-table-label">Price:</td>
<td class="a-color-price a-size-medium aw-table-data"><strong id="price">
$23.99
<span class="itemBadge">
</span>
</strong></td>
</tr>
<tr>
<td class="a-color-secondary a-right aw-table-label">You Save:</td>
<td id="you-save" class="a-color-secondary aw-table-data">$16.00 (40%)</td>
</tr>
</table><p id="scarcity" class="a-size-medium a-color-available">
<strong>In Stock</strong>
</p><div id="ships-from">
<p>Ships from and sold by Amazon.com</p><p class="addendum a-size-small a-color-secondary"></p>
Gift-wrap available.
</div>
<p><a href="/gp/aw/help/id=sss/ref=aw_d_sss_books/176-4101438-5479234">FREE Super Saver Shipping</a> on orders over $25.</p><p>
Want it delivered by Thursday, Feb 14?
Order within <span class=a-color-available>14hr 42min</span>, and choose One-Day Shipping at checkout.
</p>
</div>
<div id="buy-box" class="a-section a-row-last a-box-primary a-span12">
<div class="a-content">
<div class="a-row">
<form method="post"
id="addToCart"
action="/gp/aw/c/ref=mw_dp_buy_crt/176-4101438-5479234"
class="a-nostyle button-form">
<input type="hidden" name="a" value="0596516177" /><input type="hidden" name="colid" value="" /><input type="hidden" name="coliid" value="" /><input type="hidden" name="dl" value="" /><input type="hidden" name="o" value="add" /><input type="hidden" name="oid" value="tPDk4BwNGb6CBcKM1HokEMSRYQ6ZWPLKQFxsXn4lWM4JFBfkFxRmL2h7fd%2F%2F2MnsuI%2BeAkREvTXaxDDDIqXNFGB2HQk7iZzP5AStDPTpze8%3D" /><input type="hidden" name="verificationSessionID" value="176-4101438-5479234" />
<button type='submit'
name="cartSubmit"
id="add-to-cart-button"
class="buy-button a-button a-button-primary">
<span class="a-button-gradient">
<span class="a-button-text">Add to Cart</span>
</span>
</button>
</form>
<form method="get" id="addToWishlist" class="a-nostyle button-form" action="/gp/aw/l.html/ref=mw_dp_buy_wl/176-4101438-5479234"><input type="hidden" name="appAction" value="add" /><input type="hidden" name="appActionToken" value="414451b43a6f5fccd7b596d8ad0442a896d274443ef01ffc744063c0195bdb0d" /><input type="hidden" name="csrfRnd" value="0.609460785235555" /><input type="hidden" name="csrfTs" value="1360748821" /><input type="hidden" name="a" value="0596516177" />
<button type='submit' id="add-to-wishlist-button" name="listSubmit" class="buy-button a-button a-button-secondary">
<span class="a-button-gradient">
<span class="a-button-text">Add to Wish&nbsp;List</span>
</span>
</button>
</form>
</div>
</div>
</div>
</div>
<hr />
<div class="aw-campaigns"></div><div class="aw-campaigns"></div><div class="a-row">
<div id="new-used-offers" class="a-section a-span12">
<a href="/gp/aw/ol/0596516177/ref=mw_dp_olp/176-4101438-5479234" class="a-touch">
<div class="a-content">
<h2>
New &amp; Used Offers
<span class="a-color-secondary a-size-normal a-text-normal">
(71)
</span>
</h2>
<span class="a-color-secondary">
From <span class="a-color-price">$18.00</span>
</span>
</div>
<i class="a-icon a-icon-arrow a-touch-navigation"></i>
</a>
</div>
<hr/>
<div id="description-and-details" class="a-span12">
<a href="/gp/aw/d/0596516177/ref=mw_dp_mpd/176-4101438-5479234?pd=1" class="a-touch">
<div class="a-content">
<h2>
Description &amp; Details
</h2>
<p id='description-and-details-content'>
The Ruby Programming Language is the authoritative guide to Ruby&nbsp;...
</p>
<i class="a-icon a-icon-arrow a-touch-navigation"></i>
</div>
</a>
</div>
<hr/>
<div class="a-row">
<div id='purchase-similarities' class="a-section a-span12">
<h2>Customers who bought this also bought</h2>
<style type="text/css">
.shovelerCenterInfo {
text-align: center;
}
.starsPlaceholder {
width: 90px;
height: 17px;
}
div.shovelerByLine {
color: #686868;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.overflowLeftRightContainer { overflow: hidden }
.shovelerContainer {
text-align: center;
white-space: nowrap;
}
.imageContainerBox {
display: inline-block;
height: 100%;
position: relative;
}
.imageContainer {
left: 0;
width: 100%;
display: inline-block;
text-align: center;
position: absolute;
bottom: 0px;
margin-bottom: 0px;
}
div.shovelerCenterInfo a.shovelerItemTitle {
display: inline;
}
img.shovelerImage { height: 100%; min-width: 1px; }
.shovelerContainer a {
-webkit-tap-highlight-color: rgba(0,0,0,0);
tap-highlight-color: rgba(0,0,0,0);
}
#uniPurchaseSims_overflowLeftRight {
margin-left: -362.5px;
margin-right: -362.5px;
}
#uniPurchaseSims_shovelerContainer {
height: 125px;
}
.uniPurchaseSims_imageContainerBox {
width: 104px;
}
.uniPurchaseSims_imageContainer {
height: 95px;
}
</style>
<div class='overflowLeftRightContainer'>
<div id='uniPurchaseSims_overflowLeftRight' >
<div id='uniPurchaseSims_shovelerContainer' class='shovelerContainer'>
<span class='imageContainerBox uniPurchaseSims_imageContainerBox'>
<span class="imageContainer uniPurchaseSims_imageContainer" id='uniPurchaseSims_imgContainer-1'>
<a id='uniPurchaseSims_imgLink-1'>
<img class='shovelerImage' id='uniPurchaseSims_img-1' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniPurchaseSims_imageContainerBox'>
<span class="imageContainer uniPurchaseSims_imageContainer" id='uniPurchaseSims_imgContainer0'>
<a id='uniPurchaseSims_imgLink0'>
<img class='shovelerImage' id='uniPurchaseSims_img0' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniPurchaseSims_imageContainerBox'>
<span class="imageContainer uniPurchaseSims_imageContainer" id='uniPurchaseSims_imgContainer1'>
<a id='uniPurchaseSims_imgLink1'>
<img class='shovelerImage' id='uniPurchaseSims_img1' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniPurchaseSims_imageContainerBox'>
<span class="imageContainer uniPurchaseSims_imageContainer" id='uniPurchaseSims_imgContainer2'>
<a id='uniPurchaseSims_imgLink2'>
<img class='shovelerImage' id='uniPurchaseSims_img2' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniPurchaseSims_imageContainerBox'>
<span class="imageContainer uniPurchaseSims_imageContainer" id='uniPurchaseSims_imgContainer3'>
<a id='uniPurchaseSims_imgLink3'>
<img class='shovelerImage' id='uniPurchaseSims_img3' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniPurchaseSims_imageContainerBox'>
<span class="imageContainer uniPurchaseSims_imageContainer" id='uniPurchaseSims_imgContainer4'>
<a id='uniPurchaseSims_imgLink4'>
<img class='shovelerImage' id='uniPurchaseSims_img4' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniPurchaseSims_imageContainerBox'>
<span class="imageContainer uniPurchaseSims_imageContainer" id='uniPurchaseSims_imgContainer5'>
<a id='uniPurchaseSims_imgLink5'>
<img class='shovelerImage' id='uniPurchaseSims_img5' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
</div>
</div>
</div>
<div class='shov-ratings-bucket' style='display:none'>
<div id='uniPurchaseSims_rating-stars-4-1-0'>
<span class="s_ratingStar_45" title="4.5 stars"></span>
</div>
<div id='uniPurchaseSims_rating-stars-3-1-1'>
<span class="s_ratingStar_35" title="3.5 stars"></span>
</div>
<div id='uniPurchaseSims_rating-stars-5-0-0'>
<span class="s_ratingStar_50" title="5.0 stars"></span>
</div>
</div>
<div class='shovelerCenterInfo'>
<a class='shovelerItemTitle' id='uniPurchaseSims_title'><br /><br /></a><br />
<div class="shovelerByLine" id='uniPurchaseSims_byline'><br /></div>
<span id='uniPurchaseSims_listprice-container'>
<span id='uniPurchaseSims_listprice' class="a-color-secondary a-text-strike"></span>
&nbsp;&nbsp;
</span>
<span id='uniPurchaseSims_ourprice' class="a-color-price"></span>
<span id='uniPurchaseSims_ppu-container'>&nbsp;&nbsp;<span id='uniPurchaseSims_ppu' class="grey"></span></span>
<br/>
<span id='uniPurchaseSims_rating'><span class="starsPlaceholder"></span></span>
</div>
<script type="text/javascript">
(function() {
var div = document.getElementById('uniPurchaseSims_shovelerContainer');
var intervalID;
intervalID = setInterval(function () {
var top = window.pageYOffset || document.documentElement.scrollTop || 0;
var bottom = top + window.innerHeight;
var divY = div.offsetTop;
if (bottom >= divY ) {
clearInterval(intervalID);
if (!window.addShoveler) window.addShoveler = function(cfg) {
if (!window.smartShovelers) window.smartShovelers = [];
window.smartShovelers.push(cfg);
};
window.addShoveler({
items: [{ourprice: '$27.01', byline: 'Michael Hartl', listprice: 0, height: 125, rating: '4-1-0', image: 'http://ecx.images-amazon.com/images/I/51A4xwwFy2L._SL500_SY125_.jpg', detail: '/gp/aw/d/0321832051/ref=mw_dp_sim_ps1/176-4101438-5479234?pi=SL500_SY125', numReviews: 32, ppu: '', title: 'Ruby on Rails<br />Tutorial: Learn ...'}, {ourprice: '$30.61', byline: 'Russ Olsen', listprice: 0, height: 125, rating: '5-0-0', image: 'http://ecx.images-amazon.com/images/I/41IDuwJXFCL._SL500_SY125_.jpg', detail: '/gp/aw/d/0321584104/ref=mw_dp_sim_ps2/176-4101438-5479234?pi=SL500_SY125', numReviews: 26, ppu: '', title: 'Eloquent Ruby<br />(Addison-Wesley ...'}, {ourprice: '$28.41', byline: 'Andrew Hunt, Dave Thomas, Chad Fowler', listprice: 0, height: 125, rating: '4-1-0', image: 'http://ecx.images-amazon.com/images/I/51vFypbVAPL._SL500_SY125_.jpg', detail: '/gp/aw/d/1934356085/ref=mw_dp_sim_ps3/176-4101438-5479234?pi=SL500_SY125', numReviews: 19, ppu: '', title: 'Programming Ruby<br />1.9: The Pragmat...'}, {ourprice: '$24.63', byline: 'Dave Thomas, David Heinemeier Hansson, Sam Ruby', listprice: 0, height: 125, rating: '3-1-1', image: 'http://ecx.images-amazon.com/images/I/51jd6GaEK0L._SL500_SY125_.jpg', detail: '/gp/aw/d/1934356549/ref=mw_dp_sim_ps4/176-4101438-5479234?pi=SL500_SY125', numReviews: 36, ppu: '', title: 'Agile Web<br />Development with...'}, {ourprice: '$31.49', byline: 'Leonard Richardson, Lucas Carlson', listprice: 0, height: 125, rating: '4-1-0', image: 'http://ecx.images-amazon.com/images/I/51wM2SmbR9L._SL500_SY125_.jpg', detail: '/gp/aw/d/0596523696/ref=mw_dp_sim_ps5/176-4101438-5479234?pi=SL500_SY125', numReviews: 29, ppu: '', title: 'Ruby Cookbook<br />(Cookbooks (O\'Re...'}],
maxDisplay: 5,
initialFocus: 2,
threshold: 104,
pixel: "http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif",
smallImageHeight: 95,
ns: "uniPurchaseSims_",
loopAround: false
});
}
}, 500);
})();
</script>
</div>
</div>
<hr/>
<div id="customer-reviews" class="a-section a-span12">
<a class="a-touch" href="/gp/aw/cr/0596516177/ref=mw_dp_cr/176-4101438-5479234">
<div class="a-content">
<div class="a-row">
<h2 class="a-left">Customer reviews</h2> <span class="a-nowrap"><span class="s_ratingStar_50" title="5.0 stars"></span> <span class="a-color-secondary a-size-normal a-text-normal">62</span></span>
</div>
<table id='reviews-histogram' cellspacing="0" cellpadding="0" class="a-nostyle">
<tr><td class="dpCRstarLabels">5 star:</td><td>
<div class="dpCRbarsOutline">
<div class="dpCRbars" style="width:87.1%">
<span class="emptySpanForMediaNet"></span>
</div>
</div>
</td><td class="dpCRnumberLabels" >54</td></tr>
<tr><td class="dpCRstarLabels">4 star:</td><td>
<div class="dpCRbarsOutline">
<div class="dpCRbars" style="width:11.3%">
<span class="emptySpanForMediaNet"></span>
</div>
</div>
</td><td class="dpCRnumberLabels" >7</td></tr>
<tr><td class="dpCRstarLabels">3 star:</td><td>
<div class="dpCRbarsOutline">
<span class="emptySpanForMediaNet"></span>
</div>
</td><td class="dpCRnumberLabels" style="color: #666666">0</td></tr>
<tr><td class="dpCRstarLabels">2 star:</td><td>
<div class="dpCRbarsOutline">
<div class="dpCRbars" style="width: 2.0%">
<span class="emptySpanForMediaNet"></span>
</div>
</div>
</td><td class="dpCRnumberLabels" >1</td></tr>
<tr><td class="dpCRstarLabels">1 star:</td><td>
<div class="dpCRbarsOutline">
<span class="emptySpanForMediaNet"></span>
</div>
</td><td class="dpCRnumberLabels" style="color: #666666">0</td></tr>
</table>
</div>
<i class="a-icon a-icon-arrow a-touch-navigation"></i>
</a>
</div>
<hr/>
</div><div class="aw-campaigns"></div><div class="aw-campaigns"></div><div class="a-row">
<div id='session-similarities' class="a-section a-span12">
<h2>Customers Also Viewed</h2>
<style type="text/css">
.shovelerCenterInfo {
text-align: center;
}
.starsPlaceholder {
width: 90px;
height: 17px;
}
div.shovelerByLine {
color: #686868;
overflow: hidden;
text-overflow: ellipsis;
white-space: nowrap;
}
.overflowLeftRightContainer { overflow: hidden }
.shovelerContainer {
text-align: center;
white-space: nowrap;
}
.imageContainerBox {
display: inline-block;
height: 100%;
position: relative;
}
.imageContainer {
left: 0;
width: 100%;
display: inline-block;
text-align: center;
position: absolute;
bottom: 0px;
margin-bottom: 0px;
}
div.shovelerCenterInfo a.shovelerItemTitle {
display: inline;
}
img.shovelerImage { height: 100%; min-width: 1px; }
.shovelerContainer a {
-webkit-tap-highlight-color: rgba(0,0,0,0);
tap-highlight-color: rgba(0,0,0,0);
}
#uniSessionSims_overflowLeftRight {
margin-left: -410px;
margin-right: -410px;
}
#uniSessionSims_shovelerContainer {
height: 125px;
}
.uniSessionSims_imageContainerBox {
width: 104px;
}
.uniSessionSims_imageContainer {
height: 95px;
}
</style>
<div class='overflowLeftRightContainer'>
<div id='uniSessionSims_overflowLeftRight' >
<div id='uniSessionSims_shovelerContainer' class='shovelerContainer'>
<span class='imageContainerBox uniSessionSims_imageContainerBox'>
<span class="imageContainer uniSessionSims_imageContainer" id='uniSessionSims_imgContainer-1'>
<a id='uniSessionSims_imgLink-1'>
<img class='shovelerImage' id='uniSessionSims_img-1' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniSessionSims_imageContainerBox'>
<span class="imageContainer uniSessionSims_imageContainer" id='uniSessionSims_imgContainer0'>
<a id='uniSessionSims_imgLink0'>
<img class='shovelerImage' id='uniSessionSims_img0' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniSessionSims_imageContainerBox'>
<span class="imageContainer uniSessionSims_imageContainer" id='uniSessionSims_imgContainer1'>
<a id='uniSessionSims_imgLink1'>
<img class='shovelerImage' id='uniSessionSims_img1' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniSessionSims_imageContainerBox'>
<span class="imageContainer uniSessionSims_imageContainer" id='uniSessionSims_imgContainer2'>
<a id='uniSessionSims_imgLink2'>
<img class='shovelerImage' id='uniSessionSims_img2' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniSessionSims_imageContainerBox'>
<span class="imageContainer uniSessionSims_imageContainer" id='uniSessionSims_imgContainer3'>
<a id='uniSessionSims_imgLink3'>
<img class='shovelerImage' id='uniSessionSims_img3' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniSessionSims_imageContainerBox'>
<span class="imageContainer uniSessionSims_imageContainer" id='uniSessionSims_imgContainer4'>
<a id='uniSessionSims_imgLink4'>
<img class='shovelerImage' id='uniSessionSims_img4' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
<span class='imageContainerBox uniSessionSims_imageContainerBox'>
<span class="imageContainer uniSessionSims_imageContainer" id='uniSessionSims_imgContainer5'>
<a id='uniSessionSims_imgLink5'>
<img class='shovelerImage' id='uniSessionSims_img5' src='http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif' />
</a>
</span>
</span>
</div>
</div>
</div>
<div class='shov-ratings-bucket' style='display:none'>
<div id='uniSessionSims_rating-stars-4-1-0'>
<span class="s_ratingStar_45" title="4.5 stars"></span>
</div>
<div id='uniSessionSims_rating-stars-4-0-1'>
<span class="s_ratingStar_40" title="4.0 stars"></span>
</div>
<div id='uniSessionSims_rating-stars-5-0-0'>
<span class="s_ratingStar_50" title="5.0 stars"></span>
</div>
</div>
<div class='shovelerCenterInfo'>
<a class='shovelerItemTitle' id='uniSessionSims_title'><br /><br /></a><br />
<div class="shovelerByLine" id='uniSessionSims_byline'><br /></div>
<span id='uniSessionSims_listprice-container'>
<span id='uniSessionSims_listprice' class="a-color-secondary a-text-strike"></span>
&nbsp;&nbsp;
</span>
<span id='uniSessionSims_ourprice' class="a-color-price"></span>
<span id='uniSessionSims_ppu-container'>&nbsp;&nbsp;<span id='uniSessionSims_ppu' class="grey"></span></span>
<br/>
<span id='uniSessionSims_rating'><span class="starsPlaceholder"></span></span>
</div>
<script type="text/javascript">
(function() {
var div = document.getElementById('uniSessionSims_shovelerContainer');
var intervalID;
intervalID = setInterval(function () {
var top = window.pageYOffset || document.documentElement.scrollTop || 0;
var bottom = top + window.innerHeight;
var divY = div.offsetTop;
if (bottom >= divY ) {
clearInterval(intervalID);
if (!window.addShoveler) window.addShoveler = function(cfg) {
if (!window.smartShovelers) window.smartShovelers = [];
window.smartShovelers.push(cfg);
};
window.addShoveler({
items: [{ourprice: '$28.41', byline: 'Andrew Hunt, Dave Thomas, Chad Fowler', listprice: 0, height: 125, rating: '4-1-0', image: 'http://ecx.images-amazon.com/images/I/51vFypbVAPL._SL500_SY125_.jpg', detail: '/gp/aw/d/1934356085/ref=mw_dp_sim_ss1/176-4101438-5479234?pi=SL500_SY125', numReviews: 19, ppu: '', title: 'Programming Ruby<br />1.9: The Pragmat...'}, {ourprice: '$27.01', byline: 'Michael Hartl', listprice: 0, height: 125, rating: '4-1-0', image: 'http://ecx.images-amazon.com/images/I/51A4xwwFy2L._SL500_SY125_.jpg', detail: '/gp/aw/d/0321832051/ref=mw_dp_sim_ss2/176-4101438-5479234?pi=SL500_SY125', numReviews: 32, ppu: '', title: 'Ruby on Rails<br />Tutorial: Learn ...'}, {ourprice: '$30.61', byline: 'Russ Olsen', listprice: 0, height: 125, rating: '5-0-0', image: 'http://ecx.images-amazon.com/images/I/41IDuwJXFCL._SL500_SY125_.jpg', detail: '/gp/aw/d/0321584104/ref=mw_dp_sim_ss3/176-4101438-5479234?pi=SL500_SY125', numReviews: 26, ppu: '', title: 'Eloquent Ruby<br />(Addison-Wesley ...'}, {ourprice: '$27.31', byline: 'David A. Black', listprice: 0, height: 125, rating: '4-1-0', image: 'http://ecx.images-amazon.com/images/I/41ehFO0XieL._SL500_SY125_.jpg', detail: '/gp/aw/d/1933988657/ref=mw_dp_sim_ss4/176-4101438-5479234?pi=SL500_SY125', numReviews: 28, ppu: '', title: 'The Well-Grounded<br />Rubyist'}, {ourprice: '$33.36', byline: 'Peter Cooper', listprice: 0, height: 125, rating: '4-0-1', image: 'http://ecx.images-amazon.com/images/I/512242IrWmL._SL500_SY125_.jpg', detail: '/gp/aw/d/1430223634/ref=mw_dp_sim_ss5/176-4101438-5479234?pi=SL500_SY125', numReviews: 11, ppu: '', title: 'Beginning Ruby:<br />From Novice to P...'}, {ourprice: '$22.16', byline: 'Peter Cooper', listprice: 0, height: 125, rating: '5-0-0', image: 'http://ecx.images-amazon.com/images/I/51dDyatSyRL._SL500_SY125_.jpg', detail: '/gp/aw/d/1590597664/ref=mw_dp_sim_ss6/176-4101438-5479234?pi=SL500_SY125', numReviews: 34, ppu: '', title: 'Beginning Ruby:<br />From Novice to P...'}],
maxDisplay: 5,
initialFocus: 2,
threshold: 104,
pixel: "http://g-ecx.images-amazon.com/images/G/01/x-locale/common/transparent-pixel._V386942464_.gif",
smallImageHeight: 95,
ns: "uniSessionSims_",
loopAround: false
});
}
}, 500);
})();
</script>
</div>
</div>
<hr/>
</div>
</div>
<div id="a-footer">
<div id='search-ac-init-data'
data-aliases='aps,stripbooks,popular,apparel,electronics,sporting,garden,videogames,toys-and-games,jewelry,digital-text,digital-music,watches,grocery,hpc,instant-video,baby-products,office-products,software,magazines,tools,automotive,misc,industrial,mi,pet-supplies,digital-music-track,digital-music-album,mobile,mobile-apps,movies-tv,music-artist,music-album,music-song,stripbooks-spanish,electronics-accessories,photo,audio-video,computers,furniture,kitchen,audiobooks,beauty,shoes,arts-crafts,appliances,gift-cards,pets,outdoor,lawngarden,collectibles,financial'
data-ime=''
data-mkt='1'
data-src='completion.amazon.com/search/complete'
></div>
<div id='dpSearchKeyword-data'
data-form='dpSearchForm'
></div>
<div class="a-row">
<h3 id='search-bar-title'>Search</h3>
<form id="dpSearchForm" class="a-row a-nostyle" action="/gp/aw/s/ref=is_box_books/176-4101438-5479234">
<input class="a-span9 a-button-line psearch"
type="text" name="k"
id="dpSearchKeyword"
autocomplete="off"
placeholder="Search Amazon.com"
/>
<button type="submit" class="a-span3 a-row-last a-button a-button-dark">
<span class="a-button-gradient">
<span class="a-button-text">Go</span>
</span>
</button>
</form>
</div><div class="aw-campaigns"></div><div class="a-row a-section">
<span class="a-span12">
<span class="a-right">
<span id='top-of-page-icon' class="s_arrowUp" ></span>
<a href="#top">
Top of page
</a>
</span>
</span>
</div><ul class="a-nostyle a-row a-section" id="bottom-nav-links">
<li><a class="a-touch " href="/gp/aw/176-4101438-5479234">
Home
</a></li>
<li><a class="a-touch footer-link-even " href="/gp/aw/c/176-4101438-5479234">
Cart
</a></li>
<li><a class="a-touch footer-link-third" href="/gp/aw/ls/176-4101438-5479234">
Wish List
</a></li>
<li><a class="a-touch footer-link-even " href="/gp/aw/ls/s/176-4101438-5479234">
Find a Wish List or Registry
</a></li>
<li><a class="a-touch " href="https://www.amazon.com/gp/aw/ya/176-4101438-5479234">
Your Account
</a></li>
<li><a class="a-touch footer-link-even footer-link-third" href="https://www.amazon.com/gp/subscribe-and-save/manage/176-4101438-5479234">
Your Subscribe & Save Items
</a></li>
<li><a class="a-touch " href="https://www.amazon.com/gp/aw/vsd.html/176-4101438-5479234">
1-Click Settings
</a></li>
<li><a class="a-touch footer-link-even " href="/gp/aw/help/id=help/176-4101438-5479234">
Help
</a></li>
<li><a class="a-touch footer-link-third" href="/gp/aw/rd.html/176-4101438-5479234?at=&force-full-site=1&lc=plm&ref_=aw_bottom_links&url=%2Fgp%2Fproduct%2F0596516177">
Amazon.com Full Site
</a></li>
</ul><div id='footer' class="a-center">
<p id='who-are-you'>
Already a customer? &nbsp; &nbsp;<a href="https://www.amazon.com/gp/flex/aw/so.html/176-4101438-5479234?action=sign-in&redirectTo=%2Fgp%2Faw%2Fsi.html%2F176-4101438-5479234%3Faction%3Dsign-in%26destinationURL%3D%252Fgp%252Faw%252Fd%252F0596516177%26isHttp%3D1%26packedQuery%3D*entries*%257C0%257C*Version*%257C1">Sign In</a>
</p>
<p id='show-history'><a href="/gp/aw/sh.html/ref=aa_ft_sh/176-4101438-5479234">Search and Browse History</a></p>
<p id='footer-links'>
<a href="/gp/aw/help/id=cou/176-4101438-5479234?storeName=">Conditions of Use</a> | <a href="/gp/aw/help/id=mpa/176-4101438-5479234?storeName=">Privacy Notice</a>
|
<a href="mailto:Amazonmobilefeedback@amazon.com?subject=Amazon Mobile Feedback ">
Feedback
</a>
</p>
<p id='copyright' class="a-color-tertiary">
&copy; 1996-2013, Amazon.com, Inc. or its affiliates
</p>
</div><script async src="http://z-ecx.images-amazon.com/images/G/01/AUIClients/AnywhereDetailJS_v1.f2dbc38c459d4a2ab77eba176dc95be1a5dadb89.min._V376067175_.js"></script>
</div>
</div>
<div id='be' style='display:none;visibility:hidden;'><form name='ue_backdetect'><input name='ue_back' value='1' type='hidden'></form><script type="text/javascript">
(function(a){if(document.ue_backdetect&&document.ue_backdetect.ue_back){a.ue.bfini=document.ue_backdetect.ue_back.value}if(a.uet){a.uet("be")}if(a.onLdEnd){if(window.addEventListener){window.addEventListener("load",a.onLdEnd,false)}else{if(window.attachEvent){window.attachEvent("onload",a.onLdEnd)}}}if(a.ueh){a.ueh(0,window,"load",a.onLd,1)}if(a.ue_pr&&(a.ue_pr==3||a.ue_pr==4)){a.ue._uep()}})(ue_csm);
</script>
<a href='/gp/uedata/176-4101438-5479234?tepes=1&amp;id=0WP9Y459PHTN10MNJVR2'>v</a>
<noscript><img src='/gp/uedata/176-4101438-5479234?noscript&amp;id=0WP9Y459PHTN10MNJVR2' /></noscript></div>
<script type='text/javascript'>
(function(a){a._uec=function(d){var h=window,b=h.performance,f=b?b.navigation.type:0;if(f==0){var e="; expires="+new Date(+new Date+604800000).toGMTString(),c=+new Date-ue_t0;if(c>0){var g=a.ue_tsinc?"|"+ +new Date:"|";document.cookie="csm-hit="+(d/c).toFixed(2)+g+e+"; path=/"}}}})(ue_csm);
_uec(38874);
</script>
</body>
</html>
<!-- whfh-0rIBgfbZSgwp0OgDU7U4QRx4GkZYUfpT1KWBFnMhwQFtpJT04o1NQEg3vs45N9OwaUbXxndyiZk= rid-0WP9Y459PHTN10MNJVR2 -->

64
spec/fixtures/oneboxer/android.response vendored Normal file

File diff suppressed because one or more lines are too long

709
spec/fixtures/oneboxer/apple.response vendored Normal file
View File

@ -0,0 +1,709 @@
HTTP/1.1 200 OK
Last-Modified: Wed, 13 Feb 2013 09:56:29 GMT
x-apple-lok-response-date: Wed Feb 13 01:56:29 PST 2013
x-apple-lok-stor: memcached
x-apple-lok-current-storefront: <null>
x-apple-orig-url-path: /us/app/minecraft-pocket-edition-lite/id479651754
x-apple-application-site: NWK
x-apple-lok-expire-date: Wed Feb 13 02:00:29 PST 2013
apple-timing-app: 3 ms
x-apple-aka-ttl: Generated Wed Feb 13 01:59:31 PST 2013, Expires Wed Feb 13 02:00:31 PST 2013, TTL 60s
x-apple-translated-wo-url: /WebObjects/MZStore.woa/wa/viewSoftware?id=479651754&cc=us
x-webobjects-loadaverage: 0
x-apple-application-instance: 1002008
x-apple-lok-path: v0_https:i.a.c/MZStore/viewSoftware?id=479651754&cc=us-NOXASF-Ak
Content-Type: text/html; charset=UTF-8
x-apple-lok-ttl: Generated Wed Feb 13 01:56:29 PST 2013, Expires Wed Feb 13 02:00:29 PST 2013, TTL 240s
x-apple-jingle-correlation-key: K3HOE5UYJXVQY
Cache-Control: no-transform, max-age=60
Date: Wed, 13 Feb 2013 09:59:31 GMT
Transfer-Encoding: chunked
Connection: keep-alive
Connection: Transfer-Encoding
X-Apple-Partner: origin.0
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN" "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html prefix="og: http://ogp.me/ns#" xmlns="http://www.apple.com/itms/" lang="en">
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" /><meta name="keywords" content="Minecraft Pocket Edition Lite, Mojang, Games, Simulation, ios apps, app, appstore, app store, iphone, ipad, ipod touch, itouch, itunes" /><meta name="description" content="Read reviews, get customer ratings, see screenshots, and learn more about Minecraft Pocket Edition Lite on the App Store. Download Minecraft Pocket Edition Lite and enjoy it on your iPhone, iPad, and iPod touch." /><meta content="Minecraft Pocket Edition Lite" property="og:title" /><meta content="Get Minecraft Pocket Edition Lite on the App Store. See screenshots and ratings, and read customer reviews." property="og:description" /><meta content="App Store" property="og:site_name" /><meta content="http://a4.mzstatic.com/us/r1000/087/Purple/99/2f/dd/mzl.erzwvjsi.png" property="og:image" /><meta content="image/png" property="og:image:type" />
<link rel="canonical" href="https://itunes.apple.com/us/app/minecraft-pocket-edition-lite/id479651754?mt=8" />
<title>Minecraft Pocket Edition Lite for iPhone, iPod touch, and iPad on the iTunes App Store</title>
<script>
if (!window.its) {
window.its = {};
}
its.markupLoadStartTime = new Date().getTime();
if (!window.onerror) window.onerror = function(message, url, lineNumber) {
if (!window._earlyOnerrorException) {
window._earlyOnerrorException = {message: message,
url: url,
lineNumber: lineNumber};
}
};
</script>
<link rel="stylesheet" type="text/css" href="https://s.mzstatic.com/htmlResources/1AB7/web-storefront-base.css" />
<link rel="stylesheet" type="text/css" href="https://s.mzstatic.com/htmlResources/1AB7/web-storefront-preview.css" />
<script type="text/javascript" charset="utf-8" src="/htmlResources/1AB7/frameworks-primaryinit01.js"></script>
<script type="text/javascript" charset="utf-8">its.serverData={"pageData": {"BUY_PARAM_PRICETYPE": "STDQ","basePrice": 0,"isFree": true,"volumePrice": 0,"basePriceForDisplay": "Free","inflectionValue": 1,"productAdamId": "479651754","productType": "C","BUY_PRODUCT_URL": "https://itunes.apple.com/WebObjects/MZFinance.woa/wa/volumeBuyProduct?cc=us","jsonSearchUrl": "https://itunes.apple.com/us/search","jsonLookupUrl": "https://itunes.apple.com/us/lookup"},"constants": {"IXDisplayableKind": {"Song": {"id": 1,"cssClasses": ["song","music"]},"Album": {"id": 2,"cssClasses": ["album","music"]},"Book": {"id": 3,"cssClasses": ["audiobook"]},"Podcast": {"id": 4,"cssClasses": ["podcast"]},"MusicVideo": {"id": 5,"cssClasses": ["music-video","music","video"]},"TVEpisode": {"id": 6,"cssClasses": ["tv-episode","tv","video"]},"TVSeason": {"id": 7,"cssClasses": ["tv-season","tv","video"]},"ShortFilm": {"id": 8,"cssClasses": ["short-film","movie","video"]},"Movie": {"id": 9,"cssClasses": ["movie","video"]},"ClassicSoftware": {"id": 10,"cssClasses": ["ipod-game"]},"MobileSoftware": {"id": 11,"cssClasses": ["application"]},"MacSoftware": {"id": 30,"cssClasses": ["application","mac-application"]},"iTunesPass": {"id": 12,"cssClasses": ["itunes-pass","album","music"]},"Booklet": {"id": 13,"cssClasses": ["booklet","music"]},"Mix": {"id": 14,"cssClasses": ["mix","music"]},"PodcastEpisode": {"id": 15,"cssClasses": ["podcast-episode"]},"SoftwareAddOn": {"id": 16,"cssClasses": ["software-add-on","application"]},"iMix": {"id": 17,"cssClasses": ["imix","music"]},"ClassicSoftwarePackage": {"id": 18,"cssClasses": ["ipod-game"]},"WeMix": {"id": 19,"cssClasses": ["wemix","music"]},"Artist": {"id": 20,"cssClasses": []},"Ringtone": {"id": 21,"cssClasses": []},"RingtoneAlbum": {"id": 22,"cssClasses": []},"PreorderAlbum": {"id": 23,"cssClasses": ["album","music"]},"MovieBundle": {"id": 24,"cssClasses": ["bundle","movie","video"]},"EBook": {"id": 25,"cssClasses": ["ebook"]},"Concert": {"id": 26,"cssClasses": []},"RichPost": {"id": 29,"cssClasses": []},"SocialPerson": {"id": 27,"cssClasses": []},"SocialArtist": {"id": 28,"cssClasses": []},"Tone": {"id": 31,"cssClasses": []},"ToneAlbum": {"id": 32,"cssClasses": []},"TheyMix": {"id": 33,"cssClasses": []},"Course": {"id": 34,"cssClasses": ["course","itunes-u"]},"MetaEBook": {"id": 35,"cssClasses": ["ebook"]},"ApplePubEBook": {"id": 36,"cssClasses": ["ebook"]},"ApplePubTextbook": {"id": 37,"cssClasses": ["ebook"]}},"Urls": {"upgradeITunesUrl": "http://www.apple.com/itunes/download/","upgradeSafariUrl": "http://www.apple.com/safari/download/"},"MZMediaType": {"Music": {"id": 1},"Podcasts": {"id": 2},"Audiobooks": {"id": 3},"TVShows": {"id": 4},"MusicVideos": {"id": 5},"Movies": {"id": 6},"ClassicSoftware": {"id": 7},"MobileSoftware": {"id": 8},"Ringtones": {"id": 9},"iTunesU": {"id": 10},"EBooks": {"id": 11},"MacSoftware": {"id": 12}},"SFSortOrder": {"Name": {"id": 0},"Featured": {"id": 1},"ReleaseDate": {"id": 2},"Popularity": {"id": 3},"PurchaseDate": {"id": 4},"TopRated": {"id": 5},"ExpirationDate": {"id": 6},"Price": {"id": 7},"ArtistName": {"id": 8},"PlaylistName": {"id": 9},"Duration": {"id": 11},"DiscNumber": {"id": 12},"TrackNumber": {"id": 13},"CmpRecommended": {"id": 10},"AllTimeBestSellers": {"id": 14}},"SFCustomComponentCountryCode": "usa"},"properties": {"clientStatsLoadTimeGroup": "2000","MZHtmlResourcesUtil.allowDeferJsLoad": true,"countryCodeIso2a": "us","currencyFormat": "$#,##0.00;$#,##0.00;-$#,##0.00","currencySymbol": "$","currencyThousandSeparator": ",","currencyDecimalSeparator": ".","iTunesUEnrollLink": "","ITSServerEnvironment": "prod","ITSServerInstance": "1002008","ITSResourceRevNum": "1AB7","its.sf6.Metrics.urlProtocol": "https","its.sf6.Metrics.urlDomain": "metrics.mzstatic.com","its.sf6.Metrics.urlPathPrefix": "/WebObjects/","its.sf6.Metrics.urlAppName": "MZUserXP","its.sf6.Metrics.urlPathSuffix": ".woa/wa/","its.sf6.Metrics.urlAction": "recordStats","its.sf6.Metrics.senderName": "ITSClient","ITSLogger.ServerReportingProtocol": "https","ITSLogger.ServerReportingDomain": "metrics.mzstatic.com","ITSLogger.ServerReportingApp": "MZUserXP","ITSLogger.RecordStatsAction": "recordStats","ITSLogger.SenderName": "ITSClient","DynaLoader.allowDynaLoading": true,"itsLoggerQueueProcessingInterval": 10000,"cobaltBundleId": "com.apple.itunesu","getCobaltAppLink": "https://itunes.apple.com/us/app/id490217893","cobaltLearnMore": "https://itunes.apple.com/WebObjects/MZStore.woa/wa/learnMore?about=iTunesUUpgradePage&cc=us&type=2","isCobaltEnabled": true,"isCobaltJavascriptRedirectEnabled": true,"isCobaltUpsellPageEnabled": true,"personalizedButtonsEnabled": true,"SF6.Personalization.isCMAEnabled": true,"SF6.Personalization.isCMSEnabled": true,"SF6.StorePlatform.whitelistParams": ["caller","dsid","id","p"],"its.sf6.Metrics.disabled": true}}</script>
<script type="text/javascript" charset="utf-8">
if(typeof(iTSLocalization) == "undefined") { iTSLocalization = new Object(); }
if(typeof(iTSLocalization._strings) == "undefined") { iTSLocalization._strings = new Object(); }
iTSLocalization._strings.base = {"_decimalSeparator":".", "_thousandsSeparator":",", "Js.iTunesStoreError.Message":"We could not complete your request.", "Js.iTunesStoreError.Explanation":"There was an error in the iTunes Store. Please try again later. (@@errorNum@@)", "Js.TextTruncation.More":"More", "More":"More", "Less":"Less", "Js.TextLimit.Remaining":"@@count@@ characters remaining", "Js.Showcase.Next":"Next Item", "Js.InlineReview.1":"hate it", "Js.InlineReview.2":"don't like it", "Js.InlineReview.3":"it's ok", "Js.InlineReview.4":"it's good", "Js.InlineReview.5":"it's great", "Js.CreateAccount":"Create Apple ID", "Js.InlineReview.SigninTitle":"Sign in to write a review.", "Js.InlineReview.SigninMessage":"Enter your Apple ID and password, then click Sign In.", "Js.InlineRating.SigninTitle":"Sign in to rate this item.", "Js.InlineRating.SigninMessage":"Sign in to continue.", "Js.ReportAConcern.SigninTitle":"Sign in to report a concern.", "Js.ReportAConcern.SigninMessage":"Enter your Apple ID and password, then click Sign In.", "Js.TellAFriend.SigninTitle":"Sign in to tell a friend.", "Js.TellAFriend.SigninMessage":"Enter your Apple ID and password, then click Sign In.", "Js.InlineReview.RateThis":"Rate this", "Js.InlineReview.ClickToRate":"Click to rate", "Js.InlineReview.Thanks":"Thanks!", "Js.InlineReview.Error":"Error", "Js.Pagination.PageNumber":"Page @@num@@", "Js.Pagination.PageNumberTitle":"page @@num@@", "Js.Pagination.PreviousPage":"Previous Page", "Js.Pagination.NextPage":"Next Page", "Js.Pagination.Next":"Next", "Js.Pagination.Back":"Back", "Js.Pagination.DisabledButtonText":"disabled @@button_text@@", "Js.QuickView.Unavailable.Title":"Quick View is currently unavailable for this item.", "Js.QuickView.Unavailable.Text":"Please try again later.", "Js.Search.HintsTitle":"Suggestions", "Js.Wishlist.RemoveTooltip":"Remove from Wish List", "Js.MyAlerts.ConfirmEmailSignUp.Message":"Are you sure you want to receive email alerts?", "Js.MyAlerts.ConfirmEmailSignUp.Explanation":"You can change this preference at any time from your My Alerts page.", "Js.MyAlerts.CancelEmailSignUp.Message":"Are you sure you want to stop receiving email alerts?", "Js.MyAlerts.CancelEmailSignUp.Explanation":"You can change this preference at any time from your My Alerts page.", "Js.MyAlerts.GeniusActivationNeeded.Message":"This requires Genius.", "Js.MyAlerts.GeniusActivationNeeded.Explanation":"Alerts based on your library content will not be enabled until you have turned on Genius. To learn more, click Go to Genius.", "Js.MyAlerts.GeniusActivationNeeded.Button":"Go to Genius", "Js.ManageArtistAlerts.UncheckAll.Artists":"Uncheck All Artists", "Js.ManageArtistAlerts.UncheckAll.Actors":"Uncheck All Actors", "Js.ManageArtistAlerts.UncheckAll":"Uncheck All", "Js.ManageArtistAlerts.CheckAll.Artists":"Check All Artists", "Js.ManageArtistAlerts.CheckAll.Actors":"Check All Actors", "Js.ManageArtistAlerts.CheckAll":"Check All", "Js.List.Item":"item", "Js.InlinePreview.PlayPreview":"Play preview of @@title@@", "Js.InlinePreview.StopPreview":"Stop preview of @@title@@", "Js.CNConnections.UserReview.YouLiked":"You Liked", "Js.CNConnections.PeoplePopupMore":"and @@count@@ other@@s@@...", "Js.CNConnections.Confirmed":"Confirmed", "Js.CNConnections.RequestSent":"Request sent", "Js.CNConnections.LoginRequired.Title":"Sign in to access Ping.",
"Js.CNConnections.LoginRequired.Message":"This requires Ping. Ping will no longer be available as of September 30, and we are not accepting new members. If you are already a Ping member, sign in below to continue.", "Js.CNConnections.OptInRequired.Title":"Ping",
"Js.CNConnections.OptInRequired.Message":"This requires Ping. Ping will no longer be available as of September 30, and we are not accepting new members. If you are already a Ping member, sign in below to continue.", "Js.CNConnections.Dialog.Cancel":"Cancel", "Js.CNConnections.Dialog.GetStarted":"Get Started", "CNConnections.Dialog.PrivateUser.IllegalAction.Title":"Private users may not perform this action.", "CNConnections.Dialog.PrivateUser.IllegalAction.Message":"If you would like to perform this action, please change your privacy settings.", "CNConnections.Dialog.PrivateUser.LeakyAction.Title":"Are you sure you want to perform this action?", "CNConnections.Dialog.PrivateUser.LeakyAction.Message":"This action will make your profile photo and name visible to others.", "CNConnections.Dialog.StopFollowing.Title":"Are you sure you want to stop following @@fullName@@?", "CNConnections.Dialog.StopFollowing.Message":"CNConnections.Dialog.StopFollowing.Message", "CNConnections.Dialog.Like.Review.SignIn.Title":"Sign in to like a review.", "CNConnections.Dialog.Like.Review.SignIn.Message":"Enter your Apple ID or AOL screen name and your password, then click Sign In.", "CNConnections.Dialog.Post.Review.SignIn.Title":"Sign in to post.", "CNConnections.Dialog.Post.Review.SignIn.Message":"Enter your Apple ID or AOL screen name and your password, then click Sign In.", "CNConnections.Dialog.OptIn.Title":"Ping Will No Longer Be Available as of September 30", "CNConnections.Dialog.OptIn.Message":"Liking a review requires Ping, and we are no longer accepting new members.", "CNConnections.Dialog.OptIn.ButtonSubmit":"Learn More", "CNConnections.Dialog.OptIn.ButtonCancel":"Cancel", "CNConnections.Dialog.OptIn.ButtonSignIn":"Sign In", "CNConnections.Upload.UploadErrorHeading":"There is a Problem With Your Upload", "CNConnections.Upload.UploadErrorMessage":"Sorry, there was an error during upload.", "CNConnections.Upload.MaxPhotosErrorMessage":"You can have no more than 20 photos in one post.", "JS.errors.requiredLite":"Please fill in all required fields."}
</script>
<script type="text/javascript" charset="utf-8" src="/htmlResources/1AB7/web-storefront-base.js"></script>
<script type="text/javascript" charset="utf-8" src="/htmlResources/1AB7/web-storefront-preview.js"></script>
<link href="https://ssl.apple.com/global/nav/styles/navigation.css" id="globalheader-stylesheet" rel="stylesheet" type="text/css" />
</head>
<body onload="detectAndOpenItunes();" class="software geo-us lang-en-us">
<script type="text/javascript">
var searchSection = 'ipoditunes';
var searchCountry = 'us';
</script>
<script src="https://ssl.apple.com/global/nav/scripts/globalnav.js" type="text/javascript" charset="utf-8"></script>
<nav id="globalheader" class="itunes">
<!--googleoff: all-->
<ul id="globalnav" role="navigation">
<li id="gn-apple"><a href="http://www.apple.com/"><span>Apple</span></a></li>
<li id="gn-store"><a href="http://store.apple.com/"><span>Store</span></a></li>
<li id="gn-mac"><a href="http://www.apple.com/mac/"><span>Mac</span></a></li>
<li id="gn-ipod"><a href="http://www.apple.com/ipod/"><span>iPod</span></a></li>
<li id="gn-iphone"><a href="http://www.apple.com/iphone/"><span>iPhone</span></a></li>
<li id="gn-ipad"><a href="http://www.apple.com/ipad/"><span>iPad</span></a></li>
<li id="gn-itunes"><a href="http://www.apple.com/itunes/"><span>iTunes</span></a></li>
<li id="gn-support" class="gn-last"><a href="http://www.apple.com/support/"><span>Support</span></a></li>
</ul>
<!--googleon: all-->
<div id="globalsearch">
<form action="http://www.apple.com/search/" method="post" class="search" id="g-search"><div class="sp-label">
<label for="sp-searchtext">Search</label>
<input type="text" name="q" id="sp-searchtext" accesskey="s" />
</div></form>
<div id="sp-magnify"><div class="magnify-searchmode"></div><div class="magnify"></div></div>
<div id="sp-results"></div>
</div>
</nav>
<script type="text/javascript">
AC.GlobalNav.Instance = new AC.GlobalNav();
</script>
<div id="productheader" data-hires="true">
<h2><img src="http://ax.phobos.apple.com.edgesuite.net/images/web/itunes_preview/itunespreview_en.png" alt="iTunes" height="32" width="263"></h2>
<ul>
<li id="pn-whatsnew"><a href="http://www.apple.com/itunes/whats-new/">Whats New</a></li>
<li id="pn-whatis"><a href="http://www.apple.com/itunes/what-is/">What is iTunes</a></li>
<li id="pn-charts"><a href="http://www.apple.com/itunes/charts/">iTunes Charts</a></li>
</ul>
</div>
<div id="main">
<div id="itunes-detector">
<div id="launching-itunes">
<div id="status">
<div class="opening-itunes"><span>Opening the iTunes Store.</span><span>If iTunes doesn't open, click the iTunes application icon in your Dock or on your Windows desktop.</span><span class="spinner">Progress Indicator</span></div>
</div>
</div>
<div id="itunes-client-required">
<div class="callout">
<div class="left">iTunes</div>
<h2>iTunes is the world's easiest way to organize and add to your digital media collection.</h2>
<p preview-capable-text="We are unable to find iTunes on your computer. To download the free app Minecraft Pocket Edition Lite by Mojang, get iTunes now." class="intro has-preview-capable-text">
We are unable to find iTunes on your computer. To download the free app Minecraft Pocket Edition Lite by Mojang, get iTunes now.
</p>
<div class="download">
<p>Already have iTunes? Click I Have iTunes to open it now.</p>
<a class="i-have-itunes" onclick="its.detect.userOverrideSetItunesInstalled(); its.detect.openItunes(); return true;" href="#">
<img alt="I Have iTunes" src="/images/web/ihaveitunes.png" />
</a>
<a href="#" onclick="javascript:window.location='http://www.apple.com/itunes/affiliates/download/?id=479651754'; return true;"><img alt="Free Download" src="/images/web/freedownload.png" /></a>
</div>
<a class="macpc" href="#">iTunes for Mac + PC</a>
</div>
</div>
</div>
<script type="text/javascript">
deviceDetect();
</script>
<div id="desktopContentBlockId" class='platform-content-block display-block'>
<div id="content">
<div class="padder">
<div id="title" class="intro ">
<div class="left">
<h1>Minecraft Pocket Edition Lite</h1>
<h2>By Mojang</h2>
</div>
<div class="right">
<a href="https://itunes.apple.com/us/artist/mojang/id479516146" class="view-more">View More By This Developer</a>
</div>
<p>Open iTunes to buy and download apps.</p>
</div>
<div class="center-stack">
<div more-text="More" metrics-loc="Titledbox_Description" class="product-review">
<h4>
Description
</h4>
<p>Imagine it, build it. Create worlds on the go with Minecraft - Pocket Edition<br /><br />This is the Lite version of Minecraft - Pocket Edition. Minecraft - Pocket Edition allows you to build on the go. Use blocks to create masterpieces as you travel, hangout with friends, sit at the park, the possibilities are endless. Move beyond the limits of your computer and play Minecraft everywhere you go.<br /><br />Limitations of the Lite version<br />* The world is not saved between sessions<br />* Multiplayer worlds can not be copied to your phone<br />* Only 18 of the 36 different blocks are available</p>
</div>
<div class="app-links"><a rel="nofollow" target="_blank" href="http://www.minecraft.net" class="see-all">Minecraft Pocket Edition Lite Support</a></div>
<div more-text="More" metrics-loc="Titledbox_What&#39;s New in Version 0.2.1" class="product-review">
<h4>
What's New in Version 0.2.1
</h4>
<p>Minor version 0.2.1 (new controls!)<br />+ New optional control scheme; "split touch controls"<br />+ Added pigs to survival mode<br />+ Flying is changed; ascend/descend by sliding from the center button to the up/down button<br />+ More inventory selection slots<br />+ Bug fixes; dark tree trunk was impossible to pick up, invisible fences, resource items in the world were always bright, pixelated destruction feedback circle</p>
</div>
<div metrics-loc="Swoosh_" rows="1" class="swoosh lockup-container application large screenshots">
<div class="title">
<h2>Screenshots</h2>
<div class="pill">
<a metrics-loc="Pill_" metrics-leaf="1" href="#">iPhone</a>
<a metrics-loc="Pill_" metrics-leaf="1" href="#">iPad</a>
</div>
<a metrics-loc="Seeall" href="" class="see-all"><span></span></a>
</div>
<div class="toggle">
<div metrics-loc="iPhone" num-items="3" class="content iphone-screen-shots"><div><div class="lockup"><img alt="iPhone Screenshot 1" class="landscape" src="http://a1032.phobos.apple.com/us/r1000/065/Purple/66/56/d1/mzl.nlcdenrl.320x480-75.jpg" /></div><div class="lockup"><img alt="iPhone Screenshot 2" class="landscape" src="http://a517.phobos.apple.com/us/r1000/089/Purple/90/4e/9f/mzl.nresztpb.320x480-75.jpg" /></div><div class="lockup"><img alt="iPhone Screenshot 3" class="landscape" src="http://a896.phobos.apple.com/us/r1000/070/Purple/bb/dc/5c/mzl.ufuvkbwe.320x480-75.jpg" /></div></div></div><div metrics-loc="iPad" num-items="3" class="content ipad-screen-shots"><div><div class="lockup"><img alt="iPad Screenshot 1" class="landscape" src="http://a1464.phobos.apple.com/us/r1000/106/Purple/12/3d/d0/mzl.rzukvhhg.480x480-75.jpg" /></div><div class="lockup"><img alt="iPad Screenshot 2" class="landscape" src="http://a42.phobos.apple.com/us/r1000/120/Purple/ca/ca/d7/mzl.itrqspav.480x480-75.jpg" /></div><div class="lockup"><img alt="iPad Screenshot 3" class="landscape" src="http://a240.phobos.apple.com/us/r1000/118/Purple/49/2f/83/mzl.zkdizava.480x480-75.jpg" /></div></div></div>
</div>
</div>
<div class="customer-reviews">
<h4>Customer Reviews</h4>
<div more-text="More" class="customer-review">
<h5>
<span class="customerReviewTitle">Cool!</span>
<div class='rating' role='img' tabindex='-1' aria-label='5 stars'><div><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span></div></div>
</h5>
<span class="user-info">by
Robertobobbym
</span>
<p class="content" will-truncate-max-height="0" data-text-truncate-lines="5">
Can you believe it? It's minecraft for mobile phones! Slowly becoming just like the computer one, updates are being made, this is so awesome!<br/><br/>Also, did anyone notice the 3D sound system? I did, so cool :3<br/><br/>PIGS! :D
</p>
</div>
<div more-text="More" class="customer-review">
<h5>
<span class="customerReviewTitle">Improving</span>
<div class='rating' role='img' tabindex='-1' aria-label='5 stars'><div><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span></div></div>
</h5>
<span class="user-info">by
Taitai76
</span>
<p class="content" will-truncate-max-height="0" data-text-truncate-lines="5">
Pleas add:<br/>More enmays like creepers endermen and all<br/><br/>Let us craft so we make our own pickaxes wepons and tools it the whole reason its called mine CRAFT<br/><br/>and finally add more animles to tame and all.<br/><br/>Please update all these improvments
</p>
</div>
<div more-text="More" class="customer-review">
<h5>
<span class="customerReviewTitle">Review</span>
<div class='rating' role='img' tabindex='-1' aria-label='5 stars'><div><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span></div></div>
</h5>
<span class="user-info">by
Jdiem
</span>
<p class="content" will-truncate-max-height="0" data-text-truncate-lines="5">
Save button
</p>
</div>
</div>
<div metrics-loc="Swoosh_" rows="1" class="swoosh lockup-container application large">
<div class="title">
<h2>Customers Also Bought</h2>
</div>
<div num-items="5" class="content"><div>
<div rating-software="100,itunes-games" parental-rating="1" role="group" metrics-loc="Lockup_" adam-id="425652036" preview-artist="Geek Beach" aria-label="Dune Rider" preview-title="Dune Rider" class="lockup small application">
<a href="https://itunes.apple.com/us/app/dune-rider/id425652036?mt=8" class="artwork-link"><div class="artwork"><img width="100" height="100" alt="Dune Rider" class="artwork" src="http://a1.mzstatic.com/us/r1000/068/Purple/v4/33/73/f1/3373f115-e7f7-8701-cfd8-37a952ad53a5/mzl.nrblawbg.100x100-75.jpg" /><span class="mask"></span></div></a>
<div class="lockup-info">
<ul role="presentation" class="list"><li><a href="https://itunes.apple.com/us/app/dune-rider/id425652036?mt=8" class="name">Dune Rider</a></li><li><a href="https://itunes.apple.com/us/genre/ios-games/id6014?mt=8" class="genre">Games</a></li><li><a onclick="return its.detect.openItunes(&#39;https://itunes.apple.com/us/app/dune-rider/id425652036?mt=8&#39;);" href="#" class="action view-in-itunes"><span>View In iTunes</span></a></li></ul>
</div>
</div>
<div rating-software="100,itunes-games" parental-rating="1" role="group" metrics-loc="Lockup_" adam-id="408257810" preview-artist="Abraham Stolk" aria-label="the little crane that could" preview-title="the little crane that could" class="lockup small application">
<a href="https://itunes.apple.com/us/app/the-little-crane-that-could/id408257810?mt=8" class="artwork-link"><div class="artwork"><img width="100" height="100" alt="the little crane that could" class="artwork" src="http://a3.mzstatic.com/us/r1000/111/Purple/v4/0f/24/c8/0f24c862-b182-35de-bd25-dbebcf4b7667/mzm.wbkvgkyk.100x100-75.jpg" /><span class="mask"></span></div></a>
<div class="lockup-info">
<ul role="presentation" class="list"><li><a href="https://itunes.apple.com/us/app/the-little-crane-that-could/id408257810?mt=8" class="name">the little crane that could</a></li><li><a href="https://itunes.apple.com/us/genre/ios-games/id6014?mt=8" class="genre">Games</a></li><li><a onclick="return its.detect.openItunes(&#39;https://itunes.apple.com/us/app/the-little-crane-that-could/id408257810?mt=8&#39;);" href="#" class="action view-in-itunes"><span>View In iTunes</span></a></li></ul>
</div>
</div>
<div rating-software="100,itunes-games" parental-rating="1" role="group" metrics-loc="Lockup_" adam-id="390364604" preview-artist="Ratrod Studio Inc." aria-label="Drift Mania Championship Gold Lite" preview-title="Drift Mania Championship Gold Lite" class="lockup small application">
<a href="https://itunes.apple.com/us/app/drift-mania-championship-gold/id390364604?mt=8" class="artwork-link"><div class="artwork"><img width="100" height="100" alt="Drift Mania Championship Gold Lite" class="artwork" src="http://a2.mzstatic.com/us/r1000/114/Purple/v4/66/cb/11/66cb110c-111d-6421-57f3-19bf430c4760/mzl.kwdnbbmw.100x100-75.jpg" /><span class="mask"></span></div></a>
<div class="lockup-info">
<ul role="presentation" class="list"><li><a href="https://itunes.apple.com/us/app/drift-mania-championship-gold/id390364604?mt=8" class="name">Drift Mania Championship Gold Lite</a></li><li><a href="https://itunes.apple.com/us/genre/ios-games/id6014?mt=8" class="genre">Games</a></li><li><a onclick="return its.detect.openItunes(&#39;https://itunes.apple.com/us/app/drift-mania-championship-gold/id390364604?mt=8&#39;);" href="#" class="action view-in-itunes"><span>View In iTunes</span></a></li></ul>
</div>
</div>
<div rating-software="100,itunes-games" parental-rating="1" role="group" metrics-loc="Lockup_" adam-id="294919686" preview-artist="Ezone.com" aria-label="Crazy Snowboard" preview-title="Crazy Snowboard" class="lockup small application">
<a href="https://itunes.apple.com/us/app/crazy-snowboard/id294919686?mt=8" class="artwork-link"><div class="artwork"><img width="100" height="100" alt="Crazy Snowboard" class="artwork" src="http://a3.mzstatic.com/us/r1000/107/Purple/v4/27/9c/59/279c5980-e461-1b65-82e1-8fb96896849b/mzm.idcnsyzv.100x100-75.jpg" /><span class="mask"></span></div></a>
<div class="lockup-info">
<ul role="presentation" class="list"><li><a href="https://itunes.apple.com/us/app/crazy-snowboard/id294919686?mt=8" class="name">Crazy Snowboard</a></li><li><a href="https://itunes.apple.com/us/genre/ios-games/id6014?mt=8" class="genre">Games</a></li><li><a onclick="return its.detect.openItunes(&#39;https://itunes.apple.com/us/app/crazy-snowboard/id294919686?mt=8&#39;);" href="#" class="action view-in-itunes"><span>View In iTunes</span></a></li></ul>
</div>
</div>
<div rating-software="100,itunes-games" parental-rating="1" role="group" metrics-loc="Lockup_" adam-id="389941080" preview-artist="Logik State" aria-label="Sand Slides" preview-title="Sand Slides" class="lockup small application">
<a href="https://itunes.apple.com/us/app/sand-slides/id389941080?mt=8" class="artwork-link"><div class="artwork"><img width="100" height="100" alt="Sand Slides" class="artwork" src="http://a1.mzstatic.com/us/r1000/068/Purple/v4/63/94/51/63945127-2ea3-3bf7-0d5c-7b5571f96cbf/mzm.xqmhkley.100x100-75.jpg" /><span class="mask"></span></div></a>
<div class="lockup-info">
<ul role="presentation" class="list"><li><a href="https://itunes.apple.com/us/app/sand-slides/id389941080?mt=8" class="name">Sand Slides</a></li><li><a href="https://itunes.apple.com/us/genre/ios-games/id6014?mt=8" class="genre">Games</a></li><li><a onclick="return its.detect.openItunes(&#39;https://itunes.apple.com/us/app/sand-slides/id389941080?mt=8&#39;);" href="#" class="action view-in-itunes"><span>View In iTunes</span></a></li></ul>
</div>
</div>
</div></div>
</div>
</div>
<div id="left-stack">
<div rating-software="100,itunes-games" parental-rating="1" class="lockup product application">
<a href="https://itunes.apple.com/us/app/minecraft-pocket-edition-lite/id479651754?mt=8"><div class="artwork"><img width="175" height="175" alt="Minecraft &amp;ndash; Pocket Edition Lite" class="artwork" src="http://a5.mzstatic.com/us/r1000/087/Purple/99/2f/dd/mzl.erzwvjsi.175x175-75.jpg" /><span class="mask"></span></div></a>
<a onclick="return its.detect.openItunes(&#39;https://itunes.apple.com/us/app/minecraft-pocket-edition-lite/id479651754?mt=8&#39;);" href="#" class="action view-in-itunes"><span>View In iTunes</span></a>
<div class="fat-binary-blurb"><span class="fat-binary-badge"></span><span>This app is designed for both iPhone and iPad</span></div><ul class="list"><li><div class="price">Free</div></li><li class="genre"><span class="label">Category: </span><a href="https://itunes.apple.com/us/genre/ios-games/id6014?mt=8">Games</a></li><li class="release-date"><span class="label">Updated: </span>Mar 14, 2012</li><li><span class="label">Version: </span>0.2.1</li><li><span class="label">Size: </span>4.5 MB</li><li class="language"><span class="label">Language: </span>English</li><li><span class="label">Seller: </span>Mojang AB</li><li class="copyright">© Mojang AB</li></ul><div class="app-rating"><a href="https://itunes.apple.com/WebObjects/MZStore.woa/wa/appRatings">Rated 4+</a></div><p><span class="app-requirements">Requirements: </span>Compatible with iPhone, iPod touch, and iPad. Requires iOS 4.3 or later.</p>
</div>
<div class='extra-list customer-ratings'>
<h4>Customer Ratings</h4>
<div>Current Version:</div>
<div class='rating' role='img' tabindex='-1' aria-label='4 stars, 25571 Ratings'><div><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star ghost">&nbsp;</span></div><span class="rating-count">25571 Ratings</span>
</div>
<div>All Versions:</div>
<div class='rating' role='img' tabindex='-1' aria-label='4 stars, 31585 Ratings'><div><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star">&nbsp;</span><span class="rating-star ghost">&nbsp;</span></div><span class="rating-count">31585 Ratings</span>
</div>
</div>
<div metrics-loc="Titledbox_More by Mojang" class="extra-list more-by">
<h4>
More by Mojang
</h4>
<ul class="list"><li>
<div rating-software="100,itunes-games" parental-rating="1" role="group" metrics-loc="Lockup_" adam-id="479516143" preview-artist="Mojang" aria-label="Minecraft &ndash; Pocket Edition" preview-title="Minecraft Pocket Edition" class="lockup small application">
<a href="https://itunes.apple.com/us/app/minecraft-pocket-edition/id479516143?mt=8" class="artwork-link"><div class="artwork"><img width="75" height="75" alt="Minecraft &#8211; Pocket Edition" class="artwork" src="http://a3.mzstatic.com/us/r1000/070/Purple2/v4/3f/56/07/3f56074b-af27-8ba3-7ef8-c97314c13ee7/mzl.rfhcaysw.75x75-65.jpg" /><span class="mask"></span></div></a>
<div class="lockup-info">
<ul role="presentation" class="list"><li><a href="https://itunes.apple.com/us/app/minecraft-pocket-edition/id479516143?mt=8" class="name">Minecraft Pocket Edition</a></li><li><a onclick="return its.detect.openItunes(&#39;https://itunes.apple.com/us/app/minecraft-pocket-edition/id479516143?mt=8&#39;);" href="#" class="action view-in-itunes"><span>View In iTunes</span></a></li></ul>
</div>
</div>
</li></ul>
</div>
</div>
</div>
</div>
</div>
</div>
<object classID="CLSID:D719897A-B07A-4C0C-AEA9-9B663A28DFCB" width="1" height="1" id="iTunesDetectorIE" ></object>
<script type="text/javascript">itms.PageData.itunesDownloadUrl='http://www.apple.com/itunes/affiliates/download/?id=479651754';</script>
<div id="facebook">
<div class="fbfan">
<iframe src="http://www.facebook.com/plugins/likebox.php?id=100484820802&amp;width=230&amp;connections=0&amp;stream=false&amp;header=false&amp;height=62" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:230px; height:63px;" allowTransparency="true"></iframe>
</div>
<div class="fbfan last">
<iframe src="http://www.facebook.com/plugins/likebox.php?id=286893159420&amp;width=250&amp;connections=0&amp;stream=false&amp;header=false&amp;height=62" scrolling="no" frameborder="0" style="border:none; overflow:hidden; width:250px; height:63px;" allowTransparency="true"></iframe>
</div>
<p>Become a fan of the iTunes and App Store pages on Facebook for exclusive offers, the inside scoop on new apps and more.</p>
</div>
<div id="globalfooter">
<div id="breadory">
<ol id="breadcrumbs">
<li class="home"><a href="http://www.apple.com/">Home</a></li>
<li>iTunes</li>
</ol>
<!--googleoff: all-->
<div id="directorynav" class="itunes">
<div id="dn-cola" class="column first">
<h3>iTunes</h3>
<ul>
<li><a href="http://www.apple.com/itunes/download/">Download iTunes</a></li>
<li><a href="http://www.apple.com/itunes/whats-new/">Whats New?</a></li>
<li><a href="http://www.apple.com/itunes/what-is/">What is iTunes?</a></li>
<li><a href="http://www.apple.com/itunes/charts/songs/">iTunes Charts</a></li>
</ul>
</div>
<div id="dn-colb" class="column">
<h3>More iTunes</h3>
<ul>
<li><a href="http://www.apple.com/itunes/digital-music-basics/">Digital Music Basics</a></li>
<li><a href="http://www.apple.com/itunes/gifts/">iTunes Gifts</a></li>
<li><a href="http://www.apple.com/education/itunes-u/">iTunes U</a></li>
<li><a href="http://www.apple.com/support/ipod/">iPod + iTunes Support</a></li>
<li><a href="http://www.apple.com/airplay/">AirPlay</a></li>
<li><a href="http://www.apple.com/accessibility/itunes/vision.html">Accessibility</a></li>
</ul>
</div>
<div id="dn-colc" class="column">
<h3>Working with iTunes</h3>
<ul>
<li><a href="http://www.apple.com/itunes/sellcontent/">Sell Your Content</a></li>
<li><a href="http://www.apple.com/itunes/content-providers/">Content Providers</a></li>
<li><a href="http://www.apple.com/itunes/companies/">Market with iTunes</a></li>
<li><a href="http://www.apple.com/itunes/affiliates/">Join the Affiliate Program</a></li>
<li><a href="http://www.apple.com/itunes/link/">Link to iTunes</a></li>
</ul>
</div>
<div id="dn-cold" class="column last">
<h3>iTunes Store</h3>
<ul>
<li><a href="http://itunes.apple.com/us/browse/">Browse iTunes Store</a></li>
<li><a href="http://itunes.apple.com/us/genre/mobile-software-applications/id36?mt=8">Browse App Store</a></li>
<li><a href="http://itunes.apple.com/us/store">Buy Music Now</a></li>
<li><a href="http://store.apple.com/us/browse/home/giftcards/itunes/gallery">Buy iTunes Gift Cards</a></li>
<li><a href="https://buy.itunes.apple.com/WebObjects/MZFinance.woa/wa/redeemLandingPage">Redeem iTunes Gift Cards</a></li>
<li><a href="http://www.apple.com/itunes/corporatesales/">iTunes Corporate Sales</a></li>
<li><a href="http://itunes.apple.com/WebObjects/MZStore.woa/wa/viewFeature?id=365729306">Free Single of the Week</a></li>
<li><a href=" http://www.apple.com/itunes/inside-itunes/">Inside iTunes</a></li>
</ul>
</div>
<div class="capbottom"></div>
</div>
<!--googleon: all-->
</div><!--/breadory-->
<p class="gf-buy">Shop the <a href="http://store.apple.com/us">Apple Online Store</a> (1-800-MY-APPLE), visit an <a href="http://www.apple.com/retail/">Apple Retail Store</a>, or find a <a href="http://www.apple.com/buy/">reseller</a>.</p>
<ul class="gf-links piped">
<li><a href="http://www.apple.com/about/" class="first">Apple Info</a></li>
<li><a href="http://www.apple.com/sitemap/">Site Map</a></li>
<li><a href="http://www.apple.com/hotnews/">Hot News</a></li>
<li><a href="http://www.apple.com/rss/">RSS Feeds</a></li>
<li><a href="http://www.apple.com/contact/" class="contact_us">Contact Us</a></li>
<li><a href="http://www.apple.com/choose-your-country/" class="choose"><img src="http://images.apple.com/global/elements/flags/22x22/usa.png" alt="Choose your country or region" width="22" height="22" data-hires="true" /></a></li>
</ul>
<div class="gf-sosumi">
<p>Copyright &copy; 2013 Apple Inc. All rights reserved.</p>
<ul class="piped">
<li><a href="http://www.apple.com/legal/terms/site.html" class="first">Terms of Use</a></li>
<li><a href="http://www.apple.com/privacy/">Privacy Policy</a></li>
</ul>
</div>
</div><!--/globalfooter-->
<script language="JavaScript" type="text/javascript"><!--
var iTSMetricsCallbackFunction = function() {
ITSMetrics.reportingSuite = "appleitmsna,appleitmsus";
ITSMetrics.omniture = ITSMetrics.createBaselineOmnitureObject();
ITSMetrics.isPageMetricsEnabled=true;
/* Page Metrics */
ITSMetrics.omniture.pageName="SEO-Software-US-Mojang-Minecraft \u2013 Pocket Edition Lite-479651754";
ITSMetrics.omniture.channel="SEO";
ITSMetrics.omniture.prop22="HTML";
ITSMetrics.omniture.eVar22="HTML";
ITSMetrics.omniture.products="Mojang-Minecraft \u2013 Pocket Edition Lite-479651754";
/* User Agent */
var userAgentForMetrics = ITSMetrics.userAgentForMetrics();
ITSMetrics.omniture.prop12 = userAgentForMetrics;
ITSMetrics.omniture.eVar12 = userAgentForMetrics;
// check if Game Center
var gcUserAgent = "GameCenter";
var isGameCenter = userAgentForMetrics.length >= gcUserAgent.length && userAgentForMetrics.substr(0, gcUserAgent.length) == gcUserAgent;
if (isGameCenter) {
// prepend "GameCenter" to page and channel name
if (ITSMetrics.omniture.pageName) ITSMetrics.omniture.pageName = "GameCenter-" + ITSMetrics.omniture.pageName;
if (ITSMetrics.omniture.channel) ITSMetrics.omniture.channel = "GameCenter-" + ITSMetrics.omniture.channel;
}
/* Browser Plugins */
ITSMetrics.shouldTrackBrowserPlugins = false;
/* Pass-thru query params */
ITSMetrics.processQueryParameterInfoInCurrentRequest(ITSMetrics.omniture);
if (ITSMetrics.isPageMetricsEnabled) {
ITSMetrics.emitPagePing = function() {
var s_code=ITSMetrics.omniture.t();
if (s_code) {
var containingDiv = document.createElement('div');
containingDiv.innerHTML = s_code;
document.body.appendChild(containingDiv);
}
};
its.x.addEventListener(window, 'load', function() { window.setTimeout(ITSMetrics.emitPagePing, 1) }, false );
}
};
if (!window["ITSMetrics"]){
iTSDefer.register(function() {
iTSMetricsCallbackFunction();
});
} else {
iTSMetricsCallbackFunction();
}
--></script>
<script>
if (!window.its) {
window.its = {};
}
window.its.markupLoadEndTime = new Date().getTime();
</script>
</body>
</html>

1252
spec/fixtures/oneboxer/flickr.response vendored Normal file

File diff suppressed because one or more lines are too long

View File

@ -0,0 +1,9 @@
HTTP/1.0 302 Moved Temporarily
Server: squid/2.7.STABLE9
Date: Wed, 13 Feb 2013 10:16:13 GMT
Content-Length: 0
Location: http://en.m.wikipedia.org/wiki/Ruby
X-Cache: MISS from amssq36.esams.wikimedia.org
X-Cache-Lookup: MISS from amssq36.esams.wikimedia.org:80
Connection: close

File diff suppressed because one or more lines are too long

View File

@ -8,6 +8,9 @@ require 'spork'
#uncomment the following line to use spork with the debugger #uncomment the following line to use spork with the debugger
#require 'spork/ext/ruby-debug' #require 'spork/ext/ruby-debug'
require 'fakeweb'
FakeWeb.allow_net_connect = false
module Helpers module Helpers
def log_in(fabricator=nil) def log_in(fabricator=nil)
user = Fabricate(fabricator || :user) user = Fabricate(fabricator || :user)
@ -19,6 +22,11 @@ module Helpers
session[:current_user_id] = user.id session[:current_user_id] = user.id
end end
def fixture_file(filename)
return '' if filename == ''
file_path = File.expand_path(File.dirname(__FILE__) + '/fixtures/' + filename)
File.read(file_path)
end
end end
Spork.prefork do Spork.prefork do