diff --git a/Gemfile b/Gemfile
index d4fbf7c0..fc257b3c 100644
--- a/Gemfile
+++ b/Gemfile
@@ -36,6 +36,8 @@ gem 'jbuilder', '~> 2.5'
# Reduces boot times through caching; required in config/boot.rb
gem 'bootsnap', '>= 1.1.0', require: false
+gem 'faraday'
+
group :development, :test do
# Call 'byebug' anywhere in the code to stop execution and get a debugger console
gem 'byebug', platforms: [:mri, :mingw, :x64_mingw]
@@ -54,5 +56,6 @@ group :development do
end
+
# Windows does not include zoneinfo files, so bundle the tzinfo-data gem
gem 'tzinfo-data', platforms: [:mingw, :mswin, :x64_mingw, :jruby]
diff --git a/Gemfile.lock b/Gemfile.lock
index 9c8920e9..55d2c8f2 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -72,6 +72,10 @@ GEM
diff-lcs (1.4.4)
erubi (1.10.0)
execjs (2.8.1)
+ faraday (2.6.0)
+ faraday-net_http (>= 2.0, < 3.1)
+ ruby2_keywords (>= 0.0.4)
+ faraday-net_http (3.0.1)
ffi (1.15.4)
globalid (0.5.2)
activesupport (>= 5.0)
@@ -92,9 +96,13 @@ GEM
matrix (0.4.2)
method_source (1.0.0)
mini_mime (1.1.2)
+ mini_portile2 (2.6.1)
minitest (5.14.4)
msgpack (1.4.2)
nio4r (2.5.8)
+ nokogiri (1.12.5)
+ mini_portile2 (~> 2.6.1)
+ racc (~> 1.4)
nokogiri (1.12.5-arm64-darwin)
racc (~> 1.4)
pg (1.2.3)
@@ -153,6 +161,7 @@ GEM
rspec-mocks (~> 3.10)
rspec-support (~> 3.10)
rspec-support (3.10.2)
+ ruby2_keywords (0.0.5)
ruby_dep (1.5.0)
sass (3.7.4)
sass-listen (~> 4.0.0)
@@ -199,12 +208,14 @@ GEM
PLATFORMS
arm64-darwin-20
+ ruby
DEPENDENCIES
bootsnap (>= 1.1.0)
byebug
capybara
coffee-rails (~> 4.2)
+ faraday
jbuilder (~> 2.5)
listen (>= 3.0.5, < 3.2)
pg (>= 0.18, < 2.0)
diff --git a/app/controllers/items_controller.rb b/app/controllers/items_controller.rb
new file mode 100644
index 00000000..976da56a
--- /dev/null
+++ b/app/controllers/items_controller.rb
@@ -0,0 +1,9 @@
+class ItemsController < ApplicationController
+ def index
+ @items = ItemsFacade.get_items
+ end
+
+ def show
+ @item = ItemsFacade.get_item(params[:id])
+ end
+end
\ No newline at end of file
diff --git a/app/controllers/merchants_controller.rb b/app/controllers/merchants_controller.rb
new file mode 100644
index 00000000..fc11654f
--- /dev/null
+++ b/app/controllers/merchants_controller.rb
@@ -0,0 +1,9 @@
+class MerchantsController < ApplicationController
+ def index
+ @merchants = MerchantsFacade.get_merchants
+ end
+
+ def show
+ @merchant = MerchantsFacade.get_merchant(params[:id])
+ end
+end
\ No newline at end of file
diff --git a/app/facades/items_facade.rb b/app/facades/items_facade.rb
new file mode 100644
index 00000000..93c5417b
--- /dev/null
+++ b/app/facades/items_facade.rb
@@ -0,0 +1,20 @@
+class ItemsFacade
+ def self.get_merchant_items(merchant_id)
+ items_data = ItemsService.get_merchant_items(merchant_id)[:data]
+ items_data.map do |item_data|
+ Item.new(item_data)
+ end
+ end
+
+ def self.get_item(item_id)
+ item_data = ItemsService.get_item(item_id)[:data]
+ Item.new(item_data)
+ end
+
+ def self.get_items
+ items_data = ItemsSerice.get_items[:data]
+ items_data.map do |item_data|
+ Item.new(item_data)
+ end
+ end
+end
\ No newline at end of file
diff --git a/app/facades/merchants_facade.rb b/app/facades/merchants_facade.rb
new file mode 100644
index 00000000..e354b2d2
--- /dev/null
+++ b/app/facades/merchants_facade.rb
@@ -0,0 +1,13 @@
+class MerchantsFacade
+ def self.get_merchants
+ merchants_data = MerchantsService.get_merchants[:data]
+ merchants_data.map do |merchant_data|
+ Merchant.new(merchant_data)
+ end
+ end
+
+ def self.get_merchant(merchant_id)
+ merchant_data = MerchantsService.get_merchant(merchant_id)[:data]
+ Merchant.new(merchant_data)
+ end
+end
\ No newline at end of file
diff --git a/app/poros/item.rb b/app/poros/item.rb
new file mode 100644
index 00000000..167f463d
--- /dev/null
+++ b/app/poros/item.rb
@@ -0,0 +1,15 @@
+class Item
+ attr_reader :id, :name, :description, :unit_price
+
+ def initialize(item_data)
+ @id = item_data[:id].to_i
+ @name = item_data[:attributes][:name]
+ @description = item_data[:attributes][:description]
+ @unit_price = item_data[:attributes][:unit_price]
+ @merchant_id = item_data[:attributes][:merchant_id]
+ end
+
+ def merchant
+ MerchantsFacade.get_merchant(@merchant_id)
+ end
+end
\ No newline at end of file
diff --git a/app/poros/merchant.rb b/app/poros/merchant.rb
new file mode 100644
index 00000000..ef50912e
--- /dev/null
+++ b/app/poros/merchant.rb
@@ -0,0 +1,12 @@
+class Merchant
+ attr_reader :id, :name, :items
+
+ def initialize(merchant_data)
+ @id = merchant_data[:id].to_i
+ @name = merchant_data[:attributes][:name]
+ end
+
+ def items
+ ItemsFacade.get_merchant_items(@id)
+ end
+end
\ No newline at end of file
diff --git a/app/services/items_service.rb b/app/services/items_service.rb
new file mode 100644
index 00000000..640a2963
--- /dev/null
+++ b/app/services/items_service.rb
@@ -0,0 +1,22 @@
+class ItemsService
+ def self.get_merchant_items(merchant_id)
+ response = conn.get("/api/v1/merchants/#{merchant_id}/items")
+ JSON.parse(response.body, symbolize_names: true)
+ end
+
+ def self.get_items
+ response = conn.get("/api/v1/items")
+ JSON.parse(response.body, symbolize_names: true)
+ end
+
+ def self.get_item(item_id)
+ response = conn.get("/api/v1/items/#{item_id}")
+ JSON.parse(response.body, symbolize_names: true)
+ end
+
+ private
+
+ def self.conn
+ Faraday.new(url: "http://localhost:3000")
+ end
+end
\ No newline at end of file
diff --git a/app/services/merchants_service.rb b/app/services/merchants_service.rb
new file mode 100644
index 00000000..aac2b005
--- /dev/null
+++ b/app/services/merchants_service.rb
@@ -0,0 +1,18 @@
+class MerchantsService
+
+ def self.get_merchants
+ response = conn.get("/api/v1/merchants")
+ JSON.parse(response.body, symbolize_names: true)
+ end
+
+ def self.get_merchant(merchant_id)
+ response = conn.get("/api/v1/merchants/#{merchant_id}")
+ JSON.parse(response.body, symbolize_names: true)
+ end
+
+ private
+
+ def self.conn
+ Faraday.new(url: "http://localhost:3000/")
+ end
+end
\ No newline at end of file
diff --git a/app/views/items/index.html.erb b/app/views/items/index.html.erb
new file mode 100644
index 00000000..e69de29b
diff --git a/app/views/items/show.html.erb b/app/views/items/show.html.erb
new file mode 100644
index 00000000..e69de29b
diff --git a/app/views/merchants/index.html.erb b/app/views/merchants/index.html.erb
new file mode 100644
index 00000000..890c5386
--- /dev/null
+++ b/app/views/merchants/index.html.erb
@@ -0,0 +1,5 @@
+
+ <% @merchants.each do |merchant| %>
+ - <%= link_to merchant.name, merchant_path(merchant.id) %>
+ <% end %>
+
diff --git a/app/views/merchants/show.html.erb b/app/views/merchants/show.html.erb
new file mode 100644
index 00000000..a54f3fe6
--- /dev/null
+++ b/app/views/merchants/show.html.erb
@@ -0,0 +1,6 @@
+<%= @merchant.name %>
+
+ <% @merchant.items.each do |item| %>
+ - <%= link_to item.name, item_path(item.id) %>
+ <% end %>
+
\ No newline at end of file
diff --git a/config/routes.rb b/config/routes.rb
index 787824f8..92725056 100644
--- a/config/routes.rb
+++ b/config/routes.rb
@@ -1,3 +1,5 @@
Rails.application.routes.draw do
# For details on the DSL available within this file, see http://guides.rubyonrails.org/routing.html
+ resources :merchants, only: [:index, :show]
+ resources :items, only: [:index, :show]
end
diff --git a/db/schema.rb b/db/schema.rb
new file mode 100644
index 00000000..2611543b
--- /dev/null
+++ b/db/schema.rb
@@ -0,0 +1,18 @@
+# This file is auto-generated from the current state of the database. Instead
+# of editing this file, please use the migrations feature of Active Record to
+# incrementally modify your database, and then regenerate this schema definition.
+#
+# Note that this schema.rb definition is the authoritative source for your
+# database schema. If you need to create the application database on another
+# system, you should be using db:schema:load, not running all the migrations
+# from scratch. The latter is a flawed and unsustainable approach (the more migrations
+# you'll amass, the slower it'll run and the greater likelihood for issues).
+#
+# It's strongly recommended that you check this file into your version control system.
+
+ActiveRecord::Schema.define(version: 0) do
+
+ # These are extensions that must be enabled in order to support this database
+ enable_extension "plpgsql"
+
+end
diff --git a/spec/features/merchants/index_spec.rb b/spec/features/merchants/index_spec.rb
new file mode 100644
index 00000000..d69ab875
--- /dev/null
+++ b/spec/features/merchants/index_spec.rb
@@ -0,0 +1,28 @@
+require 'rails_helper'
+
+RSpec.describe "merchants index page" do
+
+ before :each do
+ @merchants = MerchantsFacade.get_merchants
+ end
+
+ it 'lists all the merchants' do
+ visit merchants_path
+
+ @merchants.each do |merchant|
+ expect(page).to have_content(merchant.name)
+ end
+ end
+
+ it 'each merchant name is a link to their show page' do
+ visit merchants_path
+
+ @merchants.each do |merchant|
+ expect(page).to have_link(merchant.name)
+ end
+
+ click_link @merchants.first.name
+
+ expect(current_path).to eq(merchant_path(@merchants.first.id))
+ end
+end
\ No newline at end of file
diff --git a/spec/features/merchants/show_spec.rb b/spec/features/merchants/show_spec.rb
new file mode 100644
index 00000000..2ff525f6
--- /dev/null
+++ b/spec/features/merchants/show_spec.rb
@@ -0,0 +1,22 @@
+require 'rails_helper'
+
+RSpec.describe "merchants show page" do
+
+ before :each do
+ @merchant = MerchantsFacade.get_merchants.first
+ visit merchant_path(@merchant.id)
+ end
+
+ it 'shows the merchants name' do
+ expect(page).to have_content(@merchant.name)
+ end
+
+ it 'shows the merchant items as links to their show pages' do
+ @merchant.items.each do |item|
+ expect(page).to have_link(item.name)
+ end
+ first_item = @merchant.items.first
+ click_link first_item.name
+ expect(current_path).to eq(item_path(first_item.id))
+ end
+end
\ No newline at end of file
diff --git a/spec/fixtures/files/merchants_response.json b/spec/fixtures/files/merchants_response.json
new file mode 100644
index 00000000..71ee1473
--- /dev/null
+++ b/spec/fixtures/files/merchants_response.json
@@ -0,0 +1 @@
+{"data":[{"id":"1","type":"merchant","attributes":{"name":"Schroeder-Jerde"}},{"id":"2","type":"merchant","attributes":{"name":"Klein, Rempel and Jones"}},{"id":"3","type":"merchant","attributes":{"name":"Willms and Sons"}},{"id":"4","type":"merchant","attributes":{"name":"Cummings-Thiel"}},{"id":"5","type":"merchant","attributes":{"name":"Williamson Group"}},{"id":"6","type":"merchant","attributes":{"name":"Williamson Group"}},{"id":"7","type":"merchant","attributes":{"name":"Bernhard-Johns"}},{"id":"8","type":"merchant","attributes":{"name":"Osinski, Pollich and Koelpin"}},{"id":"9","type":"merchant","attributes":{"name":"Hand-Spencer"}},{"id":"10","type":"merchant","attributes":{"name":"Bechtelar, Jones and Stokes"}},{"id":"11","type":"merchant","attributes":{"name":"Pollich and Sons"}},{"id":"12","type":"merchant","attributes":{"name":"Kozey Group"}},{"id":"13","type":"merchant","attributes":{"name":"Tillman Group"}},{"id":"14","type":"merchant","attributes":{"name":"Dicki-Bednar"}},{"id":"15","type":"merchant","attributes":{"name":"Adams-Kovacek"}},{"id":"16","type":"merchant","attributes":{"name":"Bosco, Howe and Davis"}},{"id":"17","type":"merchant","attributes":{"name":"Ullrich-Moen"}},{"id":"18","type":"merchant","attributes":{"name":"Koepp LLC"}},{"id":"19","type":"merchant","attributes":{"name":"Brown Inc"}},{"id":"20","type":"merchant","attributes":{"name":"Schulist, Wilkinson and Leannon"}}]}
\ No newline at end of file
diff --git a/spec/poros/item_spec.rb b/spec/poros/item_spec.rb
new file mode 100644
index 00000000..711587a6
--- /dev/null
+++ b/spec/poros/item_spec.rb
@@ -0,0 +1,7 @@
+require 'rails_helper'
+
+RSpec.describe Item do
+ before :each do
+
+ end
+end
\ No newline at end of file
diff --git a/spec/poros/merchant_spec.rb b/spec/poros/merchant_spec.rb
new file mode 100644
index 00000000..2ea490d9
--- /dev/null
+++ b/spec/poros/merchant_spec.rb
@@ -0,0 +1,16 @@
+require 'rails_helper'
+
+RSpec.describe Merchant do
+ before :each do
+ merchants = JSON.parse(file_fixture("merchants_response.json").read, symbolize_names: true)
+ merchant_data = merchants[:data].first
+
+ @merchant = Merchant.new(merchant_data)
+ end
+
+ it 'exists and has attributes' do
+ expect(@merchant).to be_instance_of(Merchant)
+ expect(@merchant.id).to eq(1)
+ expect(@merchant.name).to eq("Schroeder-Jerde")
+ end
+end
\ No newline at end of file
diff --git a/spec/services/merchants_service_spec.rb b/spec/services/merchants_service_spec.rb
new file mode 100644
index 00000000..642dd541
--- /dev/null
+++ b/spec/services/merchants_service_spec.rb
@@ -0,0 +1,34 @@
+require 'rails_helper'
+
+RSpec.describe MerchantsService do
+ it 'returns a list of the first 20 merchants' do
+ merchants = MerchantsService.get_merchants
+
+ expect(merchants).to be_a(Hash)
+ expect(merchants).to have_key(:data)
+ expect(merchants[:data]).to be_an(Array)
+
+ merchants[:data].each do |merchant|
+ expect(merchant).to have_key(:id)
+ expect(merchant[:type]).to eq("merchant")
+ expect(merchant).to have_key(:attributes)
+ expect(merchant[:attributes]).to have_key(:name)
+ expect(merchant[:attributes][:name]).to be_a(String)
+ end
+ end
+
+ it 'returns a single merchant' do
+ first_merchant_id = MerchantsService.get_merchants[:data].first[:id]
+
+ first_merchant = MerchantsService.get_merchant(first_merchant_id)
+
+ expect(first_merchant).to be_a(Hash)
+ expect(first_merchant).to have_key(:data)
+ expect(first_merchant[:data]).to be_a(Hash)
+ expect(first_merchant[:data][:id]).to eq(first_merchant_id)
+ expect(first_merchant[:data][:type]).to eq("merchant")
+ expect(first_merchant[:data][:attributes]).to be_a(Hash)
+ expect(first_merchant[:data][:attributes]).to have_key(:name)
+ expect(first_merchant[:data][:attributes][:name]).to be_a(String)
+ end
+end
\ No newline at end of file