From d555f09d5e688e70e5376bbb5102bed0638d1795 Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 23 Oct 2019 20:58:09 -0700 Subject: [PATCH 1/2] Add syntax highlighting to readme code examples --- README.md | 83 +++++++++++++++++++++++++++++++++---------------------- 1 file changed, 50 insertions(+), 33 deletions(-) diff --git a/README.md b/README.md index cadb20c..43d4000 100644 --- a/README.md +++ b/README.md @@ -42,69 +42,86 @@ to these environment variables: That means that you could build a client like this: - # $ export HARVEST_ACCESS_TOKEN=abc - # $ export HARVEST_ACCOUNT_ID=12345678 - client = Harvesting::Client.new - client.me - > => #2108614, "first_name"=>"Ernesto", "last_name"=>"Tagwerker", ... > +```ruby +# $ export HARVEST_ACCESS_TOKEN=abc +# $ export HARVEST_ACCOUNT_ID=12345678 +client = Harvesting::Client.new +client.me +# => #2108614, "first_name"=>"Ernesto", "last_name"=>"Tagwerker", ... > +``` If you don't specify a valid combination of token and account id, your code will raise this error: - client = Harvesting::Client.new(access_token: "foo", account_id: "bar") - client.me - > Harvesting::AuthenticationError: {"error":"invalid_token","error_description":"The access token provided is expired, revoked, malformed or invalid for other reasons."} +```ruby +client = Harvesting::Client.new(access_token: "foo", account_id: "bar") +client.me +# Harvesting::AuthenticationError: {"error":"invalid_token","error_description":"The access token provided is expired, revoked, malformed or invalid for other reasons."} +``` If your personal token and account id are valid, you should see something like this: - client = Harvesting::Client.new(access_token: "", account_id: "") - user = client.me - > => #2108614, "first_name"=>"Ernesto", "last_name"=>"Tagwerker", ... > +```ruby +client = Harvesting::Client.new(access_token: "", account_id: "") +user = client.me +# => #2108614, "first_name"=>"Ernesto", "last_name"=>"Tagwerker", ... > - user.id - > => 2108614 +user.id +# => 2108614 +``` ### Clients - client.clients - > => [#6760580, "name"=>"Toto", "is_active"=>true, "address"=>"" ... > +```ruby +client.clients +# => [#6760580, "name"=>"Toto", "is_active"=>true, "address"=>"" ... > - client = client.clients.first - > => #6760580, "name"=>"Toto", - ... > +client = client.clients.first +# => #6760580, "name"=>"Toto", +# ... > +``` ### Time Entries - time_entries = client.time_entries - > => #100, "total_pages"=>1, "total_entries"=>14, "next_page"=>nil, "previous_page"=>nil, "page"=>1, "links"=>{"first"=>"https://api.harvestapp.com/v2/time_entries?limit=1&page=1&per_page=100", "next"=>nil, "previous"=>nil, "last"=>"https://api.harvestapp.com/v2/time_entries?limit=1&page=1&per_page=100"}}, ... > +```ruby +time_entries = client.time_entries +# => #100, "total_pages"=>1, "total_entries"=>14, "next_page"=>nil, "previous_page"=>nil, "page"=>1, "links"=>{"first"=>"https://api.harvestapp.com/v2/time_entries?limit=1&page=1&per_page=100", "next"=>nil, "previous"=>nil, "last"=>"https://api.harvestapp.com/v2/time_entries?limit=1&page=1&per_page=100"}}, ... > - entry = time_entries.first - > => #792860513, "spent_date"=>"2018-05-14", "hours"=>1.0, "notes"=>"hacked the things", "is_locked"=>false, "locked_reason"=>nil, "is_closed"=>false, "is_billed"=>false, "timer_started_at"=>nil, "started_time"=>nil, "ended_time"=>nil, "is_running"=>false, "billable"=>true, "budgeted"=>false, "billable_rate"=>nil, "cost_rate ... > +entry = time_entries.first +# => #792860513, "spent_date"=>"2018-05-14", "hours"=>1.0, "notes"=>"hacked the things", "is_locked"=>false, "locked_reason"=>nil, "is_closed"=>false, "is_billed"=>false, "timer_started_at"=>nil, "started_time"=>nil, "ended_time"=>nil, "is_running"=>false, "billable"=>true, "budgeted"=>false, "billable_rate"=>nil, "cost_rate ... > +``` ### Tasks - tasks = client.tasks - > => #100, "total_pages"=>1, "total_entries"=>6, "next_page"=>nil, "previous_page"=>nil, "page"=>1, "links"=>{"first"=>"https://api.harvestapp.com/v2/tasks?page=1&per_page=100", "next"=>nil, ... > +```ruby +tasks = client.tasks +# => #100, "total_pages"=>1, "total_entries"=>6, "next_page"=>nil, "previous_page"=>nil, "page"=>1, "links"=>{"first"=>"https://api.harvestapp.com/v2/tasks?page=1&per_page=100", "next"=>nil, ... > +``` ### Projects - projects = client.projects - > => #100, "total_pages"=>1, "total_entries"=>1, "next_page"=>nil, "previous_page"=>nil, "page"=>1, "links"=>{"first"=>"https://api.harvestapp.com/v2/projects?page=1&per_page=100", ... > +```ruby +projects = client.projects +# => #100, "total_pages"=>1, "total_entries"=>1, "next_page"=>nil, "previous_page"=>nil, "page"=>1, "links"=>{"first"=>"https://api.harvestapp.com/v2/projects?page=1&per_page=100", ... > - project = projects.first - > => #17367712, "name"=>"Foo", "code"=>"", "is_active"=>true, "is_billable"=>true, "is_fixed_fee"=>false, "bill_by"=>"none", "budget"=>nil, "budget_by"=>"none", "budget_is_monthly"=>false, "notify_when_over_budget"=>false, "over_budget_notification_percentage"=>80.0, "show_budget_to_all"=>false, "created_at"=>"2018-05-13T03:30:06Z", ... > +project = projects.first +# => #17367712, "name"=>"Foo", "code"=>"", "is_active"=>true, "is_billable"=>true, "is_fixed_fee"=>false, "bill_by"=>"none", "budget"=>nil, "budget_by"=>"none", "budget_is_monthly"=>false, "notify_when_over_budget"=>false, "over_budget_notification_percentage"=>80.0, "show_budget_to_all"=>false, "created_at"=>"2018-05-13T03:30:06Z", ... > +``` ### Nested Attributes The Harvest v2 API embeds some data in JSON objects. You can access nested attributes quite naturally. For example, to access the user id for a time entry instance, `entry`, use: - entry.user.id +```ruby +entry.user.id +``` Or to access the name of the client on a project instance, `project`: - - project.client.name +```ruby +project.client.name +``` ## Tips @@ -112,7 +129,7 @@ Or to access the name of the client on a project instance, `project`: When you need to delete all items, care needs to be taken, because the API uses pagination. The following code will only delete data from _every other_ page. -``` +```ruby # WARNING - only deletes every other page client.time_entries.each do |time_entry| time_entry.delete @@ -123,7 +140,7 @@ While iterating over items from the first page, all of those items will be delet Instead you need to make sure you get access to all of the time entry objects before you try to delete any of them. The easiest way to do this is to convert the `Enumerable` instance into an `Array`, by calling `#to_a`, before you iterate over it. -``` +```ruby # GOOD - This should do what you want client.time_entries.to_a.each do |time_entry| time_entry.delete From 37860979179df55ad000b3576e179b957fd7ec66 Mon Sep 17 00:00:00 2001 From: Ivy Evans Date: Wed, 23 Oct 2019 20:58:41 -0700 Subject: [PATCH 2/2] Add doc comment for Enumerable module It wasn't immediately apparent to me what this module was doing without reading the code more closely. --- lib/harvesting/enumerable.rb | 3 +++ 1 file changed, 3 insertions(+) diff --git a/lib/harvesting/enumerable.rb b/lib/harvesting/enumerable.rb index b3b722d..fbc9b66 100644 --- a/lib/harvesting/enumerable.rb +++ b/lib/harvesting/enumerable.rb @@ -1,3 +1,6 @@ +# `Enumerable` extends the stdlib `Enumerable` to provide pagination for paged +# API requests. +# # @see https://github.com/sferik/twitter/blob/aa909b3b7733ca619d80f1c8cba961033d1fc7e6/lib/twitter/enumerable.rb module Harvesting module Enumerable