Reputation: 3638
I'm looking for a more DRY way to iterate through some code. I have a User
model and I want to keep count of certain Users
in a ReportRecord
model (for reporting).
I have a defined list of values of User.names
that I want to record (i.e. "Jan", "Lisa", "Tina"). How can I make this code more DRY as the list is much longer than three values?
@users = User.all
@users.each do |u|
# this part repeats with different names
quantity = u.where("name = ?", "Jan").count
ReportRecord.create(:user_id => u.id, :name => "Jan", :quantity => quantity)
# repeated code with different name
quantity = u.where("name = ?", "Lisa").count
ReportRecord.create(:user_id => u.id, :name => "Lisa", :quantity => quantity)
# repeated code with different name
quantity = u.where("name = ?", "Tina").count
ReportRecord.create(:user_id => u.id, :name => "Tina", :quantity => quantity)
end
Upvotes: 0
Views: 91
Reputation: 13487
I would sum all users first (1 query instead of 3):
quantity_by_name = User.select(:name).where(name: %w(Jan List Tina))
.group(:name).sum(:quantity)
#=> { 'Lisa' => 1, 'Jan' => 2, 'Tina' => 3 }
quantity_by_name.each do |name, quantity|
ReportRecord.create(name: name, quantity: quantity)
end
Upvotes: 3
Reputation: 17812
names = %w(Jan List Tina)
names.each do |name|
count = User.where(name: name).count
ReportRecord.create(name: name, quantity: count) # I don't understand `u.id`
end
Upvotes: 2