Skip to content

Commit 4e6c7de

Browse files
committed
refactors Menards driver
1 parent 64ee3d1 commit 4e6c7de

24 files changed

+1230
-464
lines changed

3

-222
This file was deleted.

app/connectors/base_connector.rb

+2-10
Original file line numberDiff line numberDiff line change
@@ -8,9 +8,8 @@ def initialize(driver)
88
@driver = driver
99
end
1010

11-
def append_url_to_listing(sku, url, abbrev: '', force_update: false)
12-
return unless valid_options?(abbrev, force_update)
13-
Listing.send("append_#{abbrev}_url", sku, url, force_update)
11+
def store_attrs(sku, attrs)
12+
Listing.append_vendor_attrs(sku, attrs)
1413
end
1514

1615
private
@@ -25,11 +24,4 @@ def validate_driver(driver)
2524
end
2625
end
2726

28-
# Validates options keyword args
29-
def valid_options?(abbrev, force_update)
30-
abbrev.present? &&
31-
Listing::CHANNELS.include?(abbrev) &&
32-
[true, false].include?(force_update)
33-
end
34-
3527
end

app/connectors/menards.rb

+23-9
Original file line numberDiff line numberDiff line change
@@ -4,21 +4,35 @@ class Menards < BaseConnector
44

55
BASE_URL = 'http://www.menards.com/main/'
66

7+
def process_listings(nodes)
8+
nodes.each_with_index do |node, index|
9+
id = node[0]
10+
sku = node[1]
11+
next if Listing.record_exists?(sku)
12+
sleep(4) if index % 20 == 0
13+
puts "=== starting id: #{id} | iteration: #{index}"
14+
sleep(rand(0.1...3))
15+
visit_product_page(id)
16+
fetch_product_attributes(id)
17+
Listing.append_menards_url(@listing_attrs[:vendor_sku],
18+
@listing_attrs[:vendor_url])
19+
end
20+
end
21+
722
def visit_product_page(menards_id)
823
driver.visit("#{BASE_URL}p-#{menards_id}.html") unless menards_id.nil?
24+
raise PageNotFoundError if page_not_found?
925
end
1026

1127
def fetch_product_attributes(menards_id)
1228
return if page_not_found?
13-
@listing_attrs = { url: driver.current_url,
14-
vendor_id: menards_id,
15-
vendor_sku: driver.doc.at('p.itemModelSku').children.last.text.strip,
16-
title: driver.doc.at('.itemCenterContent span h2').text,
17-
price: driver.doc.at('#totalItemPrice').children.first.text.strip }
18-
end
19-
20-
def store_product_attributes(listing_attrs)
21-
Listing.append_attrs(listing_attrs)
29+
@listing_attrs =
30+
{ vendor: 'menards',
31+
vendor_url: driver.current_url,
32+
vendor_id: menards_id,
33+
vendor_sku: driver.doc.at('p.itemModelSku').children.last.text.strip,
34+
vendor_title: driver.doc.at('.itemCenterContent span h2').text,
35+
vendor_price: driver.doc.at('#totalItemPrice').children.first.text.strip }
2236
end
2337

2438
private

app/models/listing.rb

+21-31
Original file line numberDiff line numberDiff line change
@@ -2,46 +2,36 @@
22
# pertaining to a retailing channel
33
class Listing < ActiveRecord::Base
44

5-
validates_presence_of :sku
6-
validate :channel_urls_format
5+
VENDORS = %W( hd menards houzz overstock lowes build hmb wayfair )
76

8-
CHANNELS = %w( hd menards overstock lowes build hmb wayfair houzz )
7+
validates_presence_of :sku
8+
serialize :vendors, HashSerializer
9+
store_accessor :vendors, :hd, :wayfair, :lowes, :menards, :hmb, :houzz, :overstock, :build
910

10-
def available_channel_urls
11-
channel_names = CHANNELS.map { |channel| "#{channel}_url" }
12-
channel_names.map do |name|
13-
attributes.fetch_values(name)
14-
end.flatten.compact
15-
end
16-
17-
CHANNELS.each do |channel_name|
18-
define_singleton_method("append_#{channel_name}_url") do |sku, url, force_update|
19-
listing = find_by(sku: sku)
20-
puts "=== SKU #{sku}"
21-
puts "--- url #{url}"
22-
puts "--- force_update #{force_update}"
23-
if force_update
24-
listing.update_attributes!("#{channel_name}_url": url)
25-
elsif listing
26-
puts '--- listing already exists'
27-
return
28-
else
29-
puts '--- updating listing'
30-
create!(sku: sku, "#{channel_name}_url":url)
31-
end
32-
end
11+
def self.append_vendor_attrs(sku, attrs)
12+
listing = find_by(sku: sku) || new(sku: sku)
13+
listing.fetch_vendor_data(attrs)
14+
listing.save!
3315
end
3416

3517
def self.record_exists?(sku)
3618
find_by(sku: sku).present?
3719
end
3820

21+
def fetch_vendor_data(attrs)
22+
vendors[attrs[:vendor]].merge!({
23+
id: attrs[:vendor_id],
24+
sku: attrs[:vendor_sku],
25+
url: attrs[:vendor_url],
26+
title: attrs[:vendor_title],
27+
price: attrs[:vendor_price] }).to_json
28+
end
3929

40-
private
41-
42-
def channel_urls_format
43-
if available_channel_urls.any? { |url| url.scan(URI.regexp).empty? }
44-
errors.add(:base, message: 'malformed url')
30+
VENDORS.each do |vendor|
31+
define_singleton_method("append_#{vendor}_url") do |sku, url|
32+
listing = find_by(sku: sku) || new(sku: sku)
33+
listing["#{vendor}_url"] = url
34+
listing.save!
4535
end
4636
end
4737

app/parsers/csv_feed_parser.rb

+8
Original file line numberDiff line numberDiff line change
@@ -17,4 +17,12 @@ def self.stringify_skus(skus)
1717
skus.join(' ')
1818
end
1919

20+
def self.fetch_menards_skus(file_path)
21+
nodes = {}
22+
CSV.foreach(file_path) do |row|
23+
nodes[row[0]] = row[1]
24+
end
25+
nodes
26+
end
27+
2028
end

app/serializers/hash_serializer.rb

+11
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,11 @@
1+
class HashSerializer
2+
3+
def self.dump(hash)
4+
hash.to_json
5+
end
6+
7+
def self.load(hash)
8+
(hash || {}).with_indifferent_access
9+
end
10+
11+
end

0 commit comments

Comments
 (0)