Path: csiph.com!fu-berlin.de!uni-berlin.de!individual.net!not-for-mail From: Robert Klemme Newsgroups: comp.lang.ruby Subject: Re: extract into a method - struggling to abstract Date: Sun, 3 Jul 2016 18:52:29 +0200 Lines: 116 Message-ID: References: Mime-Version: 1.0 Content-Type: text/plain; charset=utf-8; format=flowed Content-Transfer-Encoding: 7bit X-Trace: individual.net T5SC+Wen3MBw5X1QkyY6Vgua/0eu5P/zEnLd0fWqaxSrOIQHA= Cancel-Lock: sha1:+XV9OoIjJ1kz36EcVi3xLqnqNIk= User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:38.0) Gecko/20100101 Thunderbird/38.8.0 In-Reply-To: Xref: csiph.com comp.lang.ruby:7272 On 03.07.2016 16:01, Sayth Renshaw wrote: > Hi > > I have working code that I have currently loops through an example returning matches via nokogiri module. > > This works > > require 'nokogiri' > require 'awesome_print' > > @doc = Nokogiri::XML(File.open('/home/sayth/data/20160702RHIL0.xml')) You are not closing the file here. Better: @doc = File.open('/home/sayth/data/20160702RHIL0.xml', 'rb') do |io| Nokogiri::XML(io) end > @doc.search('race').map do |race| > nominations = race.search('nomination') > .map do |nomination| > { > number: nomination['number'].to_i, > id: nomination['id'].to_i, > horse: nomination['horse'].to_s, > age: nomination['age'].to_i, > sex: nomination['sex'].to_s, > colour: /\W(.+?)\d?\s/.match(nomination['description'].to_s)[1] > } > end > > a = { race['id'].to_i => nominations } > ap a > end > > _______________________________________________________________________________ > > So at this point I know that I need to replicate this for 6 sections in total, logically to me then I want to abstract especially the middle. > > { > number: nomination['number'].to_i, > id: nomination['id'].to_i, > horse: nomination['horse'].to_s, > age: nomination['age'].to_i, > sex: nomination['sex'].to_s, > colour: /\W(.+?)\d?\s/.match(nomination['description'].to_s)[1] > } > > and substitute a variable into race.search('nomination') this to replace the word nomination and to then replace all 'nomination' in the above section. I would replace the variable name "nomination" by something more abstract, e.g. "node".irb > So this is what I have done. > > data = %w(number id horse age sex colour) > > def extract_value(path_id, data) > @doc.search('race').map do |race| > puts path_id > nominations = race.search(path_id) > .map do | | > data > end > values = { race['id'].to_i => nominations } > ap values > return values > end > end > > extract_value('nomination', data) I think you are almost there: data = %w(number id horse age sex colour) def extract_value(path_id, data) @doc.search('race').map do |race| puts path_id extracted_data = race.search(path_id).map do |node| {}.tap do |hash| data.each {|d| hash[d.to_sym] = Integer(node[d])} end end values = { race['id'].to_i => extracted_data } ap values # next line will prematurely return from the method, # do you want that? return values end end extract_value('nomination', data) > _______________________________________________________________________________ > > The main part I cannot wrap my head around is how to get these sections in without replicating it in the definition. > > number: nomination['number'].to_i, > > How can I better abstract this out? See above. Is this what you intended? Kind regards robert -- remember.guy do |as, often| as.you_can - without end http://blog.rubybestpractices.com/