I am looping through the array self.sisters as below:
brothers_in_law = []
self.sisters&.each do |sister|
brothers_in_law << sister.spouse (if !sister.spouse.nil?)
end
How can I write it in the ruby way and also in one line?
I am looping through the array self.sisters as below:
brothers_in_law = []
self.sisters&.each do |sister|
brothers_in_law << sister.spouse (if !sister.spouse.nil?)
end
How can I write it in the ruby way and also in one line?
In ruby, a rule of thumb is: if you have an each loop that is used for anything other than simply iterating the elements, there is 99% chance there is a better method.
brothers_in_law = sisters.map(&:spouse).reject(&:nil?)
# or
brothers_in_law = sisters.map(&:spouse).compact
# or in ruby 2.7+
brothers_in_law = sisters.filter_map(&:spouse)
sisters.sisters array is nil?sisters ||= [] before this line.brothers_in_law = self.sisters&.map(&:spouse).reject(&:nil?)brothers_in_law as nil if sisters is nil. Anyhow, the matter of this nil check is orthogonal to the one-line form of your loop.Testing:
sister = OpenStruct.new(spouse: "1")
sister1 = OpenStruct.new(spouse: "2")
sister2 = OpenStruct.new(spouse: nil)
sisters = [sister, sister1, sister2, nil]
brothers_in_law = []
brothers_in_law.concat sisters.compact&.map(&:spouse).compact unless sisters.nil?
=> ["1", "2"]
The compact calls remove the nil values on both sisters and their spouses, so only the spouse objects that exist are returned.
brothers_in_law array already exists then I can do this right? brothers_in_law + sisters.compact&.map(&:spouse).compactconcat so you don't create a multidimensional array and you can append to it multiple times: brothers_in_law.concat sisters.compact&.map(&:spouse).compactbrothers_in_law.concat sisters.compact&.map(&:spouse).compact in the method if I should return brothers_in_law then should I write brothers_in_law after the above line or is the above line enough to return the array?sisters to be nil.