tawnos
tawnos

Reputation: 23

Rails: Dynamically selecting an attribute for comparison

I have a database of different food menus that I am trying to search through. In general everything works fine, but I think that there must be a cleverer way in writing the code compared to what I am doing now.

Every menu has a set of boolean attributes describing the kind of kitchen (e.g. cuisine_thai, cuisine_italian, etc.). In my view I have a dropdown allowing the user to select the type of food he wants and then I am passing the param on and save it in my search-object.

@search.cuisine_type = params[:cuisine_type]

I then continue to check for the different kitchen types and see if there is a match.

#Filter for Thai cuisine
if(@search.cuisine_type == "cuisine_thai")
  @menus = @menus.select{ |menu| menu.cuisine_thai == true}
end
#Filter for French cuisine
if(@search.cuisine_type == "cuisine_italian")
  @menus = @menus.select{ |menu| menu.cuisine_italian == true}
end
#Filter for Peruvian cuisine
if(@search.cuisine_type == "cuisine_peruvian")
  @menus = @menus.select{ |menu| menu.cuisine_peruvian == true}
end

Eventhough the way I do it works, there must be a better way to do this. I feel that the value stored in @search.cuisine_type could just determine the attribute I check on @menus.

Any help on this is greatly appreciated. Thanks!

Upvotes: 2

Views: 138

Answers (2)

Jakub Mendyk
Jakub Mendyk

Reputation: 438

Wouldn't it be better if you had column "cuisine" in database and have it set to thai, italian and so on?

Then you'd only check if certain food matches array of kitchens selected by the user.

Upvotes: 0

Matt Brictson
Matt Brictson

Reputation: 11102

Yes, your intuition is correct!

I'll assume @menus is an array are ActiveRecord Menu objects, and that the cuisine_* attributes correspond to database columns. In this case you can use ActiveRecord's attributes method.

Every ActiveRecord object has an attributes property. The docs (Rails 4.2.1) say:

attributes() Returns a hash of all the attributes with their names as keys and the values of the attributes as values.

To verify this is the case, if you peek at the attributes of a given menu, you should see a hash containing:

{
  "cuisine_italian" => true,
  "cuisine_thai" => false,
  # etc.
}

Also, as a minor point of code readability, these two statements are effectively the same:

@menus = @menus.select { ... }
@menus.select! { ... }

Therefore, your search can be rewritten as:

if @search.cuisine_type.present?
  @menus.select! { |m| m.attributes[@search.cuisine_type] }
end

Upvotes: 2

Related Questions