1

I am creating a takeaway restaurant database, which can be accessed by the Managers of each store. One of the database tables in called Product, and it has a column called product_name. The product_name is a string with multiple words. I'm trying to check whether the product_name contains meat, and then tell the user whether it is or is not suitable for vegetarians.

This is the code I have. I was trying to create a meats array, and check product_name against it. I don't think the if not statement is correct.

class Checkveg
  def self.runcheck(product_name)
    meats = ["lamb", "beef", "pork", "prawn", "chicken", "fish"]
    meats.each { |item|
      if product_name.include? item
        puts "Not suitable for vegans or vegetarians"
      end
    }
    puts "Suitable for vegans or vegetarians" if not meats.include? product_name
  end
end

**UPDATE:

I was able to fix it

noVeg = false
meats = ["lamb", "beef", "pork", "prawn", "chicken", "fish"]
meats.any? { |item|
  if product_name.include? item
    noVeg = true
    break
  end
}
if noVeg == true
  puts "Not suitable for vegetarians"
else
  puts "Suitable for vegetarians"
end
12
  • I haven't implemented it get, and i would like input to whether the coding is correct. Commented Mar 16, 2019 at 12:29
  • meats.include? x is going to be true if x is in the array meats. Do you expect product_name ever to be an element of the array? Also, look up the Ruby Array class. There are other interesting methods such as .any? or .all? that may be of interest for your problem and make it simpler. Commented Mar 16, 2019 at 12:29
  • @lurker puts "Suitable for vegans or vegetarians" if not meats.include? product_name. Would that also work, even if the product_name is a string with multiple words? Commented Mar 16, 2019 at 12:31
  • meats.include? product_name will be true only if product_name is an element of the array meats. I suspect that it never is. Also, see my prior comment about .any? and .all?. Commented Mar 16, 2019 at 12:32
  • It took me 1 minute and 27 seconds to load your code into console and run it. Why don't you do the same and see what works and what doesn't? Commented Mar 16, 2019 at 12:33

3 Answers 3

2

You are not using the any? method properly. You should use it's return value like this:

#!/usr/bin/env ruby

meats = ["lamb", "beef", "pork", "prawn", "chicken", "fish"]

product_name = "Beef curry"

noVeg = meats.any? do |item|
    product_name.downcase.include? item
end

if noVeg == true
    puts "Not suitable for vegetarians"
else
    puts "Suitable for vegetarians"
end

I also added downcase since in the comment above you wrote beef with a capital b.

Sign up to request clarification or add additional context in comments.

3 Comments

if noVeg == true is also an anti-pattern. You could simply do if noVeg.
@3limin4t0r true, that's what you get when copying OP's code, the point was to show the any method though.
I thought as much. Maybe the comment was better suited under the question itself, but nonetheless it's worth pointing out.
2

I'd suggest, first to extract the words from the product name. I used the regex from a good example by Cary Swoveland for this method. But you can use whatever regex fits best for you:

product_name = "Chicken_Wings 1"
product_words = product_name.scan(/[[:alpha:]](?:(?:[[:alpha:]]|\d|')*[[:alpha:]])?/x).map(&:downcase)

#=> ["chicken", "wings"]

Then check if none of the product_words is included in meats array:

no_veg = product_words.none? { |w| meats.include? w }
#=> false

In this case product_name = "Carrots and onions", no_veg = true.

1 Comment

When using this approach you could also use (product_words & meats).empty? instead of product_words.none? { |w| meats.include? w }. Although the result would be the reverse, eg. veg.
2

Another option is to create a regex using the meats array.

meats_regex_string = meats.map(&Regexp.method(:escape)).join('|')
meats_regex = Regexp.new(meats_regex_string)
# or /#{meats_regex_string}/
product_name.match?(meats_regex)

You can leave out .map(&Regexp.method(:escape)) if you know your strings don't contain any regex special characters like (, *, ?, |, etc.

If you don't care about the character casing use:

meats_regex = Regexp.new(meats_regex_string, Regexp::IGNORECASE)
# or /#{meats_regex_string}/i

1 Comment

Since you're new to Ruby it might be worth pointing out that .map(&Regexp.method(:escape)) could also be written as .map { |meat| Regexp.escape(meat) }.

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.