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
@@ -3,14 +3,32 @@
3
3
  module Strava
4
4
  module Models
5
5
  module Mixins
6
+ #
7
+ # Provides estimated moving time formatting methods.
8
+ #
9
+ # Estimated moving time is Strava's prediction of how long it will take
10
+ # to complete a route based on distance, elevation, and typical speeds.
11
+ # This is commonly used for routes.
12
+ #
13
+ # @example Using estimated moving time helpers
14
+ # route = client.route(1234567)
15
+ # puts route.estimated_moving_time # => 5400 (seconds)
16
+ # puts route.estimated_moving_time_in_hours_s # => "1h30m"
17
+ #
6
18
  module EstimatedMovingTime
7
19
  extend ActiveSupport::Concern
8
20
  include TimeInHours
9
21
 
10
22
  included do
23
+ # @return [Integer] Estimated moving time in seconds
11
24
  property 'estimated_moving_time'
12
25
  end
13
26
 
27
+ #
28
+ # Returns formatted estimated moving time as hours, minutes, and seconds.
29
+ #
30
+ # @return [String, nil] Formatted time string (e.g., "1h23m45s", "45m30s", "30s")
31
+ #
14
32
  def estimated_moving_time_in_hours_s
15
33
  time_in_hours_s estimated_moving_time
16
34
  end
@@ -3,17 +3,53 @@
3
3
  module Strava
4
4
  module Models
5
5
  module Mixins
6
+ #
7
+ # Provides access to HTTP response data and rate limit information.
8
+ #
9
+ # This mixin is included in Response (the base class for most API models)
10
+ # and provides access to the underlying HTTP response, which contains
11
+ # important metadata like rate limit information.
12
+ #
13
+ # @example Checking rate limits
14
+ # activity = client.activity(1234567890)
15
+ # ratelimit = activity.http_response.ratelimit
16
+ #
17
+ # puts "15-min limit: #{ratelimit.fifteen_minutes_limit}"
18
+ # puts "15-min used: #{ratelimit.fifteen_minutes_usage}"
19
+ # puts "15-min remaining: #{ratelimit.fifteen_minutes_remaining}"
20
+ #
21
+ # puts "Daily limit: #{ratelimit.daily_limit}"
22
+ # puts "Daily used: #{ratelimit.daily_usage}"
23
+ # puts "Daily remaining: #{ratelimit.daily_remaining}"
24
+ #
25
+ # @see Strava::Web::ApiResponse
26
+ # @see Strava::Api::Ratelimit
27
+ #
6
28
  module HttpResponse
7
29
  extend ActiveSupport::Concern
8
30
 
9
31
  included do
32
+ # @return [Hash] Raw input data including HTTP response
33
+ # @api private
10
34
  attr_reader :input
11
35
 
36
+ #
37
+ # Initializes the model with input data.
38
+ #
39
+ # @param obj [Hash] Input data including 'http_response' key
40
+ #
41
+ # @api private
42
+ #
12
43
  def initialize(obj)
13
44
  @input = obj
14
45
  super
15
46
  end
16
47
 
48
+ #
49
+ # Returns the HTTP response wrapper with rate limit information.
50
+ #
51
+ # @return [Strava::Web::ApiResponse] API response wrapper
52
+ #
17
53
  def http_response
18
54
  @http_response ||= Strava::Web::ApiResponse.new(input['http_response'])
19
55
  end
@@ -3,14 +3,32 @@
3
3
  module Strava
4
4
  module Models
5
5
  module Mixins
6
+ #
7
+ # Provides moving time formatting methods.
8
+ #
9
+ # Moving time is the time spent actually moving during an activity, excluding
10
+ # stopped time. This mixin adds the moving_time property and a helper method
11
+ # to format it as hours/minutes/seconds.
12
+ #
13
+ # @example Using moving time helpers
14
+ # activity = client.activity(1234567890)
15
+ # puts activity.moving_time # => 3665 (seconds)
16
+ # puts activity.moving_time_in_hours_s # => "1h1m5s"
17
+ #
6
18
  module MovingTime
7
19
  extend ActiveSupport::Concern
8
20
  include TimeInHours
9
21
 
10
22
  included do
23
+ # @return [Integer] Moving time in seconds (excludes stopped time)
11
24
  property 'moving_time'
12
25
  end
13
26
 
27
+ #
28
+ # Returns formatted moving time as hours, minutes, and seconds.
29
+ #
30
+ # @return [String, nil] Formatted time string (e.g., "1h23m45s", "45m30s", "30s")
31
+ #
14
32
  def moving_time_in_hours_s
15
33
  time_in_hours_s moving_time
16
34
  end
@@ -3,14 +3,39 @@
3
3
  module Strava
4
4
  module Models
5
5
  module Mixins
6
+ #
7
+ # Provides sport type handling and sport-specific formatting.
8
+ #
9
+ # This mixin adds the sport_type property and provides sport-aware formatting
10
+ # for distance and pace. For example, swimming activities display distance in
11
+ # meters and pace per 100m, while other activities use kilometers and pace per km.
12
+ #
13
+ # Also provides emoji representations for various sport types.
14
+ #
15
+ # @example Using sport type helpers
16
+ # activity = client.activity(1234567890)
17
+ # puts activity.sport_type # => "Run"
18
+ # puts activity.distance_s # => "10.0km" (or "500m" for swim)
19
+ # puts activity.pace_s # => "4m30s/km" (or "1m20s/100m" for swim)
20
+ # puts activity.sport_type_emoji # => "🏃"
21
+ #
6
22
  module SportType
7
23
  extend ActiveSupport::Concern
8
24
 
9
25
  included do
10
- # deprecated, property 'type'
26
+ # @return [String] Activity sport type (e.g., "Run", "Ride", "Swim", "Hike")
27
+ # @note This replaces the deprecated 'type' property
11
28
  property 'sport_type'
12
29
  end
13
30
 
31
+ #
32
+ # Returns distance formatted appropriately for the sport type.
33
+ #
34
+ # Swimming activities display distance in meters, while all other
35
+ # activities use kilometers.
36
+ #
37
+ # @return [String, nil] Formatted distance
38
+ #
14
39
  def distance_s
15
40
  if sport_type == 'Swim'
16
41
  distance_in_meters_s
@@ -19,6 +44,14 @@ module Strava
19
44
  end
20
45
  end
21
46
 
47
+ #
48
+ # Returns pace formatted appropriately for the sport type.
49
+ #
50
+ # Swimming activities display pace per 100 meters, while all other
51
+ # activities use pace per kilometer.
52
+ #
53
+ # @return [String, nil] Formatted pace
54
+ #
22
55
  def pace_s
23
56
  case sport_type
24
57
  when 'Swim'
@@ -28,6 +61,11 @@ module Strava
28
61
  end
29
62
  end
30
63
 
64
+ #
65
+ # Returns an emoji representing the sport type.
66
+ #
67
+ # @return [String, nil] Emoji character or nil if no emoji for this sport
68
+ #
31
69
  def sport_type_emoji
32
70
  case sport_type
33
71
  when 'AlpineSki' then '⛷️'
@@ -3,16 +3,40 @@
3
3
  module Strava
4
4
  module Models
5
5
  module Mixins
6
+ #
7
+ # Provides local start date/time with timezone handling.
8
+ #
9
+ # This mixin adds the start_date_local property and handles proper timezone
10
+ # conversion. The offset is calculated from the difference between start_date
11
+ # (UTC) and start_date_local, which correctly accounts for daylight saving
12
+ # time (unlike Strava's 'timezone' property, which only reflects the zone's
13
+ # standard GMT offset).
14
+ #
15
+ # This is particularly important for activities that cross timezone boundaries
16
+ # or for displaying times in the athlete's local timezone.
17
+ #
18
+ # @example Using local start date
19
+ # activity = client.activity(1234567890)
20
+ # puts activity.start_date # => 2024-01-15 14:30:00 UTC
21
+ # puts activity.start_date_local # => 2024-01-15 09:30:00 -0500
22
+ #
6
23
  module StartDateLocal
7
24
  extend ActiveSupport::Concern
8
25
 
9
26
  included do
10
27
  property 'start_date_local', transform_with: ->(v) { ::Time.parse(v) }
11
28
 
29
+ #
30
+ # Returns the start date/time in the local timezone.
31
+ #
32
+ # Constructs a Time object with the offset calculated from the difference
33
+ # between start_date and start_date_local.
34
+ #
35
+ # @return [Time] Start date/time with local timezone
36
+ #
12
37
  def start_date_local
13
38
  extracted_datetime = self['start_date_local']
14
- # some strava object do not contain a timezone property i.e. `Lap`
15
- timezone_shift = conditional_timezone(extracted_datetime)
39
+ timezone_shift = calculate_timezone(extracted_datetime)
16
40
  ::Time.new(extracted_datetime.year,
17
41
  extracted_datetime.month,
18
42
  extracted_datetime.day,
@@ -24,37 +48,29 @@ module Strava
24
48
 
25
49
  private
26
50
 
27
- def conditional_timezone(extracted_datetime)
28
- if key?(:timezone)
29
- if timezone.include?('+')
30
- timezone_shift_string('+')
31
- elsif timezone.include?('-')
32
- timezone_shift_string('-')
33
- else
34
- raise ArgumentError 'No operator of timezone correction detectable!'
35
- end
36
- else
37
- calculate_timezone(extracted_datetime)
38
- end
39
- end
40
-
51
+ #
52
+ # Determines the timezone offset for the start date.
53
+ #
54
+ # Calculates the offset from the difference between start_date (UTC)
55
+ # and start_date_local. This is used instead of Strava's 'timezone'
56
+ # property, which reflects the zone's standard GMT offset and does
57
+ # not account for daylight saving time.
58
+ #
59
+ # @param extracted_datetime [Time] The parsed start_date_local value
60
+ # @return [String] Timezone offset string (e.g., "-05:00")
61
+ #
62
+ # @api private
63
+ #
41
64
  def calculate_timezone(extracted_datetime)
42
65
  if start_date == extracted_datetime
43
66
  timezone_diff_shift_string(0, '-')
44
67
  elsif extracted_datetime < start_date
45
68
  timezone_diff_shift_string((extracted_datetime - start_date), '-')
46
- elsif extracted_datetime > start_date
47
- timezone_diff_shift_string((extracted_datetime - start_date), '+')
48
69
  else
49
- raise ArgumentError 'No operator of timezone correction detectable!'
70
+ timezone_diff_shift_string((extracted_datetime - start_date), '+')
50
71
  end
51
72
  end
52
73
 
53
- def timezone_shift_string(operator)
54
- diff_hours = timezone.split(operator).last.to_i
55
- "#{operator}#{format_int_leading_zero(diff_hours)}:00"
56
- end
57
-
58
74
  def timezone_diff_shift_string(time_diff, operator)
59
75
  diff_hours = (time_diff.abs / 3600).to_i
60
76
  "#{operator}#{format_int_leading_zero(diff_hours)}:00"
@@ -3,11 +3,34 @@
3
3
  module Strava
4
4
  module Models
5
5
  module Mixins
6
+ #
7
+ # Provides time formatting helper methods.
8
+ #
9
+ # This is a utility mixin used by other time-related mixins (MovingTime, ElapsedTime, etc.)
10
+ # to format seconds into a human-readable hours/minutes/seconds string.
11
+ #
12
+ # @example Time formatting
13
+ # time_in_hours_s(3665) # => "1h1m5s"
14
+ # time_in_hours_s(125) # => "2m5s"
15
+ # time_in_hours_s(45) # => "45s"
16
+ # time_in_hours_s(7200) # => "2h"
17
+ #
6
18
  module TimeInHours
7
19
  extend ActiveSupport::Concern
8
20
 
9
21
  private
10
22
 
23
+ #
24
+ # Converts time in seconds to formatted string with hours, minutes, and seconds.
25
+ #
26
+ # Only includes non-zero components. For example, if there are no hours,
27
+ # the result will be "23m45s" instead of "0h23m45s".
28
+ #
29
+ # @param time [Integer, nil] Time in seconds
30
+ # @return [String, nil] Formatted time string or nil if time is nil
31
+ #
32
+ # @api private
33
+ #
11
34
  def time_in_hours_s(time)
12
35
  return unless time
13
36
 
@@ -3,33 +3,75 @@
3
3
  module Strava
4
4
  module Models
5
5
  module Mixins
6
+ #
7
+ # Provides total elevation gain conversion and formatting methods.
8
+ #
9
+ # Total elevation gain represents the cumulative upward elevation change
10
+ # during an activity. This is distinct from elevation_gain - this property
11
+ # is typically used for activities while elevation_gain is used for routes.
12
+ #
13
+ # This mixin adds the total_elevation_gain property and helper methods to
14
+ # convert and format it in meters or feet.
15
+ #
16
+ # @example Using total elevation gain helpers
17
+ # activity = client.activity(1234567890)
18
+ # puts activity.total_elevation_gain # => 725.3 (meters)
19
+ # puts activity.total_elevation_gain_s # => "725.3m"
20
+ # puts activity.total_elevation_gain_in_feet_s # => "2379.6ft"
21
+ #
6
22
  module TotalElevationGain
7
23
  extend ActiveSupport::Concern
8
24
 
9
25
  included do
26
+ # @return [Float] Total elevation gain in meters
10
27
  property 'total_elevation_gain'
11
28
  end
12
29
 
30
+ #
31
+ # Returns total elevation gain in feet.
32
+ #
33
+ # @return [Float] Total elevation gain in feet
34
+ #
13
35
  def total_elevation_gain_in_feet
14
36
  total_elevation_gain * 3.28084
15
37
  end
16
38
 
39
+ #
40
+ # Returns total elevation gain in meters (same as total_elevation_gain).
41
+ #
42
+ # @return [Float] Total elevation gain in meters
43
+ #
17
44
  def total_elevation_gain_in_meters
18
45
  total_elevation_gain
19
46
  end
20
47
 
48
+ #
49
+ # Returns formatted total elevation gain in meters.
50
+ #
51
+ # @return [String, nil] Formatted elevation (e.g., "725.3m")
52
+ #
21
53
  def total_elevation_gain_in_meters_s
22
54
  return if total_elevation_gain.nil?
23
55
 
24
56
  format('%gm', format('%.1f', total_elevation_gain_in_meters))
25
57
  end
26
58
 
59
+ #
60
+ # Returns formatted total elevation gain in feet.
61
+ #
62
+ # @return [String, nil] Formatted elevation (e.g., "2379.6ft")
63
+ #
27
64
  def total_elevation_gain_in_feet_s
28
65
  return if total_elevation_gain.nil?
29
66
 
30
67
  format('%gft', format('%.1f', total_elevation_gain_in_feet))
31
68
  end
32
69
 
70
+ #
71
+ # Returns default formatted total elevation gain (meters).
72
+ #
73
+ # @return [String, nil] Formatted elevation (e.g., "725.3m")
74
+ #
33
75
  def total_elevation_gain_s
34
76
  total_elevation_gain_in_meters_s
35
77
  end
@@ -1,6 +1,20 @@
1
1
  # frozen_string_literal: true
2
2
 
3
3
  module Strava
4
+ #
5
+ # Base model class for all Strava models.
6
+ #
7
+ # This class extends Hashie::Trash to provide a flexible data structure
8
+ # for Strava API responses. All model classes in the library inherit from this.
9
+ #
10
+ # Features:
11
+ # * Ignores undeclared properties from API responses
12
+ # * Provides hash-like access to properties
13
+ # * Supports property transformations
14
+ #
15
+ # @see Strava::Models::Response
16
+ # @see https://github.com/hashie/hashie
17
+ #
4
18
  class Model < Hashie::Trash
5
19
  include Hashie::Extensions::IgnoreUndeclared
6
20
  end
@@ -2,10 +2,34 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-PhotosSummary
5
+ #
6
+ # Represents summary photo information for an activity.
7
+ #
8
+ # Contains basic information about photos attached to an activity,
9
+ # including the count and primary photo reference.
10
+ #
11
+ # @see https://developers.strava.com/docs/reference/#api-models-PhotosSummary Strava API PhotosSummary reference
12
+ # @see Strava::Models::PhotosSummaryPrimary
13
+ # @see Strava::Models::SummaryActivity
14
+ #
15
+ # @example Accessing activity photo summary
16
+ # activity = client.activity(1234567890)
17
+ # if activity.photos && activity.photos.count > 0
18
+ # puts "This activity has #{activity.photos.count} photo(s)"
19
+ # if activity.photos.primary
20
+ # puts "Primary photo: #{activity.photos.primary.urls}"
21
+ # end
22
+ # end
23
+ #
6
24
  class PhotosSummary < Strava::Models::Response
25
+ # @return [Integer] Total number of photos attached to the activity
7
26
  property 'count'
8
- property 'use_primary_photo' # undocumented
27
+
28
+ # @return [Boolean, nil] Whether to use the primary photo for display
29
+ # @note Not documented by Strava API
30
+ property 'use_primary_photo'
31
+
32
+ # @return [PhotosSummaryPrimary, nil] The primary/featured photo reference
9
33
  property 'primary', transform_with: ->(v) { Strava::Models::PhotosSummaryPrimary.new(v) }
10
34
  end
11
35
  end
@@ -2,13 +2,39 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-PhotosSummary_primary
5
+ #
6
+ # Represents the primary photo reference in a photos summary.
7
+ #
8
+ # Contains identification and URL information for the primary photo
9
+ # of an activity.
10
+ #
11
+ # @see https://developers.strava.com/docs/reference/#api-models-PhotosSummary_primary Strava API PhotosSummary_primary reference
12
+ # @see Strava::Models::PhotosSummary
13
+ #
14
+ # @example Accessing primary photo URLs
15
+ # activity = client.activity(1234567890)
16
+ # if activity.photos&.primary
17
+ # photo = activity.photos.primary
18
+ # puts "Photo ID: #{photo.id}"
19
+ # puts "Source: #{photo.source}"
20
+ # puts "URLs: #{photo.urls}"
21
+ # end
22
+ #
6
23
  class PhotosSummaryPrimary < Strava::Models::Response
24
+ # @return [Integer, nil] Unique identifier for the photo
7
25
  property 'id'
26
+
27
+ # @return [Integer] Source of the photo (1=native Strava upload, 2=Instagram)
8
28
  property 'source'
29
+
30
+ # @return [String] Unique identifier string for the photo
9
31
  property 'unique_id'
32
+
33
+ # @return [Hash] Hash containing URLs to different sizes of the photo
10
34
  property 'urls'
11
- # undocumented
35
+
36
+ # @return [Integer, nil] Type of media (1=photo, 2=video)
37
+ # @note Not documented by Strava API
12
38
  property 'media_type'
13
39
  end
14
40
  end
@@ -2,8 +2,30 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-PowerZoneRanges
5
+ #
6
+ # Represents an athlete's power zone configuration.
7
+ #
8
+ # Power zones define intensity levels based on watts output. These are
9
+ # typically used for cycling training and are often based on FTP
10
+ # (Functional Threshold Power).
11
+ #
12
+ # @see https://developers.strava.com/docs/reference/#api-models-PowerZoneRanges Strava API PowerZoneRanges reference
13
+ # @see Strava::Models::ZoneRange
14
+ # @see Strava::Models::Zones
15
+ #
16
+ # @example Accessing power zones
17
+ # zones = client.athlete_zones
18
+ #
19
+ # if zones.power
20
+ # zones.power.zones.each_with_index do |zone, i|
21
+ # puts "Power Zone #{i + 1}: #{zone.min}-#{zone.max}W"
22
+ # end
23
+ # else
24
+ # puts "No power zones configured"
25
+ # end
26
+ #
6
27
  class PowerZoneRanges < Strava::Models::Response
28
+ # @return [Array<ZoneRange>] Array of power zone ranges in watts
7
29
  property 'zones', transform_with: ->(v) { v.map { |r| Strava::Models::ZoneRange.new(r) } }
8
30
  end
9
31
  end
@@ -2,6 +2,24 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
+ #
6
+ # Base response model for all API responses.
7
+ #
8
+ # This class serves as the parent for all model classes that represent API responses.
9
+ # It includes the HttpResponse mixin which provides access to HTTP response data
10
+ # including rate limit information.
11
+ #
12
+ # Most API models inherit from this class to gain access to the http_response method,
13
+ # which can be used to inspect rate limits and other response metadata.
14
+ #
15
+ # @example Accessing rate limit information
16
+ # activity = client.activity(1234567890)
17
+ # ratelimit = activity.http_response.ratelimit
18
+ # puts "Remaining requests: #{ratelimit.fifteen_minutes_remaining}"
19
+ #
20
+ # @see Mixins::HttpResponse
21
+ # @see Strava::Api::Ratelimit
22
+ #
5
23
  class Response < Model
6
24
  include Mixins::HttpResponse
7
25
  end
@@ -2,28 +2,89 @@
2
2
 
3
3
  module Strava
4
4
  module Models
5
- # https://developers.strava.com/docs/reference/#api-models-Route
5
+ #
6
+ # Represents a Strava route.
7
+ #
8
+ # Routes are planned courses that athletes can follow for activities.
9
+ # They include map data, waypoints, and estimated moving time. Routes can
10
+ # be exported as GPX or TCX files for use with GPS devices.
11
+ #
12
+ # Includes helper mixins for formatting distance, elevation gain, and time.
13
+ #
14
+ # @example Get and display route information
15
+ # route = client.route(1234567)
16
+ # puts route.name
17
+ # puts route.description
18
+ # puts "Distance: #{route.distance_s}"
19
+ # puts "Elevation gain: #{route.elevation_gain_s}"
20
+ # puts "Estimated time: #{route.estimated_moving_time_in_hours_s}"
21
+ #
22
+ # @example Export route as GPX
23
+ # gpx_data = client.export_route_gpx(route.id)
24
+ # File.write('route.gpx', gpx_data)
25
+ #
26
+ # @see Strava::Api::Client#route
27
+ # @see Strava::Api::Client#export_route_gpx
28
+ # @see Strava::Api::Client#export_route_tcx
29
+ # @see https://developers.strava.com/docs/reference/#api-models-Route
30
+ #
6
31
  class Route < Strava::Models::Response
32
+ # @return [SummaryAthlete] The athlete who created this route
7
33
  property 'athlete', transform_with: ->(v) { Strava::Models::SummaryAthlete.new(v) }
34
+
35
+ # @return [String, nil] Route description
8
36
  property 'description'
37
+
9
38
  include Mixins::Distance
10
39
  include Mixins::ElevationGain
40
+
41
+ # @return [Integer] Route ID
11
42
  property 'id'
43
+
44
+ # @return [String] Route ID as a string
12
45
  property 'id_str'
46
+
47
+ # @return [Map] Route map with polyline data
13
48
  property 'map', transform_with: ->(v) { Strava::Models::Map.new(v) }
49
+
50
+ # @return [String] Route name
14
51
  property 'name'
52
+
53
+ # @return [Boolean] Whether this route is private
15
54
  property 'private'
55
+
56
+ # @return [Boolean] Whether this route has been starred by the authenticated athlete
16
57
  property 'starred'
58
+
59
+ # @return [Time] Timestamp for the route
17
60
  property 'timestamp', transform_with: ->(v) { Time.at(v) }
61
+
62
+ # @return [Integer] Route type (1 = Ride, 2 = Run)
18
63
  property 'type'
64
+
65
+ # @return [Integer] Route sub-type for additional categorization
19
66
  property 'sub_type'
67
+
68
+ # @return [Time] When the route was created
20
69
  property 'created_at', transform_with: ->(v) { Time.parse(v) }
70
+
71
+ # @return [Time] When the route was last updated
21
72
  property 'updated_at', transform_with: ->(v) { Time.parse(v) }
73
+
22
74
  include Mixins::EstimatedMovingTime
75
+
76
+ # @return [Array<SummarySegment>] Segments along this route
23
77
  property 'segments', transform_with: ->(v) { v.map { |r| Strava::Models::SummarySegment.new(r) } }
78
+
79
+ # @return [Array<Waypoint>] Waypoints along this route
24
80
  property 'waypoints', transform_with: ->(v) { v.map { |r| Strava::Models::Waypoint.new(r) } }
25
- # undocumented
81
+
82
+ # @note Undocumented in official API
83
+ # @return [Hash, nil] URLs to map images at various sizes
26
84
  property 'map_urls'
85
+
86
+ # @note Undocumented in official API
87
+ # @return [Integer, nil] Resource state indicator
27
88
  property 'resource_state'
28
89
  end
29
90
  end