Take the 2-minute tour ×

To populate some sample data in a Rake task curretnyl I have methods like this:

def create_population_summaries
  PopulationSummary.where(year: 2009).first_or_create(member_count: 12, organization_id: 1)
  PopulationSummary.where(year: 2010).first_or_create(member_count: 5, organization_id: 1)
  PopulationSummary.where(year: 2011).first_or_create(member_count: 99, organization_id: 1)
  PopulationSummary.where(year: 2008).first_or_create(member_count: 52, organization_id: 1)
  PopulationSummary.where(year: 2012).first_or_create(member_count: 30, organization_id: 1)
  PopulationSummary.where(year: 2013).first_or_create(member_count: 25, organization_id: 1)
  PopulationSummary.where(year: 2008).first_or_create(member_count: 46, organization_id: 1)

So it means there is a PopulationSummary table that has columns like


and we have populated them with the data that boss! has given to me.

Now I want to refactor this in a way that it uses some Ruby structures like hashes, arrays, even arrays of hashes, etc... such that after refactoring my method does NOT include those hand typed data inside the method AND those hand typed data should come from that Ruby structure, hash, etc... still in the method I can hand type the names of the fields of the data base, like year, member_count, etc... but the values for those I want to read from the ruby data structure ..

How do you suggest to write that data structure?

share|improve this question
Refactoring questions should be asked on codereview.stackexchange.com. Read "I'm confused! What questions are on-topic for this site?" in the FAQ and see if it fits your needs. –  the Tin Man Feb 16 at 17:52
add comment

3 Answers

up vote 1 down vote accepted
data = [{'year'=>2009, 'members'=>12}, {'year'=>2010, 'members'=>5}....]

then loop

data.each do |d|
  PopulationSummary.where(year: d['year']).first_or_create(member_count: d['members'], organization_id: 1)   
share|improve this answer
hmm is there a way to also get rid of repeating "year" , "members"... in the first array and keeping it DRY? –  BDotA Feb 16 at 17:53
sure, you could do that, but then you'll be asking yourself "wtf is that data structure full of numbers" and "did is that the member count at d[1] or the organization_id". be kind to your future self and the engineers that follow you: use data structures that make sense. –  Igor Serebryany Feb 16 at 18:00
I agree with your point too. Can we somehow write it in a way that be like a hash that says key of the hash is Year, and the value of the hash are those 2009, 2010,etc ? Can we write it that way? what do you think ? –  BDotA Feb 16 at 18:04
add comment

What about something like:

DATA = [[ 2009, 12, 1], 
        [ 2010,  5, 1], 
       ... ]

DATA.each do |d|
  PopulationSummary.where(year: d[0]).first_or_create(member_count: d[1], organization_id: d[2])
share|improve this answer
hmm better :) to make it more readable, can you change it in a way that it kind of uses "hash" too? for example a hash that its key is "year", then it has values of 2009, 2010 as an array for its keys? ... just something in my mind..not sure which one is better...what do you suggest? –  BDotA Feb 16 at 18:00
You want to explode the data structure in 3 hashes ? this will probably start getting complicated to maintain... All in all, igor solution is better, because it's explicit although you need to write more text... –  Oct Feb 16 at 18:45
add comment

Just out of curiosity, you may totally separate the meta-programming (business rules, came from the boss) and the population itself:

data = [ {
         }, {
         }, {
       } ]

And then populate:

data.each do |d| 
  d.inject (PopulationSummary) do |rec, val|
    rec.where val

But I’m afraid you gonna hate this hint after a couple of months when the boss will bring a new portion of data.

share|improve this answer
add comment

Your Answer


