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
@@ -2,28 +2,88 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # Undocumented
5
+ #
6
+ # Represents a photo or video attached to an activity.
7
+ #
8
+ # Photos can be uploaded directly to Strava or linked from Instagram.
9
+ # This model contains URLs to various sizes of the media, timestamps,
10
+ # and metadata about the photo or video.
11
+ #
12
+ # Note: This is an undocumented Strava API endpoint.
13
+ #
14
+ # @example List activity photos
15
+ # photos = client.activity_photos(1234567890)
16
+ # photos.each do |photo|
17
+ # puts photo.caption if photo.caption
18
+ # puts "Uploaded: #{photo.uploaded_at}"
19
+ # puts "URL: #{photo.urls['0']}" if photo.urls
20
+ # puts "Video: #{photo.video_url}" if photo.video_url
21
+ # end
22
+ #
23
+ # @see Strava::Api::Client#activity_photos
24
+ #
6
25
  class DetailedPhoto < Strava::Models::Response
26
+ # @return [String] Unique identifier for the photo/video
7
27
  property 'unique_id'
28
+
29
+ # @return [Integer] ID of the athlete who uploaded the photo
8
30
  property 'athlete_id'
31
+
32
+ # @return [Integer] ID of the activity this photo is attached to
9
33
  property 'activity_id'
34
+
35
+ # @return [String] Name of the activity
10
36
  property 'activity_name'
37
+
38
+ # @return [Integer, nil] Post identifier if photo is from a social post
11
39
  property 'post_id'
40
+
41
+ # @return [Integer] Resource state indicator
12
42
  property 'resource_state'
43
+
44
+ # @return [String, nil] Photo caption/description
13
45
  property 'caption'
46
+
47
+ # @return [Integer] Type of media (1=photo, 2=video)
14
48
  property 'type'
49
+
50
+ # @return [Integer] Source of the photo (1=native Strava upload, 2=Instagram)
15
51
  property 'source'
52
+
53
+ # @return [String] Processing status
16
54
  property 'status'
55
+
56
+ # @return [Time] When the photo was uploaded to Strava
17
57
  property 'uploaded_at', transform_with: ->(v) { Time.parse(v) }
58
+
59
+ # @return [Time] When the photo was created/taken
18
60
  property 'created_at', transform_with: ->(v) { Time.parse(v) }
61
+
62
+ # @return [Time] Local time when photo was created
19
63
  property 'created_at_local', transform_with: ->(v) { Time.parse(v) }
64
+
65
+ # @return [Hash] Map of size keys to photo URLs (e.g., {"0" => "https://...", "1000" => "https://..."})
20
66
  property 'urls'
67
+
68
+ # @return [String, nil] URL to placeholder/thumbnail image
21
69
  property 'placeholder_image'
70
+
71
+ # @return [Hash] Map of size keys to dimensions [width, height]
22
72
  property 'sizes'
73
+
74
+ # @return [Boolean] Whether this is the default/cover photo for the activity
23
75
  property 'default_photo'
76
+
77
+ # @return [String, nil] Pagination cursor for photo listing
24
78
  property 'cursor'
79
+
80
+ # @return [Float, nil] Duration in seconds (for videos)
25
81
  property 'duration'
82
+
83
+ # @return [String, nil] Direct URL to video file
26
84
  property 'video_url'
85
+
86
+ # @return [Array<Float>, nil] Geographic location [latitude, longitude] where photo was taken
27
87
  property 'location'
28
88
  end
29
89
  end
@@ -2,10 +2,38 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # undocumented
5
+ #
6
+ # Represents detailed photo information for an activity.
7
+ #
8
+ # Contains the primary photo and total photo count for an activity.
9
+ # This model is not documented in the official Strava API reference.
10
+ #
11
+ # @note This model is not documented by Strava API documentation. Properties
12
+ # are inferred from API responses.
13
+ #
14
+ # @see Strava::Models::DetailedActivity
15
+ # @see Strava::Models::DetailedPhoto
16
+ #
17
+ # @example Accessing activity photos
18
+ # activity = client.activity(1234567890)
19
+ # if activity.photos
20
+ # puts "Total photos: #{activity.photos.count}"
21
+ # if activity.photos.primary
22
+ # puts "Primary photo ID: #{activity.photos.primary.id}"
23
+ # end
24
+ # end
25
+ #
6
26
  class DetailedPhotos < Strava::Models::Response
27
+ # @return [Photo, nil] The primary/featured photo for the activity
28
+ # @note Not documented by Strava API
7
29
  property 'primary', transform_with: ->(v) { Strava::Models::Photo.new(v) }
30
+
31
+ # @return [Boolean, nil] Whether to use the primary photo for display
32
+ # @note Not documented by Strava API
8
33
  property 'use_primary_photo'
34
+
35
+ # @return [Integer, nil] Total number of photos attached to the activity
36
+ # @note Not documented by Strava API
9
37
  property 'count'
10
38
  end
11
39
  end
@@ -2,39 +2,126 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-DetailedSegment
5
+ #
6
+ # Represents detailed information about a Strava segment.
7
+ #
8
+ # Segments are specific sections of road or trail where athletes can compete
9
+ # for best times. This model contains comprehensive segment information including
10
+ # location, elevation profile, statistics, and the athlete's personal records.
11
+ #
12
+ # Includes helper mixins for formatting distance and elevation.
13
+ #
14
+ # @example Get segment details
15
+ # segment = client.segment(229781)
16
+ # puts segment.name
17
+ # puts "#{segment.distance_s} with #{segment.average_grade}% average grade"
18
+ # puts "Location: #{segment.city}, #{segment.state}"
19
+ # puts "#{segment.athlete_count} athletes have ridden this segment"
20
+ #
21
+ # if segment.athlete_segment_stats
22
+ # pr = segment.athlete_segment_stats
23
+ # puts "Your PR: #{pr.elapsed_time_in_hours_s}"
24
+ # end
25
+ #
26
+ # @see SummarySegment
27
+ # @see https://developers.strava.com/docs/reference/#api-models-DetailedSegment
28
+ #
6
29
  class DetailedSegment < Strava::Models::Response
30
+ # @return [Integer] Segment ID
7
31
  property 'id'
32
+
33
+ # @return [String] Segment name
8
34
  property 'name'
35
+
36
+ # @return [String] Activity type ('Ride' or 'Run')
9
37
  property 'activity_type'
38
+
10
39
  include Mixins::Distance
40
+
41
+ # @return [Float] Average grade as a percentage
11
42
  property 'average_grade'
43
+
44
+ # @return [Float] Maximum grade as a percentage
12
45
  property 'maximum_grade'
46
+
47
+ # @return [Float] Highest elevation point in meters
13
48
  property 'elevation_high'
49
+
50
+ # @return [Float] Lowest elevation point in meters
14
51
  property 'elevation_low'
52
+
53
+ # @return [LatLng] Starting coordinates [latitude, longitude]
15
54
  property 'start_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
55
+
56
+ # @return [LatLng] Ending coordinates [latitude, longitude]
16
57
  property 'end_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
58
+
59
+ # @return [Integer] Climb category (0 = uncategorized, 1-5 = category climbs, HC = hors catégorie)
17
60
  property 'climb_category'
61
+
62
+ # @return [String, nil] City where the segment is located
18
63
  property 'city'
64
+
65
+ # @return [String, nil] State/province where the segment is located
19
66
  property 'state'
67
+
68
+ # @return [String, nil] Country where the segment is located
20
69
  property 'country'
70
+
71
+ # @return [Boolean] Whether this segment is private
21
72
  property 'private'
73
+
74
+ # @return [SummaryPRSegmentEffort, nil] The authenticated athlete's PR on this segment
22
75
  property 'athlete_pr_effort', transform_with: ->(v) { Strava::Models::SummaryPRSegmentEffort.new(v) }
76
+
77
+ # @return [SummarySegmentEffort, nil] The authenticated athlete's statistics on this segment
23
78
  property 'athlete_segment_stats', transform_with: ->(v) { Strava::Models::SummarySegmentEffort.new(v) }
79
+
80
+ # @return [Time] When the segment was created
24
81
  property 'created_at', transform_with: ->(v) { Time.parse(v) }
82
+
83
+ # @return [Time] When the segment was last updated
25
84
  property 'updated_at', transform_with: ->(v) { Time.parse(v) }
85
+
26
86
  include Mixins::TotalElevationGain
87
+
88
+ # @return [Map] Segment map with polyline data
27
89
  property 'map', transform_with: ->(v) { Strava::Models::Map.new(v) }
90
+
91
+ # @return [Integer] Total number of efforts on this segment
28
92
  property 'effort_count'
93
+
94
+ # @return [Integer] Total number of unique athletes who have attempted this segment
29
95
  property 'athlete_count'
96
+
97
+ # @return [Boolean] Whether this segment has been flagged as hazardous
30
98
  property 'hazardous'
99
+
100
+ # @return [Integer] Number of athletes who have starred this segment
31
101
  property 'star_count'
32
- # undocumented
102
+
103
+ # @note Undocumented in official API
104
+ # @return [Integer, nil] Resource state indicator
33
105
  property 'resource_state'
106
+
107
+ # @note Undocumented in official API
108
+ # @return [String, nil] Elevation profile data (deprecated, use elevation_profiles)
34
109
  property 'elevation_profile'
110
+
111
+ # @note Undocumented in official API
112
+ # @return [Array, nil] Collection of elevation profile data points
35
113
  property 'elevation_profiles'
114
+
115
+ # @note Undocumented in official API
116
+ # @return [Boolean, nil] Whether the authenticated athlete has starred this segment
36
117
  property 'starred'
118
+
119
+ # @note Undocumented in official API
120
+ # @return [Xoms, nil] QOM/KOM information for this segment
37
121
  property 'xoms', transform_with: ->(v) { Strava::Models::Xoms.new(v) }
122
+
123
+ # @note Undocumented in official API
124
+ # @return [LocalLegend, nil] Current Local Legend holder for this segment
38
125
  property 'local_legend', transform_with: ->(v) { Strava::Models::LocalLegend.new(v) }
39
126
  end
40
127
  end
@@ -2,35 +2,124 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-DetailedSegmentEffort
5
+ #
6
+ # Represents detailed information about a segment effort within an activity.
7
+ #
8
+ # A segment effort is an attempt at a defined segment (a portion of road or trail).
9
+ # The detailed version includes comprehensive statistics, rankings, achievements,
10
+ # and sensor data for the effort.
11
+ #
12
+ # @see https://developers.strava.com/docs/reference/#api-models-DetailedSegmentEffort Strava API DetailedSegmentEffort reference
13
+ # @see Strava::Models::SummarySegmentEffort
14
+ # @see Strava::Models::SummarySegment
15
+ # @see Strava::Models::Achievement
16
+ #
17
+ # @example Accessing detailed segment effort
18
+ # effort = client.segment_effort(1234567890)
19
+ #
20
+ # puts "Segment: #{effort.name}"
21
+ # puts "Time: #{effort.elapsed_time_in_hours_s}"
22
+ # puts "Moving time: #{effort.moving_time_in_hours_s}"
23
+ # puts "Distance: #{effort.distance_s}"
24
+ #
25
+ # if effort.average_watts
26
+ # puts "Avg Power: #{effort.average_watts}W"
27
+ # end
28
+ #
29
+ # if effort.average_heartrate
30
+ # puts "Avg HR: #{effort.average_heartrate} bpm (max: #{effort.max_heartrate})"
31
+ # end
32
+ #
33
+ # # Check rankings
34
+ # puts "KOM Rank: #{effort.kom_rank}" if effort.kom_rank
35
+ # puts "PR Rank: #{effort.pr_rank}" if effort.pr_rank
36
+ #
37
+ # # View achievements
38
+ # effort.achievements.each do |achievement|
39
+ # puts "Achievement: #{achievement.type} - Rank #{achievement.rank}"
40
+ # end
41
+ #
6
42
  class DetailedSegmentEffort < Strava::Models::Response
43
+ # @return [Integer] Unique identifier for this segment effort
7
44
  property 'id'
45
+
46
+ # @return [Integer] ID of the activity containing this segment effort
8
47
  property 'activity_id'
48
+
49
+ # Includes elapsed_time (total time including stops) and helper methods
9
50
  include Mixins::ElapsedTime
51
+
52
+ # @return [Time] Start time of the segment effort in UTC
10
53
  property 'start_date', transform_with: ->(v) { Time.parse(v) }
54
+
55
+ # Includes start_date_local with timezone handling
11
56
  include Mixins::StartDateLocal
57
+
58
+ # Includes distance in meters and conversion helper methods
12
59
  include Mixins::Distance
60
+
61
+ # @return [Boolean] Whether this effort achieved KOM (King/Queen of the Mountain)
13
62
  property 'is_kom'
63
+
64
+ # @return [String] Name of the segment
14
65
  property 'name'
15
- # documented as MetaActivity and MetaAthlete
66
+
67
+ # @return [MetaActivity] Reference to the parent activity
16
68
  property 'activity', transform_with: ->(v) { Strava::Models::MetaActivity.new(v) }
69
+
70
+ # @return [MetaAthlete] Reference to the athlete who performed this effort
17
71
  property 'athlete', transform_with: ->(v) { Strava::Models::MetaAthlete.new(v) }
72
+
73
+ # Includes moving_time (time excluding stops) and helper methods
18
74
  include Mixins::MovingTime
75
+
76
+ # @return [Integer] Index in the activity stream where this effort starts
19
77
  property 'start_index'
78
+
79
+ # @return [Integer] Index in the activity stream where this effort ends
20
80
  property 'end_index'
81
+
82
+ # @return [Float, nil] Average cadence during the effort (RPM for cycling, steps/min for running)
21
83
  property 'average_cadence'
84
+
85
+ # @return [Float, nil] Average power output during the effort in watts
22
86
  property 'average_watts'
87
+
88
+ # @return [Boolean, nil] Whether power data comes from a power meter device
23
89
  property 'device_watts'
90
+
91
+ # @return [Float, nil] Average heart rate during the effort in beats per minute
24
92
  property 'average_heartrate'
93
+
94
+ # @return [Integer, nil] Maximum heart rate during the effort in beats per minute
25
95
  property 'max_heartrate'
96
+
97
+ # @return [SummarySegment] The segment that was attempted
26
98
  property 'segment', transform_with: ->(v) { Strava::Models::SummarySegment.new(v) }
99
+
100
+ # @return [Integer, nil] Overall rank on this segment (null if not in top 10)
27
101
  property 'kom_rank'
102
+
103
+ # @return [Integer, nil] Personal record rank for this segment (1 for PR, 2 for 2nd best, etc.)
28
104
  property 'pr_rank'
105
+
106
+ # @return [Boolean] Whether this effort is hidden from public segment leaderboards
29
107
  property 'hidden'
30
- # undocumented
108
+
109
+ # @return [Integer] Resource state indicator
110
+ # @note Not documented by Strava API
31
111
  property 'resource_state'
112
+
113
+ # @return [Array<Achievement>] Achievements earned during this effort (PR, yearly records, etc.)
114
+ # @note Not documented by Strava API
32
115
  property 'achievements', transform_with: ->(v) { v.map { |r| Strava::Models::Achievement.new(r) } }
116
+
117
+ # @return [String, nil] Visibility setting for this effort
118
+ # @note Not documented by Strava API
33
119
  property 'visibility'
120
+
121
+ # @return [SummaryPRSegmentEffort, nil] Athlete's personal statistics for this segment
122
+ # @note Not documented by Strava API
34
123
  property 'athlete_segment_stats', transform_with: ->(v) { Strava::Models::SummaryPRSegmentEffort.new(v) }
35
124
  end
36
125
  end
@@ -2,22 +2,75 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-ExplorerSegment
5
+ #
6
+ # Represents a segment found via segment exploration.
7
+ #
8
+ # Used when searching for segments in a geographic area. Contains basic segment
9
+ # information including location, elevation, and difficulty category.
10
+ #
11
+ # @see https://developers.strava.com/docs/reference/#api-models-ExplorerSegment Strava API ExplorerSegment reference
12
+ # @see Strava::Api::Client#explore_segments
13
+ # @see Strava::Models::SummarySegment
14
+ #
15
+ # @example Exploring segments near a location
16
+ # segments = client.explore_segments(
17
+ # bounds: [37.7, -122.5, 37.8, -122.4], # [sw_lat, sw_lng, ne_lat, ne_lng]
18
+ # activity_type: 'running'
19
+ # )
20
+ #
21
+ # segments.each do |segment|
22
+ # puts "#{segment.name} (#{segment.distance_s})"
23
+ # puts " Climb: #{segment.climb_category_desc}"
24
+ # puts " Grade: #{segment.avg_grade}%"
25
+ # puts " Elevation: #{segment.elev_difference}m"
26
+ # puts " Starred: #{segment.starred}"
27
+ # end
28
+ #
6
29
  class ExplorerSegment < Strava::Models::Response
30
+ # @return [Integer] Unique identifier for this segment
7
31
  property 'id'
32
+
33
+ # @return [String] Name of the segment
8
34
  property 'name'
35
+
36
+ # @return [Integer] Climb category (0=uncategorized, 5=easiest, 1=hardest, HC=hors catégorie)
9
37
  property 'climb_category'
38
+
39
+ # @return [String] Human-readable description of climb category (e.g., "NC", "4", "3", "2", "1", "HC")
10
40
  property 'climb_category_desc'
41
+
42
+ # @return [Float] Average grade/incline as a percentage
11
43
  property 'avg_grade'
44
+
45
+ # @return [LatLng] GPS coordinates of segment start point
12
46
  property 'start_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
47
+
48
+ # @return [LatLng] GPS coordinates of segment end point
13
49
  property 'end_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
50
+
51
+ # @return [Float] Net elevation difference in meters (positive for climbs, negative for descents)
14
52
  property 'elev_difference'
53
+
54
+ # Includes distance in meters and conversion helper methods
15
55
  include Mixins::Distance
56
+
57
+ # @return [String, nil] Encoded polyline of the segment path
16
58
  property 'points'
17
- # undocumented
59
+
60
+ # @return [Integer] Resource state indicator
61
+ # @note Not documented by Strava API
18
62
  property 'resource_state'
63
+
64
+ # @return [Boolean, nil] Whether the current athlete has starred this segment
65
+ # @note Not documented by Strava API
19
66
  property 'starred'
67
+
68
+ # @return [String, nil] URL or path to elevation profile visualization
69
+ # @note Not documented by Strava API
20
70
  property 'elevation_profile'
71
+
72
+ # @return [Boolean, nil] Whether local legend feature is enabled for this segment
73
+ # @note Not documented by Strava API
21
74
  property 'local_legend_enabled'
22
75
  end
23
76
  end
@@ -2,9 +2,37 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-HeartRateZoneRanges
5
+ #
6
+ # Represents an athlete's heart rate zone configuration.
7
+ #
8
+ # Heart rate zones define intensity levels based on beats per minute.
9
+ # Athletes can use default zones or configure custom zones based on
10
+ # their fitness level and training goals.
11
+ #
12
+ # @see https://developers.strava.com/docs/reference/#api-models-HeartRateZoneRanges Strava API HeartRateZoneRanges reference
13
+ # @see Strava::Models::ZoneRange
14
+ # @see Strava::Models::Zones
15
+ #
16
+ # @example Accessing heart rate zones
17
+ # zones = client.athlete_zones
18
+ #
19
+ # if zones.heart_rate
20
+ # if zones.heart_rate.custom_zones
21
+ # puts "Using custom heart rate zones"
22
+ # else
23
+ # puts "Using default heart rate zones"
24
+ # end
25
+ #
26
+ # zones.heart_rate.zones.each_with_index do |zone, i|
27
+ # puts "Zone #{i + 1}: #{zone.min}-#{zone.max} bpm"
28
+ # end
29
+ # end
30
+ #
6
31
  class HeartRateZoneRanges < Strava::Models::Response
32
+ # @return [Boolean] Whether the athlete is using custom heart rate zones
7
33
  property 'custom_zones'
34
+
35
+ # @return [Array<ZoneRange>] Array of heart rate zone ranges
8
36
  property 'zones', transform_with: ->(v) { v.map { |r| Strava::Models::ZoneRange.new(r) } }
9
37
  end
10
38
  end
@@ -2,11 +2,39 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # undocumented
5
+ #
6
+ # Represents a user who gave kudos to an activity.
7
+ #
8
+ # Kudos are a way for athletes to show appreciation for each other's activities.
9
+ # This model is not documented in the official Strava API reference.
10
+ #
11
+ # @note This model is not documented by Strava API documentation. Properties
12
+ # are inferred from API responses.
13
+ #
14
+ # @see Strava::Api::Client#activity_kudos
15
+ #
16
+ # @example Listing kudos for an activity
17
+ # kudos = client.activity_kudos(1234567890)
18
+ # kudos.each do |kudoser|
19
+ # puts "#{kudoser.display_name} gave kudos"
20
+ # puts " Avatar: #{kudoser.avatar_url}"
21
+ # end
22
+ #
6
23
  class Kudoser < Strava::Models::Response
24
+ # @return [String, nil] URL to the athlete's profile page
25
+ # @note Not documented by Strava API
7
26
  property 'destination_url'
27
+
28
+ # @return [String, nil] Display name of the athlete who gave kudos
29
+ # @note Not documented by Strava API
8
30
  property 'display_name'
31
+
32
+ # @return [String, nil] URL to the athlete's avatar image
33
+ # @note Not documented by Strava API
9
34
  property 'avatar_url'
35
+
36
+ # @return [Boolean, nil] Whether to show the athlete's name
37
+ # @note Not documented by Strava API
10
38
  property 'show_name'
11
39
  end
12
40
  end
@@ -2,31 +2,91 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-Lap
5
+ #
6
+ # Represents a lap within an activity.
7
+ #
8
+ # Laps are splits within an activity, either created manually by the athlete
9
+ # or auto-generated by the recording device. Each lap contains metrics like
10
+ # distance, time, speed, and elevation for that specific segment of the activity.
11
+ #
12
+ # Includes helper mixins for formatting distance, time, and elevation.
13
+ #
14
+ # @example List activity laps
15
+ # laps = client.activity_laps(1234567890)
16
+ # laps.each_with_index do |lap, i|
17
+ # puts "Lap #{i+1}: #{lap.name}"
18
+ # puts "Distance: #{lap.distance_s}"
19
+ # puts "Time: #{lap.moving_time_in_hours_s}"
20
+ # puts "Elevation: #{lap.total_elevation_gain_s}"
21
+ # end
22
+ #
23
+ # @see https://developers.strava.com/docs/reference/#api-models-Lap
24
+ #
6
25
  class Lap < Strava::Models::Response
26
+ # @return [Integer] Lap ID
7
27
  property 'id'
28
+
29
+ # @return [MetaActivity] The activity this lap belongs to
8
30
  property 'activity', transform_with: ->(v) { Strava::Models::MetaActivity.new(v) }
31
+
32
+ # @return [MetaAthlete] The athlete who recorded this lap
9
33
  property 'athlete', transform_with: ->(v) { Strava::Models::MetaAthlete.new(v) }
34
+
35
+ # @return [Float, nil] Average cadence (RPM for cycling, steps/minute for running)
10
36
  property 'average_cadence'
37
+
38
+ # @return [Float] Average speed in meters per second
11
39
  property 'average_speed'
40
+
12
41
  include Mixins::Distance
13
42
  include Mixins::MovingTime
14
43
  include Mixins::ElapsedTime
44
+
45
+ # @return [Integer] Starting index in the activity's data stream
15
46
  property 'start_index'
47
+
48
+ # @return [Integer] Ending index in the activity's data stream
16
49
  property 'end_index'
50
+
51
+ # @return [Integer] The lap number (1-indexed)
17
52
  property 'lap_index'
53
+
54
+ # @return [Float] Maximum speed in meters per second
18
55
  property 'max_speed'
56
+
57
+ # @return [String] Lap name (e.g., 'Lap 1', 'Manual Lap')
19
58
  property 'name'
59
+
60
+ # @return [Integer, nil] Pace zone indicator
20
61
  property 'pace_zone'
62
+
63
+ # @return [Integer, nil] Split number within the lap
21
64
  property 'split'
65
+
66
+ # @return [Time] Start date and time (UTC)
22
67
  property 'start_date', transform_with: ->(v) { Time.parse(v) }
68
+
23
69
  include Mixins::StartDateLocal
24
70
  include Mixins::TotalElevationGain
25
- # undocumented
71
+
72
+ # @note Undocumented in official API
73
+ # @return [Integer, nil] Resource state indicator
26
74
  property 'resource_state'
75
+
76
+ # @note Undocumented in official API
77
+ # @return [Boolean, nil] Whether the watts are from a power meter (true) or estimated (false)
27
78
  property 'device_watts'
79
+
80
+ # @note Undocumented in official API
81
+ # @return [Float, nil] Average power in watts
28
82
  property 'average_watts'
83
+
84
+ # @note Undocumented in official API
85
+ # @return [Float, nil] Average heart rate in beats per minute
29
86
  property 'average_heartrate'
87
+
88
+ # @note Undocumented in official API
89
+ # @return [Float, nil] Maximum heart rate in beats per minute
30
90
  property 'max_heartrate'
31
91
  end
32
92
  end