I ended up writing a lot, so TLDR if you don’t care about any of this: “what if we used a hash that had job titles as keys and people’s names as values, and we created a hash that had a key called ‘staff’ that had all the names from that first hash”.
Okay, so. Both of you insisted very, very heavily on the fact that it is a concept exercise, which means whatever I write comes across as either disrespectful of that concept or not understanding of that concept.
I think concept exercises are fine.
I think concept exercises are crucial.
I do also think concept exercises must be very heavily bounded, and I think here there is this one detail which unfortunately steps out of bounds, which is the reason I opened the pull request on the ruby github repo, which auto-closed the repo and told me to come post it here.
And I also know that it’s incredibly difficult to create concept exercises that aren’t so trivial to read and write that they are bland, and this exercise manages to not be bland and trivial, and that’s an accomplishment in and of itself.
Re: certain tests being placed to ensure people use a mutable solution – that’s a design choice, they indicate the builder pattern, fine, in Ruby you do the same thing by returning self
(IIRC this is some version of what rspec does to enable its syntactic sugar).
And re: similar choice in Javascript – that’s Javascript, each programming language likely needs to have this conversation happen separately, in order to represent its own paradigm effectively. In our case, we should aim to follow the community style guide as much as possible. GitHub - rubocop/ruby-style-guide: A community-driven Ruby coding style guide.
The style guide, it must be stated here, is quite pithy about the ordering of hashes:
Rely on the fact that as of Ruby 1.9 hashes are ordered.
And that’s fine - see my suggestions below, which leverage that. It just doesn’t make sense to have keys that indicate an order in a hash. Code wouldn’t be written this way, this hash wouldn’t be generated, and it creates an area of redundant information, which means it’s less clear what is happening and why.
I think we could make a change away from missing stops and towards, say, staff on the train for a particular trip, or for a particular leg of the trip.
So here are two ideas. I am hoping both are sufficiently close to the spirit of the exercise. one remains close to the letter of the exercise, one departs slightly.
def test_add_waiter_information
trip = { from: 'Bangkok', to: 'New Delhi'}
waiters = { car_1: 'Jiminy Cricket', car_2: 'Peter Pan', car_3: 'Oliver Twist'}
expected = { from: 'Bangkok', to: 'New Delhi', waiters: ['Jiminy Cricket', 'Peter Pan', 'Oliver Twist']}
actual = LocomotiveEngineer.add_staff_info(trip, waiters)
assert_equal(expected, actual)
end
def test_add_waiter_information
trip = { from: 'Bangkok', to: 'New Delhi'}
staff = { conductor: 'Jiminy Cricket', cook: 'Peter Pan', waiter: 'Oliver Twist'}
expected = { from: 'Bangkok', to: 'New Delhi', staff: ['Jiminy Cricket', 'Peter Pan', 'Oliver Twist']}
actual = LocomotiveEngineer.add_staff_info(trip, staff)
assert_equal(expected, actual)
end
In both of these tests, we are leveraging the fact that hashes preserve the creation order for the sanity of the tests, but we don’t have to, because there is no required order, and in fact the more correct test would include a custom assertion such as assert_arrays_match
, which I’m sure all of us have written at least once in our lives.
We could also do this, which is slightly uglier but much sturdier from a testing perspective - though if we do this, we largely stop relying on the hash’s implicit ordering, and we don’t need that here (it’s not like we’re loading this from postgres
or anything):
def test_add_waiter_information
trip = { from: 'Bangkok', to: 'New Delhi'}
staff = { conductor: 'Jiminy Cricket', cook: 'Peter Pan', waiter: 'Oliver Twist'}
actual = LocomotiveEngineer.add_staff_info(trip, staff)
assert_equal actual.fetch(:from), trip.fetch(:from)
assert_equal actual.fetch(:to), trip.fetch(:to)
assert_equal actual.fetch(:staff).sort, staff.values.sort
end
There you go, I hope this helps a little.