Created
September 12, 2008 14:41
-
-
Save knewter/10450 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
require 'ostruct' | |
# This model takes a filename for a CSV file intended as a product | |
# database. It will match products against existing products, | |
# creating and deleting products as needed | |
class ProductCsvImporter | |
attr_accessor :file, :products, :headers, :contents, :product_groups_with_set_headers, :header_indices | |
def initialize options | |
@file = options[:file] | |
if options[:contents] | |
@contents = options[:contents] | |
end | |
@product_groups_with_set_headers = [] | |
@header_indices = {} | |
set_products | |
end | |
def set_products | |
if @contents | |
@products = FasterCSV.parse(@contents) | |
else | |
@products = FasterCSV.read(@file) | |
end | |
# 2.times { @products.delete_at(0) } # The files start out with two useless lines...or at least they used to. | |
@headers = @products.delete_at(0).map{|cell| cell.to_s.strip } # this line contains the headers | |
end | |
def set_vendor_active_statuses | |
Vendor.find(:all).each do |v| | |
v.set_active_status | |
v.save | |
end | |
end | |
def create_product_from_row rownum | |
puts "Product ##{rownum}" | |
puts "-----------------" | |
if v = get_vendor(rownum) | |
p = get_product(rownum) | |
set_vendor(p, v) | |
set_content(p, rownum) | |
set_price(p, rownum) | |
set_item_id(p, rownum) | |
set_fiber_types(p, rownum) | |
set_group_num_and_rank(p, rownum) | |
set_weight_and_min_order(p, rownum) | |
["Gauge", "Pattern Type", "Needle Size", "Needle Type", "Needle Length", "Pattern Type", "Accessory Type", "Book Type", "Book Author", "Kit Type"].each do |key| | |
set_key key, p, rownum | |
end | |
[ | |
["Needle Length", "Needle Page Attribute Position-Length"], | |
["Needle Size", "Needle Page Attribute Position-Size"] | |
].each do |arr| | |
key = arr[0] | |
position_key = arr[1] | |
set_keyed_tag_position(key, position_key, rownum) | |
end | |
set_active(p, rownum) | |
set_product_group_header(p, rownum) | |
set_related_products(p, rownum) | |
tag(v, rownum) | |
tag(p, rownum, true) # true removes old tags (so they can change product categories, duh) | |
v.save | |
p.save | |
return true | |
end | |
end | |
def set_keyed_tag_position key, position_key, rownum | |
position = prop(position_key, rownum) | |
key = KeyedTag.find_or_create_by_name_and_key prop(key, rownum), key | |
key.position = position | |
key.save | |
end | |
def get_vendor(rownum) | |
v = Vendor.find_or_create_by_code(prop("Manufacturer", rownum)) | |
v.name = prop("Manufacturer", rownum) | |
v.save | |
puts "Got vendor: #{v.name}" | |
v | |
end | |
def set_content(product, rownum) | |
puts "Description: #{prop('Description', rownum)}" | |
product.description = prop("Description", rownum) | |
end | |
def set_related_products(product, rownum) | |
related_string = prop("Related Products", rownum) | |
related_item_ids = related_string.split(",").map(&:strip) | |
from_id = product.id | |
product.from_product_relationships.map(&:destroy) | |
related_item_ids.each do |item_id| | |
p = Product.find_by_item_id item_id | |
if p | |
to_id = p.id | |
ProductRelationship.find_or_create_by_from_id_and_to_id(from_id, to_id) | |
end | |
end | |
end | |
def get_product(rownum) | |
p = Product.find_or_create_by_sku(prop("UPC", rownum)) | |
set_name(p, rownum) | |
puts "Got product: #{p.name}" | |
p | |
end | |
def set_vendor(product, vendor) | |
product.vendor = vendor | |
end | |
def set_product_group_header(product, rownum) | |
if product.product_group && (!@product_groups_with_set_headers.include?(product.product_group.id)) | |
puts "Product Group header's getting created now..." | |
@product_groups_with_set_headers << product.product_group.id | |
c = Content.find_or_create_by_name product.product_group.content_name | |
attributes = [] | |
attributes_to_check = ["Fiber", "Weight", "Length", "Gauge", "Needle Size", "Project Ideas"] | |
attributes_to_check.each do |c_att| | |
value = prop("Group Name #{c_att}", rownum) | |
attributes << OpenStruct.new(:label => c_att, :value => value) unless value.blank? | |
end | |
mab = Markaby::Builder.new | |
mab.div.product_group_header{ | |
div.attributes{ | |
attributes.each do |attribute| | |
div.attribute{ | |
div.label attribute.label | |
div.value attribute.value | |
} | |
end | |
} | |
div.clear{} | |
} | |
c.contents = mab.to_s | |
c.save | |
end | |
end | |
def set_name(product, rownum) | |
product.name = prop("Description", rownum) | |
end | |
def set_price(product, rownum) | |
product.price = prop("Retail Price", rownum).gsub(/\$/, "").strip | |
end | |
def set_item_id(product, rownum) | |
product.item_id = prop("Item ID", rownum) | |
end | |
def set_active(product, rownum) | |
product.active = active?(rownum) | |
end | |
def set_fiber_types(product, rownum) | |
fiber_types = [] | |
fiber_types << prop("Fiber Type 1", rownum) | |
fiber_types << prop("Fiber Type 2", rownum) | |
fiber_types << prop("Fiber Type 3", rownum) | |
product.tag_with_key 'Fiber Type', fiber_types.join(', ') | |
end | |
def set_key key, product, rownum | |
product.tag_with_key key, prop(key, rownum) | |
end | |
def set_weight_and_min_order(product, rownum) | |
values = prop("Weight:Min. Order", rownum) | |
weight, min_order = get_faux_columns(values) | |
product.weight = weight | |
product.minimum_quantity = min_order | |
end | |
def set_group_num_and_rank(product, rownum) | |
values = prop("Group Num:Rank", rownum) | |
group_num, rank = get_faux_columns(values) | |
unless group_num.nil? || group_num.to_s.blank? | |
group = ProductGroup.find_or_create_by_name(group_num) | |
group.tag_with product.tag_list | |
group.vendor = product.vendor | |
group.description = prop("Group Name", rownum) | |
product.product_group = group | |
group.save | |
end | |
product.rank = rank if rank | |
end | |
def tag(obj, rownum, remove_old=false) | |
tags = prop("Category", rownum) | |
tags += ", " + obj.tag_list unless remove_old | |
obj.tag_with tags | |
end | |
def active?(rownum) | |
prop("Web", rownum) == "Yes" | |
end | |
def create_products | |
([email protected]).each { |i| create_product_from_row i } | |
set_vendor_active_statuses | |
end | |
def get_faux_columns(values) | |
values.split(":") # We use colons to delimit our faux columns | |
end | |
def valid? | |
false | |
end | |
def get_property name, row | |
begin | |
index = get_index(name) | |
if !index | |
raise "No header found to match the name #{name}" | |
end | |
@products[row][index].to_s | |
rescue | |
end | |
end | |
alias prop get_property | |
def get_index name | |
output = @header_indices[name] | |
if !output | |
output = @headers.index(name) | |
@header_indices[name] = output | |
end | |
output | |
end | |
end |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment