Maxim Fedotov Maxim Fedotov - 1 year ago 49
Ruby Question

All variables get updated instead of just one in Ruby/Rspec

I've been testing a method I made in a Module in RSpec. When comparing the results I've realised that the variable from the spec that I pass to the method gets updated. Here is the method being tested

def self.location_compact(locations)
# Find regions
regions ={|l| l.tag == 'Region'}
# Go through region ids and delete locations with that region as a parent (over 5) do |region_id|
if locations.count{|location| location.parent_id == region_id} >= 5
locations.delete_if{|l| l.parent_id == region_id}
end {|l|*' '}.map { |e| "#{e}" }

And here is the spec:

let (:regions) { Office.where(tag: 'Region').sample(2) }
let (:locations) { Office.where(tag: 'MC', parent_id: + regions }

context ".location_compact" do
it "should delete locations that count more than 5 for region" do
result = GIS::GetResponse.location_compact(locations)
expect(result).to eq( {|l|*' '}.map { |e| "#{e}" })
expect(result.size).to eq(6)

I want only the result to contain the updated array, instead locations also gets updated for some reason. I thought that variables in a method are isolated, instead it seems like its updating the memory location itself. Copying locations to another varible updates both of them... Is that I always assumed wrong and that's how Ruby works or am I doing something wrong here?

Answer Source

Most things in ruby are passed by reference, not copy. Array is certainly one of such things. So if you don't want it changed, either dup it or don't use destructive methods on it (your delete_if there).