Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

Refactor amazon product feed example into proper MVC implementation w…

…ith tests that use mocked web connection.
  • Loading branch information...
commit 9d24f1e5188d11c3c0f676f9847311d677b10adc 1 parent 298f8db
@wolframarnold wolframarnold authored
View
1  Gemfile
@@ -42,4 +42,5 @@ end
group :test do
gem 'factory_girl_rails'
gem 'launchy' # for opening error pages from webrat & capybara in a browser
+ gem 'fakeweb'
end
View
2  Gemfile.lock
@@ -58,6 +58,7 @@ GEM
factory_girl_rails (1.0.1)
factory_girl (~> 1.3)
railties (>= 3.0.0)
+ fakeweb (1.3.0)
gherkin (2.3.5)
json (>= 1.4.6)
i18n (0.5.0)
@@ -124,6 +125,7 @@ DEPENDENCIES
cucumber-rails
database_cleaner
factory_girl_rails
+ fakeweb
launchy
rails (= 3.0.5)
rspec-rails
View
2  app/controllers/users_controller.rb
@@ -8,7 +8,7 @@ def index
end
def product
-
+ @products = Product.fetch_all
end
def show
View
27 app/models/product.rb
@@ -0,0 +1,27 @@
+require 'open-uri'
+class Product
+
+ BASE_URL = "http://www.amazon.com/rss/tag/running/popular?length=1"
+
+ attr_accessor :title, :link, :image_url
+
+ def initialize(hash={})
+ @title = hash[:title]
+ @link = hash[:link]
+ @image_url = hash[:image_url]
+ end
+
+ def self.fetch_all
+ SimpleRSS.parse(open(BASE_URL)).items.map do |i|
+ Product.new(:title => i.title, :link => i.link, :image_url => parse_img_url(i.description))
+ end
+ end
+
+ private
+
+ def self.parse_img_url(desc)
+ xml = Nokogiri::XML.parse(desc)
+ xml.css("img").first['src']
+ end
+
+end
View
10 app/views/users/product.html.erb
@@ -1,12 +1,10 @@
<h1>Products</h1>
-<% require 'open-uri' %>
-<% feed = SimpleRSS.parse(open("http://www.amazon.com/rss/tag/running/popular?length=1")) %>
<ul>
- <% feed.items.each do |item| %>
+ <% @products.each do |prod| %>
<li>
- <h2><%= item.title %></h2>
- <p><%= link_to "Click here to buy", item.link %></p>
+ <h2><%= raw prod.title %></h2>
+ <p><%= link_to "Click here to buy", prod.link %></p>
+ <%= image_tag prod.image_url %>
</li>
-
<% end %>
</ul>
View
47 spec/models/product_spec.rb
@@ -0,0 +1,47 @@
+require 'spec_helper'
+
+describe Product do
+
+ before :all do
+ FakeWeb.allow_net_connect = false
+ rss_fixture = File.open(File.join(Rails.root,'spec','fixtures','amazon_rss_feed.xml')).read
+ FakeWeb.register_uri(:get, Product::BASE_URL, :body => rss_fixture)
+ end
+
+ context "class methods" do
+
+ it 'has a fetch_all method' do
+ Product.should respond_to(:fetch_all)
+ end
+ it 'returns a collection of products' do
+ Product.fetch_all.each do |p|
+ p.should be_kind_of(Product)
+ end
+ Product.fetch_all.length.should == 5
+ end
+ it 'returns the first product with correct attributes' do
+ prod = Product.fetch_all.first
+ prod.title.should include("Garmin Forerunner")
+ prod.link.should include("http://www.amazon.com/Garmin-Forerunner-Receiver-Heart-Monitor")
+ prod.image_url.should == "http://ecx.images-amazon.com/images/I/51lHg9ZcN7L._SL160_SS160_.jpg"
+ end
+
+
+ end
+
+ context "instance methods" do
+ %w(title link image_url).each do |attr|
+ it "responds to #{attr}" do
+ Product.new.should respond_to(attr)
+ end
+ end
+
+ [:title, :link, :image_url].each do |attr|
+ it "should return the correct #{attr}" do
+ prod = Product.new(attr => 'my attr')
+ prod.send(attr).should == 'my attr'
+ end
+ end
+
+ end
+end
View
2  spec/spec_helper.rb
@@ -25,3 +25,5 @@
# instead of true.
config.use_transactional_fixtures = true
end
+
+FakeWeb.allow_net_connect = false
Please sign in to comment.
Something went wrong with that request. Please try again.