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,19 +2,75 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # Undocumented
5
+ #
6
+ # Represents statistics about similar activities.
7
+ #
8
+ # Provides comparative data about activities of the same type and route,
9
+ # including speed trends and performance metrics. This model is not documented
10
+ # in the official Strava API reference.
11
+ #
12
+ # @note This model is not documented by Strava API documentation. Properties
13
+ # are inferred from API responses.
14
+ #
15
+ # @see Strava::Models::Trend
16
+ # @see Strava::Models::DetailedActivity
17
+ #
18
+ # @example Accessing similar activity statistics
19
+ # activity = client.activity(1234567890)
20
+ # if activity.similar_activities
21
+ # similar = activity.similar_activities
22
+ # puts "Average speed: #{similar.average_speed} m/s"
23
+ # puts "Similar efforts: #{similar.effort_count}"
24
+ # puts "PR rank: #{similar.pr_rank}"
25
+ # end
26
+ #
6
27
  class SimilarActivities < Strava::Models::Response
28
+ # @return [Float, nil] Average speed across similar activities in meters per second
29
+ # @note Not documented by Strava API
7
30
  property 'average_speed'
31
+
32
+ # @return [Integer, nil] Resource state indicator
33
+ # @note Not documented by Strava API
8
34
  property 'resource_state'
35
+
36
+ # @return [Integer, nil] Number of similar efforts/activities
37
+ # @note Not documented by Strava API
9
38
  property 'effort_count'
39
+
40
+ # @return [Integer, nil] Milestone frequency indicator
41
+ # @note Not documented by Strava API
10
42
  property 'frequency_milestone'
43
+
44
+ # @return [Float, nil] Maximum average speed across similar activities in meters per second
45
+ # @note Not documented by Strava API
11
46
  property 'max_average_speed'
47
+
48
+ # @return [Float, nil] Median average speed across similar activities in meters per second
49
+ # @note Not documented by Strava API
12
50
  property 'mid_average_speed'
51
+
52
+ # @return [Float, nil] Minimum average speed across similar activities in meters per second
53
+ # @note Not documented by Strava API
13
54
  property 'min_average_speed'
55
+
56
+ # @return [Float, nil] Median speed value
57
+ # @note Not documented by Strava API
14
58
  property 'mid_speed'
59
+
60
+ # @return [Float, nil] Minimum speed value
61
+ # @note Not documented by Strava API
15
62
  property 'min_speed'
63
+
64
+ # @return [Array, nil] Array of speed values
65
+ # @note Not documented by Strava API
16
66
  property 'speeds'
67
+
68
+ # @return [Trend, nil] Trend data for similar activities
69
+ # @note Not documented by Strava API
17
70
  property 'trend', transform_with: ->(v) { Strava::Models::Trend.new(v) }
71
+
72
+ # @return [Integer, nil] Personal record rank among similar activities
73
+ # @note Not documented by Strava API
18
74
  property 'pr_rank'
19
75
  end
20
76
  end
@@ -2,17 +2,42 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-Split
5
+ #
6
+ # Represents a split/interval within an activity.
7
+ #
8
+ # Splits divide an activity into equal distance segments (e.g., per mile or per kilometer)
9
+ # with metrics for each segment. Activities typically include both metric (km) and
10
+ # standard (mile) splits.
11
+ #
12
+ # Includes helper mixins for formatting distance, time, speed, and elevation.
13
+ #
14
+ # @example Access activity splits
15
+ # activity = client.activity(1234567890)
16
+ # activity.splits_metric.each_with_index do |split, i|
17
+ # puts "KM #{i+1}: #{split.moving_time_in_hours_s} at #{split.pace_s}"
18
+ # puts "Elevation: #{split.elevation_difference}m"
19
+ # end
20
+ #
21
+ # @see https://developers.strava.com/docs/reference/#api-models-Split
22
+ #
6
23
  class Split < Strava::Models::Response
7
24
  include Mixins::AverageSpeed
8
25
  include Mixins::Distance
9
26
  include Mixins::ElapsedTime
10
27
  include Mixins::ElevationDifference
28
+
29
+ # @return [Integer] Pace zone for this split (0-5)
11
30
  property 'pace_zone'
31
+
12
32
  include Mixins::MovingTime
33
+
34
+ # @return [Integer] Split number (1-indexed)
13
35
  property 'split'
14
- # undocumented
36
+
37
+ # @return [Float] Average speed adjusted for grade/incline (in meters per second)
15
38
  property 'average_grade_adjusted_speed'
39
+
40
+ # @return [Float] Average heart rate during this split (beats per minute)
16
41
  property 'average_heartrate'
17
42
  end
18
43
  end
@@ -2,9 +2,32 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # Undocumented
5
+ #
6
+ # Represents visibility settings for activity statistics.
7
+ #
8
+ # Controls which statistics are visible to others when viewing 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
+ #
16
+ # @example Accessing stats visibility
17
+ # activity = client.activity(1234567890)
18
+ # if activity.stats_visibility
19
+ # activity.stats_visibility.each do |visibility|
20
+ # puts "#{visibility.type}: #{visibility.visibility}"
21
+ # end
22
+ # end
23
+ #
6
24
  class StatsVisibility < Strava::Models::Response
25
+ # @return [String, nil] Type of statistic (e.g., "heartrate", "power")
26
+ # @note Not documented by Strava API
7
27
  property 'type'
28
+
29
+ # @return [String, nil] Visibility setting (e.g., "everyone", "followers_only", "only_me")
30
+ # @note Not documented by Strava API
8
31
  property 'visibility'
9
32
  end
10
33
  end
@@ -2,11 +2,118 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
+ #
6
+ # Represents a single stream of time-series data from the Strava API.
7
+ #
8
+ # A Stream contains both metadata about the data collection and the actual data array.
9
+ # Common stream types include: time, distance, latlng, altitude, velocity_smooth,
10
+ # heartrate, cadence, watts, temp, moving, and grade_smooth.
11
+ #
12
+ # @see https://developers.strava.com/docs/reference/#api-Streams Strava API Streams reference
13
+ # @see Strava::Models::BaseStream
14
+ # @see Strava::Models::StreamSet
15
+ #
16
+ # @example Accessing heartrate stream data
17
+ # streams = client.activity_streams(1234567890, keys: 'heartrate,watts')
18
+ # hr_data = streams.heartrate.data
19
+ # puts "Average HR: #{hr_data.sum / hr_data.size}"
20
+ # puts "Max HR: #{hr_data.max}"
21
+ #
22
+ # @example Working with GPS coordinates
23
+ # streams = client.activity_streams(1234567890, keys: 'latlng')
24
+ # coords = streams.latlng.data # Array of [lat, lng] pairs
25
+ # coords.each do |lat, lng|
26
+ # puts "#{lat}, #{lng}"
27
+ # end
28
+ #
29
+ # @example Computing elevation gain and loss from an altitude stream
30
+ # streams = client.activity_streams(1234567890, keys: 'altitude')
31
+ # puts streams.altitude.total_elevation_gain_s # => "725.3m"
32
+ # puts streams.altitude.total_elevation_loss_s # => "680.1m"
33
+ #
5
34
  class Stream < Strava::Models::Response
35
+ # @return [Integer] Total number of data points in the original stream before any resampling
6
36
  property 'original_size'
37
+
38
+ # @return [String] Resolution of the stream data ("low", "medium", or "high")
7
39
  property 'resolution'
40
+
41
+ # @return [String] Type of series - how data points are indexed ("time" or "distance")
8
42
  property 'series_type'
43
+
44
+ # @return [Array] Array of data points. The type of data depends on the stream:
45
+ # - time: Array of integers (seconds from start)
46
+ # - distance: Array of floats (meters from start)
47
+ # - latlng: Array of [latitude, longitude] coordinate pairs
48
+ # - altitude: Array of floats (meters)
49
+ # - velocity_smooth: Array of floats (meters per second)
50
+ # - heartrate: Array of integers (beats per minute)
51
+ # - cadence: Array of integers (RPM for cycling, steps/min for running)
52
+ # - watts: Array of integers (power in watts)
53
+ # - temp: Array of integers (temperature in celsius)
54
+ # - moving: Array of booleans (true if moving, false if stopped)
55
+ # - grade_smooth: Array of floats (grade as percentage)
9
56
  property 'data'
57
+
58
+ #
59
+ # Returns the total elevation gain, calculated as the sum of all positive
60
+ # elevation increases between consecutive data points.
61
+ #
62
+ # This is only meaningful when the stream represents altitude data.
63
+ #
64
+ # @return [Float, nil] Total elevation gain in meters, or nil if data is not present
65
+ #
66
+ # @example
67
+ # streams = client.activity_streams(1234567890, keys: 'altitude')
68
+ # puts streams.altitude.total_elevation_gain # => 725.3
69
+ #
70
+ def total_elevation_gain
71
+ return if data.nil?
72
+
73
+ data.each_cons(2).sum { |a, b| b > a ? b - a : 0 }
74
+ end
75
+
76
+ #
77
+ # Returns the total elevation loss, calculated as the sum of all negative
78
+ # elevation decreases between consecutive data points.
79
+ #
80
+ # This is only meaningful when the stream represents altitude data.
81
+ #
82
+ # @return [Float, nil] Total elevation loss in meters, or nil if data is not present
83
+ #
84
+ # @example
85
+ # streams = client.activity_streams(1234567890, keys: 'altitude')
86
+ # puts streams.altitude.total_elevation_loss # => 680.1
87
+ #
88
+ def total_elevation_loss
89
+ return if data.nil?
90
+
91
+ data.each_cons(2).sum { |a, b| a > b ? a - b : 0 }
92
+ end
93
+
94
+ #
95
+ # Returns formatted total elevation gain in meters.
96
+ #
97
+ # @return [String, nil] Formatted elevation (e.g., "725.3m")
98
+ #
99
+ def total_elevation_gain_s
100
+ gain = total_elevation_gain
101
+ return if gain.nil?
102
+
103
+ format('%gm', format('%.1f', gain))
104
+ end
105
+
106
+ #
107
+ # Returns formatted total elevation loss in meters.
108
+ #
109
+ # @return [String, nil] Formatted elevation (e.g., "680.1m")
110
+ #
111
+ def total_elevation_loss_s
112
+ loss = total_elevation_loss
113
+ return if loss.nil?
114
+
115
+ format('%gm', format('%.1f', loss))
116
+ end
10
117
  end
11
118
  end
12
119
  end
@@ -2,18 +2,69 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-StreamSet
5
+ #
6
+ # Represents a collection of activity streams from the Strava API.
7
+ #
8
+ # A StreamSet is returned when requesting activity or segment effort streams
9
+ # and contains multiple synchronized time-series data streams. Each stream
10
+ # contains data points that correspond to the same moments in time or distance.
11
+ #
12
+ # @see https://developers.strava.com/docs/reference/#api-models-StreamSet Strava API StreamSet reference
13
+ # @see Strava::Models::Stream
14
+ # @see Strava::Api::Client#activity_streams
15
+ # @see Strava::Api::Client#segment_effort_streams
16
+ #
17
+ # @example Fetching and analyzing multiple streams
18
+ # streams = client.activity_streams(1234567890,
19
+ # keys: 'time,distance,heartrate,watts',
20
+ # key_by_type: true
21
+ # )
22
+ #
23
+ # # Access individual streams
24
+ # time_data = streams.time.data # Array of elapsed seconds
25
+ # hr_data = streams.heartrate.data # Array of heart rate values
26
+ # power_data = streams.watts.data # Array of power values
27
+ #
28
+ # # Calculate average power for time above threshold HR
29
+ # threshold_hr = 160
30
+ # time_data.each_with_index do |time, i|
31
+ # if hr_data[i] > threshold_hr
32
+ # puts "At #{time}s: HR=#{hr_data[i]}, Power=#{power_data[i]}W"
33
+ # end
34
+ # end
35
+ #
6
36
  class StreamSet < Strava::Models::Response
37
+ # @return [Stream, nil] Time stream - elapsed seconds from activity start
7
38
  property 'time', transform_with: ->(v) { Strava::Models::Stream.new(v) }
39
+
40
+ # @return [Stream, nil] Distance stream - meters from activity start
8
41
  property 'distance', transform_with: ->(v) { Strava::Models::Stream.new(v) }
42
+
43
+ # @return [Stream, nil] GPS coordinate stream - array of [latitude, longitude] pairs
9
44
  property 'latlng', transform_with: ->(v) { Strava::Models::Stream.new(v) }
45
+
46
+ # @return [Stream, nil] Altitude stream - elevation in meters
10
47
  property 'altitude', transform_with: ->(v) { Strava::Models::Stream.new(v) }
48
+
49
+ # @return [Stream, nil] Smoothed velocity stream - speed in meters per second
11
50
  property 'velocity_smooth', transform_with: ->(v) { Strava::Models::Stream.new(v) }
51
+
52
+ # @return [Stream, nil] Heart rate stream - beats per minute
12
53
  property 'heartrate', transform_with: ->(v) { Strava::Models::Stream.new(v) }
54
+
55
+ # @return [Stream, nil] Cadence stream - RPM for cycling, steps per minute for running
13
56
  property 'cadence', transform_with: ->(v) { Strava::Models::Stream.new(v) }
57
+
58
+ # @return [Stream, nil] Power stream - watts
14
59
  property 'watts', transform_with: ->(v) { Strava::Models::Stream.new(v) }
60
+
61
+ # @return [Stream, nil] Temperature stream - degrees celsius
15
62
  property 'temp', transform_with: ->(v) { Strava::Models::Stream.new(v) }
63
+
64
+ # @return [Stream, nil] Moving stream - boolean indicating whether athlete is moving
16
65
  property 'moving', transform_with: ->(v) { Strava::Models::Stream.new(v) }
66
+
67
+ # @return [Stream, nil] Smoothed grade stream - grade as percentage
17
68
  property 'grade_smooth', transform_with: ->(v) { Strava::Models::Stream.new(v) }
18
69
  end
19
70
  end
@@ -2,67 +2,210 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-SummaryActivity
5
+ #
6
+ # Represents a summary view of a Strava activity.
7
+ #
8
+ # A summary activity contains the most important information about an activity
9
+ # without the detailed segments, splits, and other extended data found in
10
+ # {DetailedActivity}. This model is typically returned when listing activities
11
+ # or when full details are not needed.
12
+ #
13
+ # Includes helper mixins for formatting distance, time, elevation, speed, and sport type.
14
+ #
15
+ # @example List and display activities
16
+ # activities = client.athlete_activities(per_page: 10)
17
+ # activities.each do |activity|
18
+ # puts "#{activity.name} - #{activity.distance_s} in #{activity.moving_time_in_hours_s}"
19
+ # puts activity.strava_url
20
+ # end
21
+ #
22
+ # @see DetailedActivity
23
+ # @see https://developers.strava.com/docs/reference/#api-models-SummaryActivity
24
+ #
6
25
  class SummaryActivity < Strava::Models::Response
26
+ # @return [Integer] Activity ID
7
27
  property 'id'
28
+
29
+ # @return [String, nil] External ID from the original upload source
8
30
  property 'external_id'
31
+
32
+ # @return [Integer, nil] Upload ID
9
33
  property 'upload_id'
34
+
35
+ # @return [MetaAthlete] The athlete who performed the activity
10
36
  property 'athlete', transform_with: ->(v) { Strava::Models::MetaAthlete.new(v) }
37
+
38
+ # @return [String] Activity name
11
39
  property 'name'
40
+
12
41
  include Mixins::Distance
13
42
  include Mixins::MovingTime
14
43
  include Mixins::ElapsedTime
15
44
  include Mixins::TotalElevationGain
45
+
46
+ # @return [Float, nil] Highest elevation in meters
16
47
  property 'elev_high'
48
+
49
+ # @return [Float, nil] Lowest elevation in meters
17
50
  property 'elev_low'
51
+
18
52
  include Mixins::SportType
53
+
54
+ # @return [Time] Start date and time (UTC)
19
55
  property 'start_date', transform_with: ->(v) { Time.parse(v) }
56
+
20
57
  include Mixins::StartDateLocal
58
+
59
+ # @return [String] Timezone in which the activity was recorded
21
60
  property 'timezone'
61
+
62
+ # @return [LatLng, nil] Starting coordinates [latitude, longitude]
22
63
  property 'start_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
64
+
65
+ # @return [LatLng, nil] Ending coordinates [latitude, longitude]
23
66
  property 'end_latlng', transform_with: ->(v) { Strava::Models::LatLng.new(v) }
67
+
68
+ # @return [Integer] Number of achievements (segment PRs, CRs, etc.)
24
69
  property 'achievement_count'
70
+
71
+ # @return [Integer] Number of kudos received
25
72
  property 'kudos_count'
73
+
74
+ # @return [Integer] Number of comments
26
75
  property 'comment_count'
76
+
77
+ # @return [Integer] Number of athletes who participated (group activities)
27
78
  property 'athlete_count'
79
+
80
+ # @return [Integer] Number of photos attached
28
81
  property 'photo_count'
82
+
83
+ # @return [Integer] Total number of photos including Instagram
29
84
  property 'total_photo_count'
85
+
86
+ # @return [Map] Activity map with polyline data
30
87
  property 'map', transform_with: ->(v) { Strava::Models::Map.new(v) }
88
+
89
+ # @return [Boolean] Whether this activity was on a stationary trainer
31
90
  property 'trainer'
91
+
92
+ # @return [Boolean] Whether this activity was a commute
32
93
  property 'commute'
94
+
95
+ # @return [Boolean] Whether this activity was manually entered
33
96
  property 'manual'
97
+
98
+ # @return [Boolean] Whether this activity is set to private
34
99
  property 'private'
100
+
101
+ # @return [Boolean] Whether this activity has been flagged
35
102
  property 'flagged'
103
+
104
+ # @return [Integer, nil] Workout type (e.g., 10 = Race, 11 = Workout)
36
105
  property 'workout_type'
106
+
107
+ # @return [String, nil] Upload ID as a string
37
108
  property 'upload_id_str'
109
+
110
+ # @return [Float] Average speed in meters per second
38
111
  property 'average_speed'
112
+
113
+ # @return [Float] Maximum speed in meters per second
39
114
  property 'max_speed'
115
+
116
+ # @return [Boolean] Whether the authenticated athlete has kudoed this activity
40
117
  property 'has_kudoed'
118
+
119
+ # @return [Boolean] Whether to hide this activity from the home feed
41
120
  property 'hide_from_home'
121
+
122
+ # @return [String, nil] Gear (bike/shoes) ID used for this activity
42
123
  property 'gear_id'
124
+
125
+ # @return [Float, nil] Kilojoules of energy expended
43
126
  property 'kilojoules'
127
+
128
+ # @return [Float, nil] Average power in watts
44
129
  property 'average_watts'
130
+
131
+ # @return [Boolean, nil] Whether the watts are from a power meter (true) or estimated (false)
45
132
  property 'device_watts'
133
+
134
+ # @return [Integer, nil] Maximum power in watts
46
135
  property 'max_watts'
136
+
137
+ # @return [Integer, nil] Weighted average power in watts
47
138
  property 'weighted_average_watts'
48
- # undocumented
139
+
140
+ # @note Undocumented in official API
141
+ # @return [Integer, nil] Resource state indicator
49
142
  property 'resource_state'
143
+
144
+ # @note Undocumented in official API
145
+ # @return [String, nil] Activity visibility setting (e.g., 'everyone', 'followers_only')
50
146
  property 'visibility'
147
+
148
+ # @note Undocumented in official API
149
+ # @return [Float, nil] UTC offset in seconds
51
150
  property 'utc_offset'
151
+
152
+ # @note Undocumented in official API
153
+ # @return [String, nil] City where the activity took place
52
154
  property 'location_city'
155
+
156
+ # @note Undocumented in official API
157
+ # @return [String, nil] State/province where the activity took place
53
158
  property 'location_state'
159
+
160
+ # @note Undocumented in official API
161
+ # @return [String, nil] Country where the activity took place
54
162
  property 'location_country'
163
+
164
+ # @note Undocumented in official API
165
+ # @return [Float, nil] Average cadence (RPM for cycling, steps/minute for running)
55
166
  property 'average_cadence'
167
+
168
+ # @note Undocumented in official API
169
+ # @return [Float, nil] Average temperature during the activity in Celsius
56
170
  property 'average_temp'
171
+
172
+ # @note Undocumented in official API
173
+ # @return [Boolean, nil] Whether the activity has heart rate data
57
174
  property 'has_heartrate'
175
+
176
+ # @note Undocumented in official API
177
+ # @return [Float, nil] Average heart rate in beats per minute
58
178
  property 'average_heartrate'
179
+
180
+ # @note Undocumented in official API
181
+ # @return [Float, nil] Maximum heart rate in beats per minute
59
182
  property 'max_heartrate'
183
+
184
+ # @note Undocumented in official API
185
+ # @return [Boolean, nil] Whether the athlete has opted out of heart rate display
60
186
  property 'heartrate_opt_out'
187
+
188
+ # @note Undocumented in official API
189
+ # @return [Boolean, nil] Whether to display the hide heart rate option
61
190
  property 'display_hide_heartrate_option'
191
+
192
+ # @note Undocumented in official API
193
+ # @return [Boolean, nil] Whether the activity was created from an accepted tag
62
194
  property 'from_accepted_tag'
195
+
196
+ # @note Undocumented in official API
197
+ # @return [Integer, nil] Number of personal records achieved in this activity
63
198
  property 'pr_count'
199
+
200
+ # @note Undocumented in official API
201
+ # @return [Integer, nil] Relative effort score (suffer score)
64
202
  property 'suffer_score'
65
203
 
204
+ #
205
+ # Returns the Strava web URL for this activity.
206
+ #
207
+ # @return [String] Full URL to view the activity on Strava.com
208
+ #
66
209
  def strava_url
67
210
  "https://www.strava.com/activities/#{id}"
68
211
  end
@@ -2,27 +2,80 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-SummaryAthlete
5
+ #
6
+ # Represents summary information about a Strava athlete.
7
+ #
8
+ # Contains basic profile information about an athlete. This is typically returned
9
+ # when listing kudoers, commenters, or other athletes associated with activities,
10
+ # rather than the full {DetailedAthlete} information.
11
+ #
12
+ # @example Access athlete who kudoed an activity
13
+ # kudoers = client.activity_kudos(1234567890)
14
+ # kudoers.each do |athlete|
15
+ # puts "#{athlete.name} from #{athlete.city}"
16
+ # puts athlete.strava_url
17
+ # end
18
+ #
19
+ # @see DetailedAthlete
20
+ # @see https://developers.strava.com/docs/reference/#api-models-SummaryAthlete
21
+ #
6
22
  class SummaryAthlete < Strava::Models::Response
23
+ # @return [Integer] Athlete ID
7
24
  property 'id'
25
+
26
+ # @return [Integer] Resource state indicator
8
27
  property 'resource_state'
28
+
29
+ # @return [String] First name
9
30
  property 'firstname'
31
+
32
+ # @return [String] Last name
10
33
  property 'lastname'
34
+
35
+ # @return [String, nil] URL to medium-sized profile picture
11
36
  property 'profile_medium'
37
+
38
+ # @return [String, nil] URL to full-sized profile picture
12
39
  property 'profile'
40
+
41
+ # @return [String, nil] City
13
42
  property 'city'
43
+
44
+ # @return [String, nil] State or province
14
45
  property 'state'
46
+
47
+ # @return [String, nil] Country
15
48
  property 'country'
49
+
50
+ # @return [String] Sex ('M' for male, 'F' for female)
16
51
  property 'sex'
52
+
53
+ # @return [Boolean] Whether the athlete has a premium subscription
17
54
  property 'premium'
55
+
56
+ # @return [Boolean] Whether the athlete has a Summit subscription
18
57
  property 'summit'
58
+
59
+ # @return [Time] When the athlete account was created
19
60
  property 'created_at', transform_with: ->(v) { Time.parse(v) }
61
+
62
+ # @return [Time] When the athlete account was last updated
20
63
  property 'updated_at', transform_with: ->(v) { Time.parse(v) }
21
64
 
65
+ #
66
+ # Returns the athlete's full name.
67
+ #
68
+ # @return [String, nil] Full name combining firstname and lastname, or nil if neither exists
69
+ #
22
70
  def name
23
71
  [firstname, lastname].compact.join(' ') if firstname || lastname
24
72
  end
25
73
 
74
+ #
75
+ # Returns the Strava web URL for this athlete's profile.
76
+ #
77
+ # @return [String] Full URL to view the athlete on Strava.com
78
+ #
26
79
  def strava_url
27
80
  "https://www.strava.com/athletes/#{id}"
28
81
  end