Skip to content

Conversation

@emilcecarlisa
Copy link

@emilcecarlisa emilcecarlisa commented Feb 20, 2018

Grocery Store

Congratulations! You're submitting your assignment.

Comprehension Questions

Question Response Instructor Response
Why is it useful to put classes inside modules? To reference them as objects and not have to re-write code constantly
What is accomplished with raise ArgumentError? It handles errors or exceptions without quitting the program This isn't quite right. raise-ing an exception is like saying "something's wrong", and will cause the program to exit. If you're calling a method that you know might raise an exception, and you know what to do in that situation, you can rescue the error, which will prevent the program from exiting.
Why do you think we made the .all & .find methods class methods? Why not instance methods? Class methods only exist in the methods that call them, so no matter what file we used, we could call on the method to retrieve information...? I'm not sure what you mean by this. To think about why we've made them class methods, consider how your code would be different if we had made them instance methods. In that case, you would need to already have an instance of Order to get the list of all orders, which doesn't make much sense. With class methods, all you need is to know that there is such a thing as an Order, and then you can call Order.all to get the list.
Why does it make sense to use inheritance for the online order? An online order is an order with a few exceptions so inheritance is good design for our problem which is not too complex
Did the presence of automated tests change the way you thought about the problem? How? It sort of helped me understand what was going on in my "product code", but still felt like extra work.

@emilcecarlisa
Copy link
Author

I would like to continue working on Wave 3.

@emilcecarlisa emilcecarlisa changed the title Emilce -- Octos -- Grocery Store Emilce -- Grocery Store -- Octos Feb 20, 2018
@droberts-sea
Copy link

Grocery Store

What We're Looking For

Feature Feedback
Baseline
Answered comprehension questions yes - see my responses above
Used Git Regularly It looks like you're still using the old turn-in instructions, where you copy/paste code into GitHub. In the future please use git push to get code to the internet, so that I can see your full commit history.
Wave 1
All provided tests pass yes
Using the appropriate attr_ for instance variables no - see inline
Wave 2
All stubbed tests are implemented fully and pass mostly - tests for .find don't actually call .find
Appropriately parses the product data from CSV file in Order.all yes
Used CSV library only in Order.all (not in Order.find) yes
Used Order.all to get order list in Order.find yes
Wave 3
All stubbed tests are implemented fully and pass No - most tests are not implemented
Used inheritance in the initialize for online order no - see inline
Used inheritance for the total method in online order yes
Use CSV library only in OnlineOrder.all yes
Used all to get order list in find yes
Appropriately searches for Customer orders in find_by_customer N/A
Additional Notes

This is a good start, but there are definitely some pieces missing from this submission, and it also seems like there may have been some requirements misses.

One thing that might help going forward is to focus more on keeping yourself organized and making sure you've got a process to follow. An example of this process for a method might look something like this:

  1. Look at the requirements for the method
  2. Read the requirements carefully, and make sure you fully understand what we're asking for
    • What parameters does the method take? What does each parameter look like? Write an example input as a comment.
    • What does the method return? What is the type of the return value?
    • If you're not sure, ask an instructor!
  3. Write the method signature, and a line at the bottom of the method where you return an appropriately named variable.
  4. Come up with a nominal test case for the method. What will it look like from the outside when everything is going right?
  5. Think about how the method will work. Use a whiteboard or write some pseudocode to help you reason through the logic.
  6. Implement the method
  7. Think about edge cases for the method. What arguments might cause it to break? Where does it transition from working to not working?

There is a lot of good work that went into this project, and I want to acknowledge the hours you've been putting in as well. Hopefully following a process like this will help to make your work more efficient. Keep that level of dedication and keep your spirits up, and things will definitely come together.

require "awesome_print"

ORDERS_CSV = "../support/orders.csv" # take off ../ if running rake

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of changing the path, you can run the ruby file from the project root:

$ ls
README.md  Rakefile  feedback.md  lib  specs  support
$ ruby lib/order.rb
[ ... program output ...]

class Order
attr_reader :all, :total
attr_accessor :id, :products, :add_product

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

I'm curious why you chose to make these attr_accessors. As far as I can tell, you don't set these values anywhere outside this class, nor should you given the spec.

Leaving it an attr_reader is a safety measure, so that if you accidentally do something like if order.id = 3 (using = instead of ==), ruby will give you a big error instead of doing the wrong thing.

Also, add_product is an instance method, but attr_accessors only work for instance variables. Saying attr_accessor :add_product doesn't make any sense.

products_string.each do |product| # "cucumber:5"
key = product.split(":")[0] # ["cucumber", "5"]
value = product.split(":")[1]
products_hash[key] = value.to_f # or # products_hash.push(key: value)

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Good work getting this tricky logic sorted out.

unless order.id == id
raise ArgumentError.new("Order number could not be found")
end
return order.products

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This isn't quite what we were looking for with this method. What we want is for you to, given an ID, find the entire Order, not the list of products.

Moreover, putting the raise inside the loop like this means that as soon as you look at an order that isn't the one you want, you'll throw an error. Instead, you should do something like this:

def self.find(id)
  self.all.each do |order|
    if order.id == id
      return order
    end
  end
  raise ArgumentError.new("Order number could not be found")
end

What this code says is, "if I looked at every single order and still couldn't find the one I wanted, then I'll raise an error".

return false
else
@products.store(product_name, product_price)
return true

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

On line 71, it would be a little more clear to say @products[product_name] = product_price. This square brackets notation makes it clear that you're adding a key/value pair to the hash, whereas calling a method means the reader has to think about what's going on.

order_array.each do |order|
if order.id == 1
order.products.must_equal({"Slivered Almonds"=>22.88, "Wholewheat flour"=>1.93, "Grape Seed Oil"=>74.9})
end

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Since these tests are for Order.find, you should be calling Order.find here. Remember, the Act step of Arrange, Act, Assert is always to call the method you're testing.


class OnlineOrder < Grocery::Order
# OnlineOrder is an Order
# customer object

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This class should be inside the Grocery module.


def initialize(id, products, cust_id, status)
@id = id
@products = products

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of saving @id and @products yourself here, you should call super(id, products) and have Order's initialize method do the work for you.

if @products.key? product_name
puts "This is already included in the order."
return false
else

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Instead of copying this code from Order, you should use super(product_name, product_price) to access the existing behavior.


def add_product(product_name, product_price, cust_id, status)
if status != :pending || status != :paid
raise ArgumentError.new("Can only add new product if your status is pending or paid")

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This method should not take a customer ID or a status. The method signature should be the same as for Order.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

2 participants