5

I'm trying to use Nokogiri to grab some data from an XML file, then save it into the database.

The code I'm using is:

def self.import_from_feed(feed)
 doc = Nokogiri::XML(open(feed))

 @products = doc.xpath('/merchantProductFeed/merchant/prod').map do |i| 
   {
     'name' => i.xpath('text/name').inner_text,
     'link' => i.xpath('uri/mLink').inner_text, 
     'description' => i.xpath('text/desc').inner_text,
     'price' => i.xpath('price/buynow').inner_text
   }
 end
end

In Rails' console, I ran Products.import_from_feed(myfeedgoeshere) and got:

[{"price"=>"8.00", "name"=>"BASIC GIRL BOXER", "description"=>"Boxer shorts Elasticated waist with Bench logo Button fly", "link"=>"http://www.bench.co.uk/womenswear/underwear/basic-girl-boxer/GY001X/"}, {"price"=>"10.00", "name"=>"CMTL  PK SPORTY SOCKS", "description"=>"Ankle sockBench logo on sole of each sockContrasting stripe around ankle", "link"=>"http://www.bench.co.uk/womenswear/underwear/cmtl03593-3-pk-sporty-socks/BK014-SK034/"}, {"price"=>"12.00", "name"=>"A PK STRING UNDERWEAR", "description"=>"Plain thong Bench logo along waistband Bench tag on front", "link"=>"http://www.bench.co.uk/womenswear/underwear/a4771-3pk-string-underwear/PK023-BK001-WH001/"}, {"price"=>"8.00", "name"=>"BASIC GIRL BOXER", "description"=>"Boxer shorts Elasticated waist with Bench logo Button fly", "link"=>"http://www.bench.co.uk/womenswear/underwear/basic-girl-boxer/WH001/"}, {"price"=>"45.00", "name"=>"OSPREY TRAINER", "description"=>"Lace up trainers Bench logo on tongue and back of heelBench logo on end of trainer", "link"=>"http://www.bench.co.uk/menswear/footwear/osprey-trainer/WH001-BL081/"}, {"price"=>"45.00", "name"=>"OSPREY TRAINER", "description"=>"Lace up trainers Bench logo on tongue and back of heelBench logo on said of trainer", "link"=>"http://www.bench.co.uk/menswear/footwear/osprey-trainer/WH001-GR128/"}, {"price"=>"90.00", "name"=>"META TRENCH", "description"=>"Vintage look leather bootLace upFabric sidesPull on tab on heel", "link"=>"http://www.bench.co.uk/womenswear/footwear/meta-trench/BK001/"}]
(^ Truncated)

Can someone tell me how I can access elements of the array? Loop through so I can get @products.price, @products.description etc?

Edit: I've tried @products[0], products[0], I've tried printing key/value pairs without any luck.

I'm not asking you to do all the work, I think it's that there are a few concepts at work here - enough to keep me hitting brick walls.

Part 2: Extra Credit!

Based on the selected answer, this should work, right?

 @products.each do |h|
   h.save
 end

I get:

NoMethodError: undefined method `save' for #<Hash:0x10388c7d8>

3 Answers 3

4

Since each element of @products is a hash, you could do this:

@products.each do |h|
  puts "#{h['price']}, #{h['description']}"
end
Sign up to request clarification or add additional context in comments.

5 Comments

Thanks for your answer, just editing now. For clarification - theres a } missing after price, right?
It worked! Thank you so much! I can't vote up your answer (rep <15), I'll come back to it when I can.
@Geoff, thanks for catching the error. I shouldn't try to give answers before my first cup of coffee!
I have a follow up if you wouldn't mind. The way you've presented the data means it can't be stored in the db, right? You convert it to a string almost on the fly? This should work, right? (added to question)
Assuming you have a model called Product, you would need to create/save a new Product with the given values in each hash.
2

Didn't test this but it looks like you have an array of hashes, so first, loop through the array:

@products.each do |product_hash|

Then, for each item (and each item is a hash), get the elements you want: product_hash[:price] or product_hash.price

@products.each do |product_hash|
#Do something with the price
product_hash[:price]
#Do other things...
end

1 Comment

Didn't get a chance to look as got it fixed from above, but thanks very much for taking the time to help!
1

If you like to save those values in a database table say,Product, then just do as below:

@products.each do |product|
    prod = Product.new
    prod.name = product["name"]
    prod.price = product["price"]
    prod.description = product["description"] 
    prod.save
end

you got an error regarding the save keyword because you didn't perform any database operatopn.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.