Ruby on Rails, how to improve the performance of the Hash to Activerecord transformation?

Asked

Viewed 104 times

0

I am having a performance problem when transforming a hash for the activerecord model objects, the hash is returned by Gem Savon after consuming a web service. Benckmark has a relatively high time for Hash size which is 0.25sec for the following test and code below:

Testing

it 'build' do
    @edict_build = EdictBuild.new
    @edict = {
        :edital => {
            :number => "6",
            :year => "2016",
            :status => "ABERTO",
            :items => {
                :item_edital => [
                    {
                        :number => "1",
                        :id_aggregator_property => "0",
                        :payment_detail => {
                            :input_percentage => "5",
                            :deposit_percentage => "5",
                            :time_financing => "180"
                        },
                        :value => {
                            :appraised => "184000"
                        },
                        :dimension => {
                            :lot_size => "150.0",
                            :basic_construction_area => "300.0",
                            :max_construction_area => "300.0"},
                        :properties => {
                            :property => [
                                {
                                    :id => "400000",
                                    :digit => "6",
                                    :destination => "L-3/ADE-COMERCIO, PREST/SERVICO E INDUSTRIA N/POLUENTE (VIDE PUR-122/97, PDL/RA-III E/OU ADM/TAGUATINGA PARA ATIVIDADES N/PERMITIDAS.",
                                    :address => {
                                        :description => "ADE-AGUAS CLARAS   CONJ 16  LT 26",
                                        :city => "AGUAS CLARAS"
                                    },
                                    :physical_data => {
                                        :area_size => "5225.0",
                                        :basic_construction_area => "10450.0",
                                        :max_construction_area => "10450.0"
                                    },
                                    :images => {
                                        :file => {
                                            :id => "203701",
                                            :name => "9.JPG",
                                            :path => "../arquivos/203701.JPG",
                                            :type => "131",
                                            :date => "15/09/2016",
                                            :user_id => "11615"
                                        }
                                    },
                                    :coordinates => {:coordinate => [{:id => "1", :latitude => "-15.895702319854314", :longitude => "-47.77818581470863"}, {:id => "2", :latitude => "-15.895610995614275", :longitude => "-47.778308787644626"}, {:id => "3", :latitude => "-15.895792196798503", :longitude => "-47.77845088500496"}, {:id => "4", :latitude => "-15.89583698700304", :longitude => "-47.778389748193874"}, {:id => "5", :latitude => "-15.895881166800333", :longitude => "-47.77832944381391"}, {:id => "6", :latitude => "-15.895702319854314", :longitude => "-47.77818581470863"}]}
                                }, {
                                    :id => "500000",
                                    :digit => "6",
                                    :destination => "L-3/ADE-COMERCIO, PREST/SERVICO E INDUSTRIA N/POLUENTE (VIDE PUR-122/97, PDL/RA-III E/OU ADM/TAGUATINGA PARA ATIVIDADES N/PERMITIDAS.",
                                    :address => {
                                        :description => "ADE-AGUAS CLARAS   CONJ 16  LT 28",
                                        :city => "AGUAS CLARAS"
                                    },
                                    :physical_data => {
                                        :area_size => "5225.0",
                                        :basic_construction_area => "10450.0",
                                        :max_construction_area => "10450.0"
                                    },
                                    :images => {
                                        :file => {
                                            :id => "203701",
                                            :name => "9.JPG",
                                            :path => "../arquivos/203701.JPG",
                                            :type => "131",
                                            :date => "15/09/2016",
                                            :user_id => "11615"
                                        }
                                    },
                                    :coordinates => {:coordinate => [{:id => "1", :latitude => "-15.892666216804347", :longitude => "-47.78230611817888"}, {:id => "2", :latitude => "-15.892556225483684", :longitude => "-47.78245426999193"}, {:id => "3", :latitude => "-15.892735448024855", :longitude => "-47.782596339886844"}, {:id => "4", :latitude => "-15.892845440365102", :longitude => "-47.782448187132346"}, {:id => "5", :latitude => "-15.892666216804347", :longitude => "-47.78230611817888"}]}
                                }]
                        }
                    }, {
                        :number => "2",
                        :id_aggregator_property => "0",
                        :payment_detail => {
                            :input_percentage => "5",
                            :deposit_percentage => "5",
                            :time_financing => "180"
                        },
                        :value => {
                            :appraised => "284000"
                        },
                        :dimension => {
                            :lot_size => "150.0",
                            :basic_construction_area => "300.0",
                            :max_construction_area => "300.0"},
                        :properties => {
                            :property => [
                                {
                                    :id => "600000",
                                    :digit => "6",
                                    :destination => "L-3/ADE-COMERCIO, PREST/SERVICO E INDUSTRIA N/POLUENTE (VIDE PUR-122/97, PDL/RA-III E/OU ADM/TAGUATINGA PARA ATIVIDADES N/PERMITIDAS.",
                                    :address => {
                                        :description => "ADE-AGUAS CLARAS   CONJ 16  LT 27",
                                        :city => "TAGUATINGA"
                                    },
                                    :physical_data => {
                                        :area_size => "5225.0",
                                        :basic_construction_area => "10450.0",
                                        :max_construction_area => "10450.0"
                                    },
                                    :images => {
                                        :file => {
                                            :id => "203701",
                                            :name => "9.JPG",
                                            :path => "../arquivos/203701.JPG",
                                            :type => "131",
                                            :date => "15/09/2016",
                                            :user_id => "11615"
                                        }
                                    },
                                    :coordinates => {:coordinate => [{:id => "1", :latitude => "-15.89280370700262", :longitude => "-47.78212092609189"}, {:id => "2", :latitude => "-15.892666216804347", :longitude => "-47.78230611817888"}, {:id => "3", :latitude => "-15.892845440365102", :longitude => "-47.782448187132346"}, {:id => "4", :latitude => "-15.892982930694034", :longitude => "-47.78226299501928"}, {:id => "5", :latitude => "-15.89280370700262", :longitude => "-47.78212092609189"}]}
                                }, {
                                    :id => "700000",
                                    :digit => "6",
                                    :destination => "L-3/ADE-COMERCIO, PREST/SERVICO E INDUSTRIA N/POLUENTE (VIDE PUR-122/97, PDL/RA-III E/OU ADM/TAGUATINGA PARA ATIVIDADES N/PERMITIDAS.",
                                    :address => {
                                        :description => "ADE-AGUAS CLARAS   CONJ 16  LT 29",
                                        :city => "TAGUATINGA"
                                    },
                                    :physical_data => {
                                        :area_size => "5225.0",
                                        :basic_construction_area => "10450.0",
                                        :max_construction_area => "10450.0"
                                    },
                                    :images => {
                                        :file => {
                                            :id => "203701",
                                            :name => "9.JPG",
                                            :path => "../arquivos/203701.JPG",
                                            :type => "131",
                                            :date => "15/09/2016",
                                            :user_id => "11615"
                                        }
                                    },
                                    :coordinates => {:coordinate => [{:id => "1", :latitude => "-15.894039601604181", :longitude => "-47.77938217219249"}, {:id => "2", :latitude => "-15.893944913117782", :longitude => "-47.77951135930087"}, {:id => "3", :latitude => "-15.894122816497235", :longitude => "-47.779652378734916"}, {:id => "4", :latitude => "-15.89421827303992", :longitude => "-47.77952380035496"}, {:id => "5", :latitude => "-15.894039601604181", :longitude => "-47.77938217219249"}]}
                                }
                            ]
                        }
                    }
                ]
            }
        }
    }

    Benchmark.bm do |x|
      x.report { @response = @edict_build.generate(@edict) }
    end
    expect(@response.number).to eq('6')
end

Code

class EdictBuild

  def generate(response)
    edict = Edict.new
    if response[:control].nil?
      edict.year = response[:edital][:year]
      edict.number=response[:edital][:number]
      edict.status=response[:edital][:status]
      unless response[:edital].nil?
        convert_single_hash_to_array(response[:edital][:items][:item_edital]).each do |item_edital|
          properties = []
          unless item_edital[:properties].nil?
            convert_single_hash_to_array(item_edital[:properties][:property]).each do |property|
              geolocations = []
              unless property[:coordinates].nil?
                convert_single_hash_to_array(property[:coordinates][:coordinate]).each do |coordinate|
                  geolocations << Geolocation.new(latitude: coordinate[:latitude], longitude: coordinate[:longitude])
                end
              end
              photos = []
              unless property[:images].nil?
                photos << Photo.new(name: convert_single_hash_to_array(property[:images][:file])[0][:name], url: convert_single_hash_to_array(property[:images][:file])[0][:path])
              else
                photos << Photo.new(name: "Sem foto", url: "/images/sem-foto.gif")
              end
              destination = Destination.new(description: property[:destination])
              city = City.new(description: property[:address][:city])
              address = Address.new(description: property[:address][:description], city: city)
              properties << Property.new(
                  number: property[:id],
                  digit: property[:digit],
                  area_size: property[:physical_data][:area_size],
                  area_basic: property[:physical_data][:basic_construction_area],
                  area_maximum: property[:physical_data][:max_construction_area],
                  address: address,
                  geolocations: geolocations,
                  destination: destination,
                  photos: photos
              )
            end
          end
          edict.items << Item.new(
              number: item_edital[:number],
              price: item_edital[:value][:appraised],
              percentage_entry: item_edital[:payment_detail][:input_percentage],
              percentage_bail: item_edital[:payment_detail][:deposit_percentage],
              financing_max: item_edital[:payment_detail][:time_financing],
              properties: properties
          )

        end
      end
    end
    return edict
  end

  private

  def convert_single_hash_to_array(element)
    if element.is_a? Array
      return element
    else
      return Array.new << element
    end
  end

end

Could someone help me leave this transformation to performatica?

1 answer

0

Apparently you have several entities in the consumed Hash. If it comes from a JSON, AC has a method that does all these assignments you’re doing on EdictBuild#generate.

Model.new.from_json (http://api.rubyonrails.org/classes/ActiveModel/Serializers/JSON.html#method-i-from_json)

So maybe you dividing Hash into entities and doing something like below will improve performance:

Edict.new.from_json(edict_hash)
geolocation = Geolocation.new.from_json(geolocation_hash)
#etc

Then you would make the associations according to business logic.

Browser other questions tagged

You are not signed in. Login or sign up in order to post.