-1

I am building a rails app that i need to update totals of managers each time someone is added. The method that updates the totals to me is looking really bad there is a lot of repetition going on that could be solved with a bit of metaprogramming. so i have a private method being called on before_save called update_totals

So we categorize them like this there is four races, african, coloured, indian and white there are three kinds of managements senior, middle and junior and then obviously two kinds of genders male and female. I need to be able to assign each possible variation of the three so i end up with something like this.

self.number_of_african_female_senior_managers = managers.native.african.female.senior.count
self.number_of_african_male_senior_managers = managers.native.african.male.senior.count
self.number_of_african_female_middle_managers = managers.native.african.female.middle.count
self.number_of_african_male_middle_managers = managers.native.african.male.middle.count
self.number_of_african_female_junior_managers = managers.native.african.female.junior.count
self.number_of_african_male_junior_managers = managers.native.african.male.junior.count

I would need to do this for each race. So i thought of building them dynamically and then having them assigned.

So something like this:

["african", "indian", "coloured", "white"].each do |race|
  ["senior","middle","junior"].each do |management_type|
    ["male","Female"].each do |gender|
      "number_of_#{race}_#{gender}_#{management_type}_managers" = managers.native.race.gender.management_type.count
    end
  end
end

But this will return strings and not variables that be assigned. I saw there is a define_method method that can dynamically build methods but that looks like you have to call it outside of the constructor in this example, and i saw that you can use Object#send like this example, but i cant see that working in this situation either.

Is this a good ruby practice? Its adding a bit of complexity but removing a lot of DRY code.

Community
  • 1
  • 1
legendary_rob
  • 12,792
  • 11
  • 56
  • 102
  • your question is looking really bad there are a lot of sentences starting with low case and without proper punction to finish that could be solved with a bit of care be respectful to anyone who might spend time reading and answering your question – sawa Jan 08 '14 at 12:24
  • There's a few questions just like yours: http://stackoverflow.com/questions/17842765/how-do-i-dynamically-create-a-local-variable-in-ruby ...among others – AndreDurao Jan 08 '14 at 12:28
  • Sorry if my punctuation offends you Sawa. AndreDurao that question makes little sense to me. i'm going to look up documentation on eval. – legendary_rob Jan 08 '14 at 12:34
  • apparently using eval for this particular situation would be a code smell. http://stackoverflow.com/questions/1902744/when-is-eval-in-ruby-justified – legendary_rob Jan 08 '14 at 12:50

1 Answers1

1

Is this a good ruby practice?

DRY is a good ruby practice, so the answer to your question is: YES

Regarding your code you will probably use send in such a situation.

something like self.send("number_of_#{race}_#{gender}_#{management_type}_managers=", managers.send(native).send(race).send(gender).send(management_type).count)

This still looks pretty ugly to me. I am kind of asking myself why that datastructure is so insane. Why are you not using a simple hash structure here?

phoet
  • 18,688
  • 4
  • 46
  • 74
  • thanks for the answer. i agree its not very pretty code at all. the guys that wrote this did so a while back. i think its time for a mega refactor. – legendary_rob Jan 08 '14 at 14:05