cancel
Showing results for 
Search instead for 
Did you mean: 
dranzolin
Community Participant

R Client for Canvas API

Hi everyone,

For any useRs out there, I just started to put together an R Client for the Canvas API. It's pretty early in the development stage, and I'll add more functionality in the next few months, but I thought I'd share!

Let me know what you think!

David

Labels (1)
11 Replies
xxie34
Community Participant

Hi David, 

Thanks for creating this. I tried the get_course_gradebook function and it only returned grades for 10 students out of 200+ students. Do you know why that could be?

James
Community Champion

I don't use the script (and my R experience is limited), but the returning 10 out of 200+ sounds like a pagination issue.

By default, calls to the API only return 10 items, so any time someone complains of only getting 10 items, it's almost invariably a pagination issue. You can often specify a per_page=100 parameter in the query string to get up to 100 records, but at some point, you'll run into the issue of more records needing to be returned. It's not as simple as changing the 100 to a 1000, I picked 100 because that seems to be an upper limit for most of the requests.

xxie34
Community Participant

I got about 400+ items -- this course has a LOT of assignments and quizzes. But only 10 unique students show up from those 400 items. Can this still be a pagination issue?

 

If so, I don't see a parameter in the function to change that.

James
Community Champion

It could still be a pagination issue. It's the outer results that are limited, so if it's grouped by student, then you would get 10 students, but perhaps many items for each of those students.

I don't know how to code R, but there are a couple of places I see that it might go.

Here's the link to the source code file for that function: rcanvas/get_course_gradebook.R


Inside of that is this code (starting at line 18)

  get_assignment_submissions <- function(course_id, assignment_id) {
    url <- sprintf("%s/courses/%s/assignments/%s/submissions",
                   canvas_url(), course_id, assignment_id)
    # process_response(url, args = list(access_token = check_token()))
    httr::GET(url, query = list(access_token = check_token())) %>%
      httr::content("text") %>%
      jsonlite::fromJSON(flatten = TRUE)
  }‍‍‍‍‍‍‍‍

In the line that has URL, you could add ?per_page=100 after the submissions (change line 1 to line 2)

url <- sprintf("%s/courses/%s/assignments/%s/submissions",
url <- sprintf("%s/courses/%s/assignments/%s/submissions?per_page=100",

However, I suspect that a better place would be on the line that has the query = (line 5 in what I quoted). Again, change line 1 to line 2. Also realize that I don't know R and this may not work, but it sounds reasonable.

httr::GET(url, query = list(access_token = check_token())) %>%
httr::GET(url, query = list(access_token = check_token(), per_page = 100)) %>%

Three notes.

The first is that it will only get you 100 items and if you have 200 students, then it's not going to work beyond the first 100. You'll need to run it as is, then modify the code to add a page=2 and run the code, then modify it to have page=3 and run it and so on until you've gotten all of the students.

The second is that what really needs to happen is that the maintainer of the software needs to handle pagination. They seem to be aware of the issue as one was filed about your exact problem back in May. get_course_gradebook(course_id) shows maximum 10 entries per assignment_id · Issue #13

The person found a work-around and the problem was never fixed, but you should try to reach out to the developers on GitHub.

The third is that passing the access_token in the query string is not the preferred way of sending it. According to the API documentation, Canvas LMS REST API Documentation (emphasis mine).

API authentication is done with OAuth2. If possible, using the HTTP Authorization header is recommended. Sending the access token in the query string or POST parameters is also supported.

They do go on to show an example of how to do it with the query string, but the header is the preferred way. That's not your issue since you're using someone else's library, but you might be concerned with security or possibly mention it to them. I'm not sure what R allows or doesn't allow, but I thought I'd mention it.

xxie34
Community Participant

Thanks for taking the time to look at the issue. This makes a lot of sense. 

I will come back to update if it works if I get a chance to edit the source code.

Hi Canoe,

Apologies I'm seeing this so late! I started a new job and no longer receive Canvas alerts to my original account. And because Canvas is no longer a part of my job, I haven't devoted much time to its continued development.  @James  is correct--this is an issue for the maintainer (me, or my collaborators) to fix. James, that was also an impressive exposition of unfamiliar R code! 

I'd like to continue development on this package in the near future, but in the meantime, feel free to file an issue on the GitHub page. We might have some new collaborators and features in the pipeline.

Just pushed an update--authentication now occurs in the header! Smiley Wink 

xxie34
Community Participant

Hi David,

I was trying to edit the code following what  @James ‌ wrote, but the code seems to have been updated and i'm lost. 

There is already an issue on the pagination here: get_course_gradebook(course_id) shows maximum 10 entries per assignment_id · Issue #13 · daranzolin/...   It would be awesome if you or your team could fix it! This will be very helpful for us.

Hi Canoe, 

I pushed a small update that I haven't tested. There are some structural adjustments I wanted to make earlier this year, but I moved into a different position where I no longer use Canvas. My new testing suite, so to speak, is far less robust. 

Let me know if the small change works--I still need to address pagination, if you have more than 100 entries.