strava-ruby-client 3.0.0.pre.2 → 3.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (108) hide show
  1. checksums.yaml +4 -4
  2. data/CHANGELOG.md +15 -2
  3. data/README.md +47 -58
  4. data/lib/strava/api/client.rb +69 -0
  5. data/lib/strava/api/config.rb +40 -0
  6. data/lib/strava/api/cursor.rb +32 -1
  7. data/lib/strava/api/endpoints/activities.rb +197 -57
  8. data/lib/strava/api/endpoints/athletes.rb +64 -8
  9. data/lib/strava/api/endpoints/clubs.rb +24 -59
  10. data/lib/strava/api/endpoints/gears.rb +11 -2
  11. data/lib/strava/api/endpoints/oauth.rb +45 -0
  12. data/lib/strava/api/endpoints/routes.rb +20 -13
  13. data/lib/strava/api/endpoints/segment_efforts.rb +15 -8
  14. data/lib/strava/api/endpoints/segments.rb +74 -21
  15. data/lib/strava/api/endpoints/streams.rb +22 -18
  16. data/lib/strava/api/endpoints/uploads.rb +12 -2
  17. data/lib/strava/api/pagination.rb +25 -0
  18. data/lib/strava/api/ratelimit.rb +34 -0
  19. data/lib/strava/deep_copyable.rb +20 -1
  20. data/lib/strava/errors/fault.rb +32 -0
  21. data/lib/strava/errors/ratelimit_error.rb +35 -0
  22. data/lib/strava/errors/upload_error.rb +55 -0
  23. data/lib/strava/logger.rb +27 -0
  24. data/lib/strava/models/achievement.rb +28 -1
  25. data/lib/strava/models/activity_stats.rb +47 -1
  26. data/lib/strava/models/activity_total.rb +25 -1
  27. data/lib/strava/models/activity_zone.rb +39 -2
  28. data/lib/strava/models/authorization.rb +13 -0
  29. data/lib/strava/models/base_stream.rb +22 -1
  30. data/lib/strava/models/club_event.rb +64 -1
  31. data/lib/strava/models/comment.rb +39 -1
  32. data/lib/strava/models/destination.rb +28 -1
  33. data/lib/strava/models/detailed_activity.rb +203 -2
  34. data/lib/strava/models/detailed_athlete.rb +104 -2
  35. data/lib/strava/models/detailed_club.rb +76 -2
  36. data/lib/strava/models/detailed_gear.rb +45 -2
  37. data/lib/strava/models/detailed_photo.rb +61 -1
  38. data/lib/strava/models/detailed_photos.rb +29 -1
  39. data/lib/strava/models/detailed_segment.rb +89 -2
  40. data/lib/strava/models/detailed_segment_effort.rb +92 -3
  41. data/lib/strava/models/explorer_segment.rb +55 -2
  42. data/lib/strava/models/heart_rate_zone_ranges.rb +29 -1
  43. data/lib/strava/models/kudoser.rb +29 -1
  44. data/lib/strava/models/lap.rb +62 -2
  45. data/lib/strava/models/lat_lng.rb +42 -4
  46. data/lib/strava/models/local_legend.rb +41 -1
  47. data/lib/strava/models/map.rb +31 -0
  48. data/lib/strava/models/meta_activity.rb +15 -2
  49. data/lib/strava/models/meta_athlete.rb +17 -2
  50. data/lib/strava/models/meta_club.rb +15 -1
  51. data/lib/strava/models/mixins/average_speed.rb +81 -3
  52. data/lib/strava/models/mixins/distance.rb +25 -0
  53. data/lib/strava/models/mixins/elapsed_time.rb +18 -0
  54. data/lib/strava/models/mixins/elevation_difference.rb +42 -0
  55. data/lib/strava/models/mixins/elevation_gain.rb +39 -0
  56. data/lib/strava/models/mixins/estimated_moving_time.rb +18 -0
  57. data/lib/strava/models/mixins/http_response.rb +36 -0
  58. data/lib/strava/models/mixins/moving_time.rb +18 -0
  59. data/lib/strava/models/mixins/sport_type.rb +39 -1
  60. data/lib/strava/models/mixins/start_date_local.rb +40 -24
  61. data/lib/strava/models/mixins/time_in_hours.rb +23 -0
  62. data/lib/strava/models/mixins/total_elevation_gain.rb +42 -0
  63. data/lib/strava/models/model.rb +14 -0
  64. data/lib/strava/models/photos_summary.rb +26 -2
  65. data/lib/strava/models/photos_summary_primary.rb +28 -2
  66. data/lib/strava/models/power_zone_ranges.rb +23 -1
  67. data/lib/strava/models/response.rb +18 -0
  68. data/lib/strava/models/route.rb +63 -2
  69. data/lib/strava/models/similar_activities.rb +57 -1
  70. data/lib/strava/models/split.rb +27 -2
  71. data/lib/strava/models/stats_visibility.rb +24 -1
  72. data/lib/strava/models/stream.rb +107 -0
  73. data/lib/strava/models/stream_set.rb +52 -1
  74. data/lib/strava/models/summary_activity.rb +145 -2
  75. data/lib/strava/models/summary_athlete.rb +54 -1
  76. data/lib/strava/models/summary_club.rb +61 -2
  77. data/lib/strava/models/summary_gear.rb +31 -2
  78. data/lib/strava/models/summary_pr_segment_effort.rb +32 -2
  79. data/lib/strava/models/summary_segment.rb +80 -2
  80. data/lib/strava/models/summary_segment_effort.rb +32 -1
  81. data/lib/strava/models/timed_zone_range.rb +24 -1
  82. data/lib/strava/models/token.rb +31 -0
  83. data/lib/strava/models/trend.rb +38 -1
  84. data/lib/strava/models/updatable_activity.rb +36 -1
  85. data/lib/strava/models/upload.rb +50 -1
  86. data/lib/strava/models/waypoint.rb +31 -1
  87. data/lib/strava/models/xoms.rb +35 -1
  88. data/lib/strava/models/zone_range.rb +20 -1
  89. data/lib/strava/models/zones.rb +32 -1
  90. data/lib/strava/oauth/client.rb +107 -19
  91. data/lib/strava/oauth/config.rb +41 -0
  92. data/lib/strava/version.rb +1 -1
  93. data/lib/strava/web/api_response.rb +28 -2
  94. data/lib/strava/web/client.rb +72 -2
  95. data/lib/strava/web/config.rb +40 -0
  96. data/lib/strava/web/connection.rb +39 -0
  97. data/lib/strava/web/raise_response_error.rb +47 -0
  98. data/lib/strava/web/request.rb +56 -0
  99. data/lib/strava/web/response.rb +18 -0
  100. data/lib/strava/webhooks/client.rb +108 -7
  101. data/lib/strava/webhooks/config.rb +44 -0
  102. data/lib/strava/webhooks/models/challenge.rb +40 -0
  103. data/lib/strava/webhooks/models/event.rb +50 -0
  104. data/lib/strava/webhooks/models/subscription.rb +27 -0
  105. data/lib/strava-ruby-client.rb +0 -2
  106. metadata +2 -4
  107. data/lib/strava/models/club_activity.rb +0 -22
  108. data/lib/strava/models/club_athlete.rb +0 -21
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 85404dadff6dfd290b5c0430a7f53b3f32c8a4e44e0d274225bb7f46ef8b4dc8
4
- data.tar.gz: 2455fc9a14b62a9e3d0c25fd7c2f46773b6e2d7b735392ad5addbf315a79130d
3
+ metadata.gz: bf4db074212670b76d6bd8045add5f2bfa1232ba0cf81fdf7ba66b8f0bb20f94
4
+ data.tar.gz: 78f72488ee23a2add7d9167b455eae14fd908cba008dc3fa7ee4cfcf2380c12a
5
5
  SHA512:
6
- metadata.gz: 3107a6341b8d7a94212e6cb09eda0235144c2c07b429ff081b3b5d9ee908a6ae97911f8eef07c05b5c5116b284e793abe62fbe6fdc1d8350332cc201b05400b3
7
- data.tar.gz: f6a861046c655134c025fc203793c918534922d984acd094d08c895936187989577aad58a659e8567bd742e33e521228b4e0b858f3acc100ab6cb6f15506c8b2
6
+ metadata.gz: 7af3b537e12f45ddd344ee1d059a43f667372481fb1c5e781510fb07f9bd6ab2443ea74bdc1e1f24a3a79467da8743aed973fc7c757f72f0c37b2e9347d74635
7
+ data.tar.gz: a925ee0ea3e3e056b4ae08d39e46fa6209a7279a4124c7b9a4184fa55ae59b808ce592271eeff11608dec0cb9ef81e9d85947880cf124a8b72bdc2a139b1b5b3
data/CHANGELOG.md CHANGED
@@ -1,4 +1,18 @@
1
- ### 3.0.0 (Next)
1
+ ### 3.1.0 (2026/08/29)
2
+
3
+ * [#110](https://github.com/dblock/strava-ruby-client/pull/110): Removes `club_activities`, `club_members`, and `club_admins`, which Strava retired on September 1, 2026 - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/apps/copilot-swe-agent).
4
+ * [#100](https://github.com/dblock/strava-ruby-client/pull/100): Adds comprehensive rdoc documentation - [@dblock](https://github.com/dblock).
5
+ * [#103](https://github.com/dblock/strava-ruby-client/pull/103): Migrate Danger to use the `danger-pr-comment` reusable workflow - [@dblock](https://github.com/dblock), [@Copilot](https://github.com/apps/copilot-swe-agent).
6
+ * [#104](https://github.com/dblock/strava-ruby-client/pull/104): Fixes `Danger Comment` workflow failing with a `contents: none` permissions error - [@dblock](https://github.com/dblock).
7
+ * [#102](https://github.com/dblock/strava-ruby-client/pull/102): Adds `revoke`, deprecating `deauthorize`, per Strava's June 2026/2027 developer program changes - [@dblock](https://github.com/dblock).
8
+ * [#105](https://github.com/dblock/strava-ruby-client/pull/105): Adds `total_elevation_gain`, `total_elevation_loss` and formatted helpers to `Strava::Models::Stream`, computed from altitude stream data - [@dblock](https://github.com/dblock).
9
+ * [#106](https://github.com/dblock/strava-ruby-client/pull/106): Adds test coverage reporting with [coveralls.io](https://coveralls.io) - [@dblock](https://github.com/dblock).
10
+ * [#108](https://github.com/dblock/strava-ruby-client/pull/108): Adds an integration test that verifies the real Strava API endpoint is reachable, run in CI on every push and pull request via `rake spec:integration` - [@dblock](https://github.com/dblock).
11
+ * [#107](https://github.com/dblock/strava-ruby-client/pull/107): Fixes `explore_segments` and `star_segment` raising `UncaughtThrowError` instead of `ArgumentError` for missing required arguments - [@dblock](https://github.com/dblock).
12
+ * [#107](https://github.com/dblock/strava-ruby-client/pull/107): Fixes `start_date_local` to always derive the timezone offset from the difference between `start_date` and `start_date_local`, since Strava's `timezone` property does not account for daylight saving time - [@dblock](https://github.com/dblock).
13
+ * [#109](https://github.com/dblock/strava-ruby-client/pull/109): Fixed coverage reporting to Coveralls not running on pull requests, and to report coverage from every Ruby/JRuby test matrix job merged into a single build, by switching from `coveralls_reborn`/`COVERALLS_REPO_TOKEN` to `coverallsapp/github-action`/`GITHUB_TOKEN` - [@dblock](https://github.com/dblock).
14
+
15
+ ### 3.0.0 (2025/10/24)
2
16
 
3
17
  * [#96](https://github.com/dblock/strava-ruby-client/pull/96): Updates and refactors models to spec - [@dblock](https://github.com/dblock).
4
18
  * [#98](https://github.com/dblock/strava-ruby-client/pull/98): Changes all `latlng` properties to return an instance of `Strava::Models::LatLng` - [@dblock](https://github.com/dblock).
@@ -8,7 +22,6 @@
8
22
  * [#92](https://github.com/dblock/strava-ruby-client/pull/92): Fixes `Hashie::Trash` serialization warning for `object_id` of `Strava::Webhooks::Models::Event` - [@simonneutert](https://github.com/simonneutert).
9
23
  * [#95](https://github.com/dblock/strava-ruby-client/pull/95): Fixes `club_events` returning `Strava::Models::ClubEvent` with an empty string in `created_at` - [@dblock](https://github.com/dblock).
10
24
  * [#93](https://github.com/dblock/strava-ruby-client/pull/93): Updates GitHub Actions workflows - [@simonneutert](https://github.com/simonneutert).
11
- * Your contribution here.
12
25
 
13
26
  ### 2.3.0 (2025/10/16)
14
27
 
data/README.md CHANGED
@@ -2,6 +2,7 @@
2
2
 
3
3
  [![Gem Version](https://badge.fury.io/rb/strava-ruby-client.svg)](https://badge.fury.io/rb/strava-ruby-client)
4
4
  [![Test](https://github.com/dblock/strava-ruby-client/actions/workflows/test.yml/badge.svg?branch=master)](https://github.com/dblock/strava-ruby-client/actions/workflows/test.yml)
5
+ [![Coverage Status](https://coveralls.io/repos/github/dblock/strava-ruby-client/badge.svg?branch=master)](https://coveralls.io/github/dblock/strava-ruby-client?branch=master)
5
6
 
6
7
  A complete Ruby client for the [Strava API v3](https://developers.strava.com).
7
8
 
@@ -27,12 +28,9 @@ Unlike other clients, including [strava-api-v3](https://github.com/jaredholdcrof
27
28
  - [Get Athlete Stats](#get-athlete-stats)
28
29
  - [Update Athlete](#update-athlete)
29
30
  - [Clubs](#clubs)
30
- - [List Club Activities](#list-club-activities)
31
- - [List Club Events](#list-club-events)
32
- - [List Club Administrators](#list-club-administrators)
33
- - [Get Club](#get-club)
34
- - [List Club Members](#list-club-members)
35
31
  - [List Athlete Clubs](#list-athlete-clubs)
32
+ - [Get Club](#get-club)
33
+ - [List Club Events](#list-club-events)
36
34
  - [Gears](#gears)
37
35
  - [Get Equipment](#get-equipment)
38
36
  - [Routes](#routes)
@@ -58,6 +56,7 @@ Unlike other clients, including [strava-api-v3](https://github.com/jaredholdcrof
58
56
  - [Pagination](#pagination)
59
57
  - [OAuth](#oauth)
60
58
  - [OAuth Workflow](#oauth-workflow)
59
+ - [Revoke](#revoke)
61
60
  - [Deauthorize](#deauthorize)
62
61
  - [Command Line OAuth Workflow](#command-line-oauth-workflow)
63
62
  - [Webhooks](#webhooks)
@@ -381,46 +380,22 @@ See [Strava::Models::DetailedAthlete](lib/strava/models/detailed_athlete.rb) for
381
380
 
382
381
  ### Clubs
383
382
 
384
- #### List Club Activities
385
-
386
- Retrieve recent activities from members of a specific club.
383
+ Strava removed the Club Activities, Club Members, and Club Admins endpoints on September 1, 2026 (see the [Strava API changelog](https://developers.strava.com/docs/changelog/)). The corresponding `club_activities`, `club_members`, and `club_admins` methods have been removed from this gem.
387
384
 
388
- ```ruby
389
- activities = client.club_activities(108605) # => Array[Strava::Models::ClubActivity]
390
-
391
- activity = activities.first # => Strava::Models::ClubActivity
392
-
393
- activity.name # => 'Afternoon Run'
394
- ```
395
-
396
- See [Strava::Models::ClubActivity](lib/strava/models/club_activity.rb) for all available properties. Note that Strava does not return activity or athlete ID via this API.
397
-
398
- #### List Club Events
385
+ #### List Athlete Clubs
399
386
 
400
- Retrieve recent Events from a specific club.
387
+ Returns a list of the clubs whose membership includes the authenticated athlete.
401
388
 
402
389
  ```ruby
403
- events = client.club_events(108605) # => Array[Strava::Models::ClubEvent]
404
-
405
- event = events.first # => Strava::Models::ClubEvent
406
-
407
- event.title # => 'First Group Event Ever! Yippieh!'
408
- ```
409
-
410
- See [Strava::Models::ClubEvent](lib/strava/models/club_event.rb) for all available properties.
411
-
412
- #### List Club Administrators
413
-
414
- Returns a list of the administrators of a given club.
390
+ clubs = client.athlete_clubs # => Array[Strava::Models::SummaryClub]
415
391
 
416
- ```ruby
417
- admins = client.club_admins(108605) # => Array[Strava::Models::ClubAthlete]
392
+ club = clubs.first # => Strava::Models::SummaryClub
418
393
 
419
- admin = admins.first # => Strava::Models::ClubAthlete
420
- admin.name # => 'Peter Ciaccia'
394
+ activity.name # => 'NYRR'
395
+ activity.strava_url # => 'https://www.strava.com/clubs/nyrr'
421
396
  ```
422
397
 
423
- See [Strava::Models::ClubAthlete](lib/strava/models/club_athlete.rb) for all available properties.
398
+ See [Strava::Models::SummaryClub](lib/strava/models/summary_club.rb) for all available properties.
424
399
 
425
400
  #### Get Club
426
401
 
@@ -434,33 +409,19 @@ club.name # => 'NYRR'
434
409
 
435
410
  See [Strava::Models::DetailedClub](lib/strava/models/detailed_club.rb) for all available properties.
436
411
 
437
- #### List Club Members
438
-
439
- Returns a list of the members of a given club.
440
-
441
- ```ruby
442
- members = client.club_members(108605) # => Array[Strava::Models::ClubAthlete]
443
-
444
- member = members.first # => Strava::Models::ClubAthlete
445
- member.name # => 'Peter Ciaccia'
446
- ```
447
-
448
- See [Strava::Models::ClubAthlete](lib/strava/models/club_athlete.rb) for all available properties.
449
-
450
- #### List Athlete Clubs
412
+ #### List Club Events
451
413
 
452
- Returns a list of the clubs whose membership includes the authenticated athlete.
414
+ Retrieve recent Events from a specific club.
453
415
 
454
416
  ```ruby
455
- clubs = client.athlete_clubs # => Array[Strava::Models::SummaryClub]
417
+ events = client.club_events(108605) # => Array[Strava::Models::ClubEvent]
456
418
 
457
- club = clubs.first # => Strava::Models::SummaryClub
419
+ event = events.first # => Strava::Models::ClubEvent
458
420
 
459
- activity.name # => 'NYRR'
460
- activity.strava_url # => 'https://www.strava.com/clubs/nyrr'
421
+ event.title # => 'First Group Event Ever! Yippieh!'
461
422
  ```
462
423
 
463
- See [Strava::Models::SummaryClub](lib/strava/models/summary_club.rb) for all available properties.
424
+ See [Strava::Models::ClubEvent](lib/strava/models/club_event.rb) for all available properties.
464
425
 
465
426
  ### Gears
466
427
 
@@ -508,13 +469,18 @@ gpx.tracks # => Array[GPX::Track]
508
469
 
509
470
  #### Export Route TCX
510
471
 
511
- Returns a [Training Center XML](https://en.wikipedia.org/wiki/Training_Center_XML) (TCX) data of the route. Combine with [multi_xml](https://github.com/sferik/multi_xml) to parse it.
472
+ Returns a [Training Center XML](https://en.wikipedia.org/wiki/Training_Center_XML) (TCX) data of the route. Combine with [multi_xml](https://github.com/sferik/multi_xml) or [tcx](https://github.com/dblock/tcx) to parse it.
512
473
 
513
474
  ```ruby
514
475
  data = client.export_route_tcx(16341573) # => String
515
476
 
516
477
  require 'multi_xml'
517
478
  xml = MultiXml.parse(data) # => parsed TCX
479
+
480
+ require 'tcx'
481
+ tcx = Tcx.load(data) # => Tcx::Database
482
+
483
+ tcx.courses.first.name # => 'Lower Manhattan'
518
484
  ```
519
485
 
520
486
  #### Get Route
@@ -678,6 +644,17 @@ streams.latlng # => Strava::Models::Stream
678
644
  streams.altitude # => Strava::Models::Stream
679
645
  ```
680
646
 
647
+ The Strava API doesn't return a total elevation loss (descent) property for streams, but it can be computed from an altitude stream's data.
648
+
649
+ ```ruby
650
+ streams = client.activity_streams(1946417534, keys: %w[altitude]) # => Strava::Models::StreamSet
651
+
652
+ streams.altitude.total_elevation_gain # => 725.3
653
+ streams.altitude.total_elevation_loss # => 680.1
654
+ streams.altitude.total_elevation_gain_s # => "725.3m"
655
+ streams.altitude.total_elevation_loss_s # => "680.1m"
656
+ ```
657
+
681
658
  #### Get Activity Streams
682
659
 
683
660
  Returns the given activity's streams.
@@ -866,6 +843,16 @@ response.refresh_token # => String, new refresh token
866
843
  response.expires_at # => Time, new timestamp when the access token expires
867
844
  ```
868
845
 
846
+ #### Revoke
847
+
848
+ Revoke access to an athlete's data using an instance of `Strava::API::Client`.
849
+
850
+ ```ruby
851
+ authorization = client.revoke
852
+
853
+ authorization.access_token # => String, access token being revoked
854
+ ```
855
+
869
856
  #### Deauthorize
870
857
 
871
858
  Revoke access to an athlete's data using an instance of `Strava::API::Client`.
@@ -876,6 +863,8 @@ authorization = client.deauthorize
876
863
  authorization.access_token # => String, access token being revoked
877
864
  ```
878
865
 
866
+ _Deprecated: use [`revoke`](#revoke) instead. The `oauth/deauthorize` endpoint will be retired on June 1, 2027 in favor of `oauth/revoke`._
867
+
879
868
  #### Command Line OAuth Workflow
880
869
 
881
870
  The OAuth process is web-based and you cannot obtain a token from a Strava client ID and secret without user intervention. You can, however, start a local web server to handle the OAuth redirect and open a browser from the command-line.
@@ -2,6 +2,33 @@
2
2
 
3
3
  module Strava
4
4
  module Api
5
+ #
6
+ # Main API client for interacting with the Strava API v3.
7
+ #
8
+ # This class provides a complete Ruby interface to the Strava API, including support for:
9
+ # * Activities (create, read, update, list)
10
+ # * Athletes (profile, stats, zones)
11
+ # * Clubs (details, members, activities)
12
+ # * Gear (equipment details)
13
+ # * Routes (details, GPX/TCX export)
14
+ # * Segments and Segment Efforts
15
+ # * Streams (activity, route, segment data)
16
+ # * Uploads (activity file uploads)
17
+ # * OAuth (token refresh, deauthorization)
18
+ #
19
+ # @example Create a client with an access token
20
+ # client = Strava::Api::Client.new(access_token: "your_access_token")
21
+ # athlete = client.athlete
22
+ # activities = client.athlete_activities(per_page: 10)
23
+ #
24
+ # @example Configure globally
25
+ # Strava::Api::Client.configure do |config|
26
+ # config.access_token = "your_access_token"
27
+ # end
28
+ # client = Strava::Api::Client.new
29
+ #
30
+ # @see https://developers.strava.com/docs/reference/ Strava API Documentation
31
+ #
5
32
  class Client < Strava::Web::Client
6
33
  include Endpoints::Activities
7
34
  include Endpoints::Athletes
@@ -16,6 +43,26 @@ module Strava
16
43
 
17
44
  attr_accessor(*Config::ATTRIBUTES)
18
45
 
46
+ #
47
+ # Initialize a new API client.
48
+ #
49
+ # @param [Hash] options Configuration options for the client
50
+ # @option options [String] :access_token OAuth access token for API authentication (required)
51
+ # @option options [String] :endpoint API endpoint URL (defaults to https://www.strava.com/api/v3)
52
+ # @option options [String] :user_agent User agent string for HTTP requests
53
+ # @option options [Logger] :logger Logger instance for request/response logging
54
+ # @option options [Integer] :timeout HTTP request timeout in seconds
55
+ # @option options [Integer] :open_timeout HTTP connection timeout in seconds
56
+ # @option options [String] :proxy HTTP proxy URL
57
+ # @option options [String] :ca_path Path to SSL CA certificates
58
+ # @option options [String] :ca_file Path to SSL CA certificate file
59
+ #
60
+ # @example
61
+ # client = Strava::Api::Client.new(
62
+ # access_token: "your_access_token",
63
+ # user_agent: "My Strava App/1.0"
64
+ # )
65
+ #
19
66
  def initialize(options = {})
20
67
  Config::ATTRIBUTES.each do |key|
21
68
  send("#{key}=", options[key] || Strava::Api.config.send(key))
@@ -23,15 +70,37 @@ module Strava
23
70
  super
24
71
  end
25
72
 
73
+ #
74
+ # Returns HTTP headers for API requests.
75
+ #
76
+ # @return [Hash] Headers including OAuth bearer token authorization
77
+ # @api private
78
+ #
26
79
  def headers
27
80
  { 'Authorization' => "Bearer #{access_token}" }
28
81
  end
29
82
 
30
83
  class << self
84
+ #
85
+ # Configure the API client globally.
86
+ #
87
+ # @yield [Config] Configuration object
88
+ # @return [Strava::Api::Config] Configuration object
89
+ #
90
+ # @example
91
+ # Strava::Api::Client.configure do |config|
92
+ # config.access_token = "your_access_token"
93
+ # end
94
+ #
31
95
  def configure
32
96
  block_given? ? yield(Config) : Config
33
97
  end
34
98
 
99
+ #
100
+ # Returns the configuration object.
101
+ #
102
+ # @return [Strava::Api::Config] Configuration object
103
+ #
35
104
  def config
36
105
  Config
37
106
  end
@@ -2,9 +2,25 @@
2
2
 
3
3
  module Strava
4
4
  module Api
5
+ #
6
+ # Configuration module for the Strava API client.
7
+ #
8
+ # This module manages configuration settings for the API client, including
9
+ # the API endpoint URL and access token for authentication.
10
+ #
11
+ # @example Configure the API client
12
+ # Strava::Api.configure do |config|
13
+ # config.access_token = 'your_access_token_here'
14
+ # end
15
+ #
16
+ # @example Access current configuration
17
+ # Strava::Api.config.endpoint
18
+ # # => 'https://www.strava.com/api/v3'
19
+ #
5
20
  module Config
6
21
  extend self
7
22
 
23
+ # @return [Array<Symbol>] List of configurable attributes
8
24
  ATTRIBUTES = %i[
9
25
  endpoint
10
26
  access_token
@@ -12,6 +28,14 @@ module Strava
12
28
 
13
29
  attr_accessor(*Config::ATTRIBUTES)
14
30
 
31
+ #
32
+ # Reset configuration to default values.
33
+ #
34
+ # Sets the endpoint to the default Strava API v3 URL and
35
+ # clears the access token.
36
+ #
37
+ # @return [void]
38
+ #
15
39
  def reset
16
40
  self.endpoint = 'https://www.strava.com/api/v3'
17
41
  self.access_token = nil
@@ -19,10 +43,26 @@ module Strava
19
43
  end
20
44
 
21
45
  class << self
46
+ #
47
+ # Configure the API client with a block.
48
+ #
49
+ # @yield [Config] Yields the configuration module for setup
50
+ # @return [Module] The Config module
51
+ #
52
+ # @example
53
+ # Strava::Api.configure do |config|
54
+ # config.access_token = ENV['STRAVA_ACCESS_TOKEN']
55
+ # end
56
+ #
22
57
  def configure
23
58
  block_given? ? yield(Config) : Config
24
59
  end
25
60
 
61
+ #
62
+ # Returns the current API configuration.
63
+ #
64
+ # @return [Module] The Config module
65
+ #
26
66
  def config
27
67
  Config
28
68
  end
@@ -2,11 +2,42 @@
2
2
 
3
3
  module Strava
4
4
  module Api
5
+ #
6
+ # Handles paginated iteration through API endpoints.
7
+ #
8
+ # This class provides an Enumerable interface for iterating through
9
+ # paginated API responses. It supports both traditional page-based
10
+ # pagination and cursor-based pagination.
11
+ #
12
+ # @see Strava::Api::Pagination
13
+ #
14
+ # @example Iterating through pages
15
+ # cursor = Strava::Api::Cursor.new(client, 'athlete/activities', per_page: 30)
16
+ # cursor.each do |page|
17
+ # page.each do |activity|
18
+ # puts activity.name
19
+ # end
20
+ # end
21
+ #
5
22
  class Cursor
6
23
  include Enumerable
7
24
 
8
- attr_reader :client, :path, :params
25
+ # @return [Strava::Api::Client] API client instance
26
+ attr_reader :client
9
27
 
28
+ # @return [String] API endpoint path
29
+ attr_reader :path
30
+
31
+ # @return [Hash] Query parameters for the request
32
+ attr_reader :params
33
+
34
+ #
35
+ # Initialize a new Cursor for paginated iteration.
36
+ #
37
+ # @param client [Strava::Api::Client] API client to use for requests
38
+ # @param path [String] API endpoint path to paginate
39
+ # @param params [Hash] Query parameters (excluding :limit which is removed)
40
+ #
10
41
  def initialize(client, path, params = {})
11
42
  @client = client
12
43
  @path = path