How to understand this Arrays and loops in Ruby? [closed]
Regarding the following code:
update:
(thank you DGM and The Tin Man for recomendation on code and apneadiving for explanation.)
#################
# get main page
#################
rows = doc.xpath('//table[@class="articulos"]/tr[td[5]/p/b]')
i = 0
details = rows.each do |row|
detail = {}
[
[:sku, 'td[3]/text()'],
[:desc, 'td[4]/text()'],
[:stock, "td[5]/p[@title]"],
[:price, 'td[6]/text()']
].each do |name, xpath|
detail[name] = row.at_xpath(xpath).to_s.strip
end
i = i + 1
if detail[:sku] != ""
price = detail[:price].split
if price[1] == "D"
currency = 144
else
currency = 168
开发者_如何学编程 end
stock = detail[:stock].gsub(/[^\d]/, '')
cost = price[0].gsub(",", "").to_f
end
- Is the first
i = 0
,i = i + 1
neccesary? - What syntax is this using?
details = rows.each do |row|
- Why would you want to use
detail = {}
? What is this doing? - I do understand
.each do |name,xpath|
because it is in the order:name
,xpath
. - I guess
detail[name] = row.at_xpath(xpath).to_s.strip
is saying that, if I calldetail[:sku]
, it will make that row at thatxpath
to a string strip.
for what I understand after reading Ruby Poignant Book reading the code I wrote above I can maybe translate to Ruby logic words?. If that is not to insulting for Ruby Experts,haha.
First we have a loop of one method, with an array of arrays, inside another one.
variable = variable.method block |block argument|
variable = {block}
[ array of arrays
[ symbol_1, 'string'],
[ symbol_2, 'string'],
[ symbol_3, 'string'],
[ symbol_4, 'string'],
[ symbol_5, 'string'],
[ symbol_6, 'string']
].method block |symbol, string|
variable[symbol] = variable.method(method argument).method.kernel_method
end block
end block
??? is this correct? now I need to explain that using the method , variable, and arguments actual names in the code, lets see:
The rows variable gets a collect message to collect a row of an array of arrays containing the symbol and xpath and for each block of arrays the row and xpath wil be applied a kernel method strip?
The first i = 0, i = i + 1 (why is that neccesary here?)
it's useless, you're right
details = rows.collect do |row| what syntax is this for? a array? or what class is using from nokogiri? does nokogiri has anything to do with this or is it only RUBY handling an object.
it's sheer ruby style, it loops the elements of what should be an Array.
It also recreates an Array stored in details
containing every element declared at the end of the loop. Here it's detail
detail = {} you see this. why would you want to use this? is this doing something I am not seing?
It initializes detail
to an empty Hash which is then filled in the collect
loop.
I do understand .collect do |name,xpath| because of the top is in order in name , xpath detail[name] = row.at_xpath(xpath).to_s.strip I guess this is saying that if I call detail[:sku] it will make that row at that xpath to a string strip?
Correct.
what does .map do? is there a syntax tutorial in nokogiri page for this?
map
loops all the elements of what should be a Hash. It creates an Array containing links. Duplicates of links are removed from this Array thanks to uniq!
Notice the bang at then end of this function, it means it changes the object.
and why did he had to repeat all data in the #walk trough paginator instead of just using idk some variable?
Don't understand this question.
detail << detail I know this is called a push? so why do anyone want to push some same name haha...
It's a push but it's details << detail
so logic is safe.
To conclude, it's not beautiful code but it seems functional :)
One thing to note, I did this in my own code recently:
detail = {}
[
[:sku, 'td[3]/text()'],
[:desc, 'td[4]/text()'],
[:qty, 'td[5]/text()'],
[:qty2, 'td[5]/p/b/text()'],
[:title, 'td[5]/p/@title'],
[:price, 'td[6]/text()']
].collect do |name, xpath|
detail[name] = row.at_xpath(xpath).to_s.strip
end
The result of the collect statement is thrown way, and the side effect of stuffing things into detail
is the main concern. The collect could be changed to an each, in this case.
detail = {}
[
[:sku, 'td[3]/text()'],
[:desc, 'td[4]/text()'],
[:qty, 'td[5]/text()'],
[:qty2, 'td[5]/p/b/text()'],
[:title, 'td[5]/p/@title'],
[:price, 'td[6]/text()']
].each do |name, xpath|
detail[name] = row.at_xpath(xpath).to_s.strip
end
精彩评论