0

I have a DataPoint model where I have three methods that do the same thing, just on different fields in the data_points database.

def self.currently_employed(data_points)
    data_points.where(currently_employed: true).count / data_points.count.to_f * 100
end

def self.undergrad_degree(data_points)
    data_points.where(undergrad_degree: true).count / data_points.count.to_f * 100
end

def self.grad_degree(data_points)
    data_points.where(grad_degree: true).count / data_points.count.to_f * 100
end

I think I should be able to refactor this to accept which column to perform the calculation on as a parameter, but much time on the internet / trying stuff out hasn't yielded results.

Could someone please advise me on whether / how I could refactor this to a single method?

In case it affects the answer: the data_points argument is a subset of DataPoint.all specified by the User - i.e. User types in what age, years work experience, etc. they want to see results for (age & years_work_experience are DataPoint attributes), and then I want to show summary stats for that subset.

Thanks!

2 Answers 2

1

The name of the attribute is really just a key in a hash.

data_points.where(currently_employed: true)

Is equivalent to

data_points.where({:currently_employed => true})

With this in mind, it's easy to refactor these methods into one:

def self.percent_with_attribute(data_points, attribute)
    data_points.where(attribute => true).count / data_points.count.to_f * 100
end
Sign up to request clarification or add additional context in comments.

Comments

0

You can use string interpolation here.

def self.status(data_points, key)
  data_points.where("#{key}": true).count / data_points.count.to_f * 100
end

How it differs from @Ajedi32's answer is only in that the key here will be converted to a Symbol, instead of a plain String.

3 Comments

To clarify, my answer only passes the attribute as a string if the attribute argument given to percent_with_attribute was already a string. If the attribute argument was a symbol, it will be passed as a symbol. This answer converts the argument to a symbol regardless of whether it was passed as a string, symbol, or any other object that responds to to_s. In practice, there's probably not any real significant difference between these two approaches, since AFAIK Rails treats string and symbol keys identically.
That's correct, but I thought I would provide the alternative solution as well.
No. There isn't. Except the syntax for the hash will change to key.to_sym => true.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.