-2

I have the following array with nested hashes:

pizza = [
         { flavor: "cheese", extras: { topping1: 1, topping2: 2, topping3: 3} },
         { flavor: "buffalo chicken", extras: { topping1: 1, topping2: 2, topping3: 3} } } ]

If want to verify that I can get an order of "buffalo chicken" pizza with two toppings. I use the .map method to iterate through the array of hashes to verify that the "flavor" I want and the "extras" I want ( 2 toppings) are available. Bingo! The code I use works, returns true, and indeed these two elements are available. BUT, if I want to check if the "buffalo chicken" flavor is available and 5 toppings are also available, then it should return false, but instead, I get an Error message that says:

Failure Error: expect(Party).not_to be_available(pizza, "buffalo chicken", :toppings5) to return false, got []

Here is my code:

 def self.available?(pizza, flavor, extra)
      pizza.map { |x| x if x[:flavor] == flavor && x[:extra] == extra }
end

I'm trying to figure out why I get [] returned rather than false. Perhaps there is something I'm not understanding with the way .map is being used to iterate through my array of hashes? Without changing the structure of my array of hashes, could someone please help me understand?

  • "I get an error message" – Unfortunately, you don't tell us what the error message says, so the best thing we can do is tell you to read the error message and fix the error. – Jörg W Mittag Sep 28 '17 at 07:32
  • _"[...] pizza with two toppings"_ – does that mean _at least_ two toppings or are you looking for two specific toppings? – Stefan Sep 28 '17 at 11:09
  • Two toppings, so I am looking for "topping2" to return true. – user8687088 Sep 28 '17 at 11:20
  • If I were looking for let's say "topping5" (for 5 toppings) on a "buffalo chicken" pizza, it should then return false since it's not an option under "extras" – user8687088 Sep 28 '17 at 11:22
  • Instead of putting a sequence in hash key names (`topping1`, `topping2`), you'd be better off with an array (`toppings: [1, 2]`) – Mark Thomas Sep 28 '17 at 11:39
  • Not saying this is the case, but based on my experience it must be said: If this hash is the product of an ActiveRecord query, then you should throw it out and make your queries directly from the DB using the AR query syntax. – Mark Thomas Sep 28 '17 at 11:43
  • Hi @MarkThomas, I hear what you're saying, but I want to keep it this way for this reason. Say I later want to change topping1 to be "sausage" rather than 1, and topping2 to be "sausage and mushrooms" rather than 2, and topping3 to be "sausage, mushroom, spinach" rather than 3. Then I would still have to work with the extras being a hash of the different topping options, rather than an array of the toppings. – user8687088 Sep 29 '17 at 00:15
  • `pizzas = [ {flavor: cheese, toppings: [:sausage]}, {flavor:cheese, toppings: [:sausage, :mushrooms]}, {flavor: cheese, toppings: [:sausage, :mushrooms, :spinach]} }` This is much more flexible. You can do things like `pizzas.collect {|p| p.toppings.size < 3}` – Mark Thomas Sep 29 '17 at 00:24

1 Answers1

2

You have several problems here:

  • The keys in the hash must be unique, so the two first toppings keys are ignored. Here is an example of a wrong hash { key: 1, key: 2, key: 3 } it becomes { key: 3 }.
  • You must not use hash as the name of a variable in any case, it's a method.

To find an element in an array of hashes, you can use the find method, e.g.:

>> h = [{ f: "cheese", extras: [1,2,3] }, { f: "buffalo", extras: [1,3] }] 
>> h.find { |h| h[:f] == "cheese" && h[:extras].size > 2 }
=> {:f=>"cheese", :extras=>[1, 2, 3]}

There are a lot of methods to iterate over an array or hash. Read more about Enumerable module. Also don't be lazy and check documentation.

dda
  • 6,030
  • 2
  • 25
  • 34
Roman Kiselenko
  • 43,210
  • 9
  • 91
  • 103
  • Thanks, I just tried using the find and include? methods but I get the following error message: NoMethodError: undefined method `include?' for nil:NilClass – user8687088 Sep 28 '17 at 04:55
  • @user8687088 Bear in mind, I'm not your debugging tool. If you have an error, you must doing some research and understand the problem. – Roman Kiselenko Sep 28 '17 at 04:58
  • I tried looking up various reasons why I could get this error message, and either I can't use .include? or the (2) is the problem. I've use this message before with .any? with no issues but I can't seem to get it to work with .find and I'm not sure why. – user8687088 Sep 28 '17 at 05:39
  • @user8687088 show the full code which you're using. exactly full. – Roman Kiselenko Sep 28 '17 at 05:43
  • pizza.find { |h| h[:flavor] == "buffalo chicken" && h[:extras].include?(topping2) } – user8687088 Sep 28 '17 at 06:42
  • @user8687088 please the __FULL__ code, all things, all variables, all steps. – Roman Kiselenko Sep 28 '17 at 06:46
  • Thanks for your help! I've edited my post with all the variables and full code to clarify the parts I am trying to understand. – user8687088 Sep 29 '17 at 07:19
  • @user8687088 that's not a StackOverflow way to usage, you're editing your question several times. 1 question => 1 answer. S.O. is not a forum. – Roman Kiselenko Sep 29 '17 at 07:30