# Dynamically combine ActiveRecord Relation results [closed]

This isn't the actual use-case I have but for simplicity, let's say I have an ActiveRecord Animal model in a Rails app. The Animals have a name (string) and rating (int). There could be animals with the same name but different ratings. In my Animal model I have a hardcoded constant like this:

SPECIAL_ANIMAL_TYPES = [
{ name: 'Cat', rating: 3 },
{ name: 'Dog', rating: 5 },
{ name: 'Fish', rating: 1 }
]


I want to grab a single ActiveRecord:Relation with all Animals that match these attributes exactly. I can't pass an array to the where clause like where(name: ['Cat', 'Dog', etc], rating: [3, 5, 1]) because I only want cats that are rating 3, and dogs that are rating 5 and so on. Like I said, there could be multiple records with the same name but different ratings.

In the Animal model I have a class method (basically a scope) to grab the records that match the types specified in SPECIAL_ANIMAL_TYPES. The following code does what I want, but clearly is pretty ugly and if I added more types to SPECIAL_ANIMAL_TYPES I'd have to modify this method:

def self.special_animals_only
where(SPECIAL_ANIMAL_TYPES[0]).or(where(SPECIAL_ANIMAL_TYPES[1])).or(where(SPECIAL_ANIMAL_TYPES[2]))
end


I also tried something like:

def self.special_animals_only
SPECIAL_ANIMAL_TYPES.collect { |types| where(types) }.sum
end


But that returns an array and I want an ActiveRecord Relation. So is there a more elegant way to write this class method so I can continue modifying/adding types to the constant and have this method work dynamically?

• The code snippets I posted do work absolutely correctly (see code snippet #2), but it could be improved, it's not the most elegant solution, which is what I thought this Stack Exchange was for. Would appreciate some actual feedback on how to improve this question! – kaydanzie Sep 10 at 15:38

def self.special_animals_only