Skip to content
This repository has been archived by the owner on Jan 17, 2019. It is now read-only.

Add API endpoint for fetching global track files #124

Closed
wants to merge 4 commits into from
Closed

Add API endpoint for fetching global track files #124

wants to merge 4 commits into from

Conversation

ramyaravindranath
Copy link
Contributor

No description provided.

@Insti
Copy link
Contributor

Insti commented Aug 9, 2016

Can you add some description to the commit message that gives us more information about this?
It should tells us what the endpoint is, why it is useful, references any issues/PRs that have further discussion.

end
end
assert_equal filenames.sort, files.sort
end
Copy link
Contributor

Choose a reason for hiding this comment

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

I really like that you've extracted assert_archive_contents into a method. 👍

Copy link
Contributor

Choose a reason for hiding this comment

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

while (entry = io.get_next_entry)
  files << entry.name
end

Is io Enumerable? Is it possible to replace this with io.map(&:name)?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

That is already implemented. I have just reused this code :)

Copy link
Contributor

Choose a reason for hiding this comment

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

I have some suggestions about the naming here: assert_archive_contains(filenames, zip)

What do you think about:

assert_archive_filenames(zip, filenames)

  • 'contains' can be ambiguous and it's not clear whether the method will check all or only some of the filenames, and if contains refers to the data that is zipped up.
  • The arguments to the method are in the same order as they are in the method name.

Copy link
Contributor

Choose a reason for hiding this comment

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

Turns out it's not Enumerable anyway. :(

Choose a reason for hiding this comment

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

The arguments to the method are in the same order as they are in the method name

Most assert methods use the ordering: expected, actual. What about assert_filenames_in_archive? Too clunky?

Copy link
Contributor

@Insti Insti Aug 10, 2016

Choose a reason for hiding this comment

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

Most assert methods use the ordering: expected, actual. What about assert_filenames_in_archive? Too clunky?

You are quite right. assert_filenames_in_archive would be fine.

But the more I think about this the more I don't like that method at all.
Here is my reasoning:

The actual assertion we want is: assert_equal expected, actual

Where:
expected = known_filenames.
actual = filenames_in_the_archive.

Which gives us: assert_equal known_filenames, filenames_in_the_archive

We have known_filenames which is files.keys (line 115 below)

What we need is filenames_in_the_archive

Ideally, we would get this by sending the archive a filenames message, (archive.filenames) but since it doesn't respond to that, we can make a wrapper method: archive_filenames(archive) which will return an array of filenames.

Extracting that part from our custom assertion, gives us a new method:

  def archive_filenames(zip)
    files = []
    Zip::InputStream.open(zip) do |io|
      while (entry = io.get_next_entry)
        files << entry.name
      end
    end
    files
  end

Which I like because it is only doing one thing (getting the filenames from the archive) and leaves the assertion (a separate responsibility) as :
assert_equal known_filenames, archive_filenames(archive)

That done, we can remove the custom assert_archive_contains/assert_archive_filenames/assert_filenames_in_archive method completely.

@ramyaravindranath
Copy link
Contributor Author

@Insti It says this branch has merge conflict. I will resolve it first and edit my commit message

@Insti
Copy link
Contributor

Insti commented Aug 9, 2016

Build is failing due to a Rubocop error:
lib/xapi/track.rb:6:3: C: Class has too many lines. [123/100]

Some things to think about:
Does the functionality you've added need to be a part of the Track class?
Could it be implemented in its own class?
Which other methods from the Track class does it depend on?

@ramyaravindranath
Copy link
Contributor Author

@Insti:This is the PR for https://github.com/exercism/x-api/issues/29.

@ramyaravindranath
Copy link
Contributor Author

@Insti I will think about it and update you. I am figuring how tests are written for routes on line 58. I will implement it for tracks as well

assert_equal 200, last_response.status
assert_equal last_response.headers["Content-Disposition"].split(';')[0], 'attachment'
assert_equal last_response.headers["Content-Type"], 'application/octet-stream'
end
Copy link
Contributor

Choose a reason for hiding this comment

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

👍

@Insti
Copy link
Contributor

Insti commented Aug 10, 2016

@ramyaravindranath Nice one on the class extraction. I'll have a closer look at it a bit later, but that was what I thought was needed. Good job.

@@ -65,6 +65,14 @@ class Tracks < Core
implementation.zip.string
end

get '/tracks/:id/global' do |id|
track = find_track(id)
filename = "%s-%s.zip" % [id, "global"]
Copy link
Contributor

Choose a reason for hiding this comment

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

Is this line tested?
What would happen if I changed it to `filename = 'blablabla'?

Copy link
Contributor Author

Choose a reason for hiding this comment

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

@Insti Thanks for pointing it out. New test has been added.

@Insti
Copy link
Contributor

Insti commented Aug 10, 2016

Ok, I've looked through it more closely now, and am impressed by what you've done.

I've made a few suggestions for things I think are possible improvements, (but not because I think what you have is not good enough!) Have a think about them and see if you agree. It may be that you think that it is unnecessary work, and you're happy with the way things are, But if you've got more time and want to stretch yourself a bit I think they will make the code more elegant and easier to work with for the next person who comes along to work on it.

Overall, great work. ❤️

Insti added a commit to Insti/x-api that referenced this pull request Aug 10, 2016
Moved large chunks of text into `Approvals` files.
Remove redundant tests.
Replace custom assertion with regular assertion + helper method.
  See discussion here: exercism#124 (comment)
Simplified individual test methods.

Flog score improvement:

Old version:
69.3: flog total
8.7: flog/method average

New version:
52.8: flog total
5.9: flog/method average
@Insti
Copy link
Contributor

Insti commented Aug 11, 2016

Those latest changes have made things much nicer.
Is there anything more you want to do before you call it done?

@ramyaravindranath
Copy link
Contributor Author

@Insti : It is done for now 😄

@Insti
Copy link
Contributor

Insti commented Aug 11, 2016

Great, I'll tag it as ready and then @kytrinyx can look over it and merge it. 👍

@Insti Insti added the ready label Aug 11, 2016
@ignore_patterns = ignore_patterns
end

def create_zip
Copy link
Member

Choose a reason for hiding this comment

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

I avoid names that say what a method does, and try to name things for what the method returns. This is because the implementation could change (we could decide to create the zip elsewhere, and this method would just return the zip that we had created).

@kytrinyx kytrinyx removed the ready label Aug 13, 2016
@kytrinyx
Copy link
Member

@ramyaravindranath This needs a couple of small tweaks before it can be merged.

@exercism/rgsoc2016 I've got some feedback with respect to pull requests in general.

The advice in this article about commit messages is also relevant to pull requests.

When you submit a pull request, try to make the title state the most important idea, and then in the body of the pull request, explain why this was necessary, and summarize the details.

Here the title says adds new api end point, which means that the reader has to figure out what endpoint and why. A better subject-line would be

Add API endpoint for fetching global track files

or

Implement support for exercise-agnostic files in tracks

If the pull request fixes an existing issue, then it's important to reference that, either in the subject or the body of the pull request—preferably in a way that would automatically close the issue when the pull request gets merged. See https://github.com/blog/1506-closing-issues-via-pull-requests for details.

Even though there is often a discussion about the change elsewhere, it's important to summarize the most important / most relevant points about the actual change that was made in the pull request description.

The goal is to let the reviewer have a solid idea of what the code is doing and why before actually looking at the code—and without going to read through other discussions elsewhere, unless they want more granularity.

Without it, the reviewer has to wade through an entire discussion where the details have been hashed out, often through dozens of comments, and they also have to read the code while guessing what the change is about. If the important changes are mentioned up front, then it's possible to review the patch much more strategically instead of top-to-bottom.

If you have a pull request that includes both refactoring and changes, then it's a huge help if you commit the refactoring in a separate git commit, before making the change. This lets the reviewer review the refactoring first without mixing in new behavior, and it also lets them look at the new behavior without mixing in the refactoring changes. That new behavior will be a smaller diff, and therefore easier to understand. Often I end up starting to make a change, and then realizing that I'm going to refactor. At that point I usually stash the changes that I've already made, refactor, commit, and unstash. Or sometimes I make a branch. This sometimes means that I have to redo some of the work that I already did, but it's worth it to have the commits be atomic.

@ramyaravindranath ramyaravindranath changed the title adds new api end point Add API endpoint for fetching global track files Aug 15, 2016
@ErikSchierboom
Copy link
Member

Excited to see it is almost done :)

@kytrinyx
Copy link
Member

@ramyaravindranath Would you post a comment here when you're ready for the final review?

@ramyaravindranath
Copy link
Contributor Author

@kytrinyx I have fixed all the comments. It is ready for the final review. Thank you.

@kytrinyx
Copy link
Member

Thank you @ramyaravindranath! Merged in d1385d7

@kytrinyx kytrinyx closed this Aug 18, 2016
@Insti Insti removed the in progress label Aug 18, 2016
@ErikSchierboom
Copy link
Member

@kytrinyx I think the CLI also has to be updated, right?

@kytrinyx
Copy link
Member

kytrinyx commented Sep 2, 2016

Yepp: exercism/cli#88

@kytrinyx
Copy link
Member

kytrinyx commented Sep 2, 2016

Oh, haha, you found that one :)

@ErikSchierboom
Copy link
Member

I did 😀

Sign up for free to subscribe to this conversation on GitHub. Already have an account? Sign in.
Labels
None yet
Projects
None yet
5 participants