Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

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
Wolfram Arnold wolframarnold authored
1  Gemfile
View
@@ -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
2  Gemfile.lock
View
@@ -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
2  app/controllers/users_controller.rb
View
@@ -8,7 +8,7 @@ def index
end
def product
-
+ @products = Product.fetch_all
end
def show
27 app/models/product.rb
View
@@ -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
10 app/views/users/product.html.erb
View
@@ -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>
47 spec/models/product_spec.rb
View
@@ -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
2  spec/spec_helper.rb
View
@@ -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.