themoviedb-api 0.7.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 (172) hide show
  1. checksums.yaml +7 -0
  2. data/.gitignore +90 -0
  3. data/.ruby-gemset +1 -0
  4. data/.ruby-version +1 -0
  5. data/.travis.yml +6 -0
  6. data/Gemfile +4 -0
  7. data/Gemfile.lock +64 -0
  8. data/README.md +6 -0
  9. data/lib/tmdb.rb +62 -0
  10. data/lib/tmdb/account.rb +4 -0
  11. data/lib/tmdb/api.rb +26 -0
  12. data/lib/tmdb/authentication.rb +4 -0
  13. data/lib/tmdb/backdrop.rb +4 -0
  14. data/lib/tmdb/certification.rb +27 -0
  15. data/lib/tmdb/change.rb +44 -0
  16. data/lib/tmdb/change_item.rb +4 -0
  17. data/lib/tmdb/collection.rb +32 -0
  18. data/lib/tmdb/company.rb +21 -0
  19. data/lib/tmdb/configuration.rb +10 -0
  20. data/lib/tmdb/country.rb +4 -0
  21. data/lib/tmdb/credit.rb +26 -0
  22. data/lib/tmdb/discover.rb +27 -0
  23. data/lib/tmdb/error.rb +4 -0
  24. data/lib/tmdb/find.rb +47 -0
  25. data/lib/tmdb/genre.rb +32 -0
  26. data/lib/tmdb/image.rb +25 -0
  27. data/lib/tmdb/job.rb +13 -0
  28. data/lib/tmdb/keyword.rb +21 -0
  29. data/lib/tmdb/language.rb +4 -0
  30. data/lib/tmdb/list.rb +4 -0
  31. data/lib/tmdb/media.rb +4 -0
  32. data/lib/tmdb/movie.rb +173 -0
  33. data/lib/tmdb/multi.rb +4 -0
  34. data/lib/tmdb/network.rb +10 -0
  35. data/lib/tmdb/person.rb +91 -0
  36. data/lib/tmdb/poster.rb +4 -0
  37. data/lib/tmdb/rating.rb +4 -0
  38. data/lib/tmdb/release.rb +4 -0
  39. data/lib/tmdb/resource.rb +30 -0
  40. data/lib/tmdb/review.rb +10 -0
  41. data/lib/tmdb/search.rb +69 -0
  42. data/lib/tmdb/struct.rb +30 -0
  43. data/lib/tmdb/translation.rb +4 -0
  44. data/lib/tmdb/tv.rb +165 -0
  45. data/lib/tmdb/tv/episode.rb +89 -0
  46. data/lib/tmdb/tv/season.rb +91 -0
  47. data/lib/tmdb/utils.rb +50 -0
  48. data/lib/tmdb/version.rb +3 -0
  49. data/lib/tmdb/video.rb +4 -0
  50. data/spec/api_spec.rb +44 -0
  51. data/spec/certification_spec.rb +62 -0
  52. data/spec/change_spec.rb +71 -0
  53. data/spec/collection_spec.rb +69 -0
  54. data/spec/company_spec.rb +50 -0
  55. data/spec/configuration_spec.rb +43 -0
  56. data/spec/credit_spec.rb +49 -0
  57. data/spec/discover_spec.rb +54 -0
  58. data/spec/find_spec.rb +105 -0
  59. data/spec/genre_spec.rb +75 -0
  60. data/spec/job_spec.rb +39 -0
  61. data/spec/keyword_spec.rb +52 -0
  62. data/spec/movie_spec.rb +362 -0
  63. data/spec/network_spec.rb +33 -0
  64. data/spec/person_spec.rb +201 -0
  65. data/spec/resource_spec.rb +47 -0
  66. data/spec/review_spec.rb +33 -0
  67. data/spec/search_spec.rb +161 -0
  68. data/spec/spec_helper.rb +37 -0
  69. data/spec/tv/episode_spec.rb +154 -0
  70. data/spec/tv/season_spec.rb +144 -0
  71. data/spec/tv_spec.rb +352 -0
  72. data/spec/vcr/certification/movie_list.yml +305 -0
  73. data/spec/vcr/certification/tv_list.yml +318 -0
  74. data/spec/vcr/change/movie.yml +58 -0
  75. data/spec/vcr/change/person.yml +58 -0
  76. data/spec/vcr/change/tv.yml +58 -0
  77. data/spec/vcr/collection/backdrops.yml +58 -0
  78. data/spec/vcr/collection/detail.yml +73 -0
  79. data/spec/vcr/collection/posters.yml +58 -0
  80. data/spec/vcr/company/detail.yml +56 -0
  81. data/spec/vcr/company/movies.yml +363 -0
  82. data/spec/vcr/configuration/get.yml +50 -0
  83. data/spec/vcr/credit/detail.yml +61 -0
  84. data/spec/vcr/discover/movie.yml +361 -0
  85. data/spec/vcr/discover/tv.yml +401 -0
  86. data/spec/vcr/find/movie.yml +64 -0
  87. data/spec/vcr/find/people.yml +114 -0
  88. data/spec/vcr/find/tv_episode.yml +66 -0
  89. data/spec/vcr/find/tv_season.yml +66 -0
  90. data/spec/vcr/find/tv_serie.yml +79 -0
  91. data/spec/vcr/genre/movie_list.yml +57 -0
  92. data/spec/vcr/genre/movies.yml +330 -0
  93. data/spec/vcr/genre/tv_list.yml +58 -0
  94. data/spec/vcr/job/list.yml +128 -0
  95. data/spec/vcr/keyword/detail.yml +56 -0
  96. data/spec/vcr/keyword/movies.yml +344 -0
  97. data/spec/vcr/movie/alternative_titles.yml +69 -0
  98. data/spec/vcr/movie/backdrops.yml +58 -0
  99. data/spec/vcr/movie/cast.yml +225 -0
  100. data/spec/vcr/movie/changes.yml +57 -0
  101. data/spec/vcr/movie/crew.yml +225 -0
  102. data/spec/vcr/movie/detail.yml +69 -0
  103. data/spec/vcr/movie/director.yml +225 -0
  104. data/spec/vcr/movie/keywords.yml +57 -0
  105. data/spec/vcr/movie/latest.yml +60 -0
  106. data/spec/vcr/movie/lists.yml +157 -0
  107. data/spec/vcr/movie/now_playing.yml +331 -0
  108. data/spec/vcr/movie/popular.yml +361 -0
  109. data/spec/vcr/movie/posters.yml +58 -0
  110. data/spec/vcr/movie/releases.yml +57 -0
  111. data/spec/vcr/movie/reviews.yml +56 -0
  112. data/spec/vcr/movie/similar.yml +354 -0
  113. data/spec/vcr/movie/top_rated.yml +343 -0
  114. data/spec/vcr/movie/translations.yml +96 -0
  115. data/spec/vcr/movie/upcoming.yml +313 -0
  116. data/spec/vcr/movie/videos.yml +57 -0
  117. data/spec/vcr/network/detail.yml +56 -0
  118. data/spec/vcr/person/changes.yml +61 -0
  119. data/spec/vcr/person/combined_credits.yml +317 -0
  120. data/spec/vcr/person/detail.yml +72 -0
  121. data/spec/vcr/person/external_ids.yml +56 -0
  122. data/spec/vcr/person/images.yml +56 -0
  123. data/spec/vcr/person/latest.yml +61 -0
  124. data/spec/vcr/person/movie_credits.yml +293 -0
  125. data/spec/vcr/person/popular.yml +1116 -0
  126. data/spec/vcr/person/tagged_images.yml +458 -0
  127. data/spec/vcr/person/tv_credits.yml +82 -0
  128. data/spec/vcr/resource/configuration_get.yml +50 -0
  129. data/spec/vcr/review/detail.yml +66 -0
  130. data/spec/vcr/search/collection.yml +58 -0
  131. data/spec/vcr/search/company.yml +70 -0
  132. data/spec/vcr/search/keyword.yml +61 -0
  133. data/spec/vcr/search/list.yml +70 -0
  134. data/spec/vcr/search/movie.yml +335 -0
  135. data/spec/vcr/search/multi.yml +219 -0
  136. data/spec/vcr/search/person.yml +117 -0
  137. data/spec/vcr/search/tv.yml +300 -0
  138. data/spec/vcr/tv/airing_today.yml +503 -0
  139. data/spec/vcr/tv/alternative_titles.yml +59 -0
  140. data/spec/vcr/tv/backdrops.yml +58 -0
  141. data/spec/vcr/tv/cast.yml +86 -0
  142. data/spec/vcr/tv/changes.yml +58 -0
  143. data/spec/vcr/tv/content_ratings.yml +56 -0
  144. data/spec/vcr/tv/crew.yml +86 -0
  145. data/spec/vcr/tv/detail.yml +71 -0
  146. data/spec/vcr/tv/episode/cast.yml +70 -0
  147. data/spec/vcr/tv/episode/changes.yml +66 -0
  148. data/spec/vcr/tv/episode/crew.yml +70 -0
  149. data/spec/vcr/tv/episode/detail.yml +68 -0
  150. data/spec/vcr/tv/episode/external_ids.yml +56 -0
  151. data/spec/vcr/tv/episode/guest_stars.yml +70 -0
  152. data/spec/vcr/tv/episode/posters.yml +58 -0
  153. data/spec/vcr/tv/episode/videos.yml +56 -0
  154. data/spec/vcr/tv/external_ids.yml +56 -0
  155. data/spec/vcr/tv/keywords.yml +59 -0
  156. data/spec/vcr/tv/latest.yml +97 -0
  157. data/spec/vcr/tv/on_the_air.yml +421 -0
  158. data/spec/vcr/tv/popular.yml +401 -0
  159. data/spec/vcr/tv/posters.yml +58 -0
  160. data/spec/vcr/tv/season/cast.yml +69 -0
  161. data/spec/vcr/tv/season/changes.yml +69 -0
  162. data/spec/vcr/tv/season/crew.yml +69 -0
  163. data/spec/vcr/tv/season/detail.yml +649 -0
  164. data/spec/vcr/tv/season/external_ids.yml +56 -0
  165. data/spec/vcr/tv/season/posters.yml +58 -0
  166. data/spec/vcr/tv/season/videos.yml +72 -0
  167. data/spec/vcr/tv/similar.yml +441 -0
  168. data/spec/vcr/tv/top_rated.yml +454 -0
  169. data/spec/vcr/tv/translations.yml +95 -0
  170. data/spec/vcr/tv/videos.yml +57 -0
  171. data/themoviedb-api.gemspec +30 -0
  172. metadata +433 -0
@@ -0,0 +1,4 @@
1
+ module Tmdb
2
+ class Poster < Struct
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Tmdb
2
+ class Rating < Struct
3
+ end
4
+ end
@@ -0,0 +1,4 @@
1
+ module Tmdb
2
+ class Release < Struct
3
+ end
4
+ end
@@ -0,0 +1,30 @@
1
+ module Tmdb
2
+ class Resource
3
+
4
+ include Utils
5
+
6
+ attr_reader :params, :query_url
7
+
8
+ def initialize(query_url, filters={})
9
+ @params = filters
10
+ @query_url = query_url
11
+ end
12
+
13
+ def get
14
+ options = Api.params.merge(@params)
15
+
16
+ begin
17
+ response = Api.get(@query_url, query: options)
18
+ rescue Net::HTTP::Exception
19
+ raise Tmdb::Error, 'Network Exception: TMDB API endpoint is not reachable.'
20
+ end
21
+
22
+ if has_errors?(response)
23
+ raise Tmdb::Error, response['status_message']
24
+ end
25
+
26
+ response.to_h
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,10 @@
1
+ module Tmdb
2
+ class Review < Struct
3
+
4
+ def self.detail(keyword_id, filters={})
5
+ result = Resource.new("/review/#{keyword_id}", filters).get
6
+ self.new(result)
7
+ end
8
+
9
+ end
10
+ end
@@ -0,0 +1,69 @@
1
+ module Tmdb
2
+ class Search < Struct
3
+
4
+ def self.company(query, filters={})
5
+ filters.merge!(query: clean_query_param(query))
6
+
7
+ result = Resource.new('/search/company', filters).get
8
+ Company.new(result)
9
+ end
10
+
11
+ def self.collection(query, filters={})
12
+ filters.merge!(query: clean_query_param(query))
13
+
14
+ result = Resource.new('/search/collection', filters).get
15
+ Collection.new(result)
16
+ end
17
+
18
+ def self.keyword(query, filters={})
19
+ filters.merge!(query: clean_query_param(query))
20
+
21
+ result = Resource.new('/search/keyword', filters).get
22
+ Keyword.new(result)
23
+ end
24
+
25
+ def self.list(query, filters={})
26
+ filters.merge!(query: clean_query_param(query))
27
+
28
+ result = Resource.new('/search/list', filters).get
29
+ Tmdb::List.new(result)
30
+ end
31
+
32
+ def self.movie(query, filters={})
33
+ filters.merge!(query: clean_query_param(query))
34
+
35
+ result = Resource.new('/search/movie', filters).get
36
+ Movie.new(result)
37
+ end
38
+
39
+ def self.multi(query, filters={})
40
+ filters.merge!(query: clean_query_param(query))
41
+
42
+ result = Resource.new('/search/multi', filters).get
43
+ Multi.new(result)
44
+ end
45
+
46
+ def self.person(query, filters={})
47
+ filters.merge!(query: clean_query_param(query))
48
+
49
+ result = Resource.new('/search/person', filters).get
50
+ person = Person.new(result)
51
+ person.convert_known_for_multiple!
52
+ person
53
+ end
54
+
55
+ def self.tv(query, filters={})
56
+ filters.merge!(query: clean_query_param(query))
57
+
58
+ result = Resource.new('/search/tv', filters).get
59
+ TV.new(result)
60
+ end
61
+
62
+ def self.clean_query_param(query)
63
+ CGI.escape(query)
64
+ end
65
+
66
+ private_class_method :clean_query_param
67
+
68
+ end
69
+ end
@@ -0,0 +1,30 @@
1
+ module Tmdb
2
+ class Struct < OpenStruct
3
+
4
+ def initialize(data=nil)
5
+ @table = {}
6
+
7
+ if data
8
+ data.each do |k,v|
9
+ @table[k.to_sym] = analyze_value(v)
10
+
11
+ new_ostruct_member(k)
12
+ end
13
+ end
14
+ end
15
+
16
+ def analyze_value(v)
17
+ case
18
+ when v.is_a?(Hash)
19
+ self.class.new(v)
20
+ when v.is_a?(Array)
21
+ v.map do |element|
22
+ analyze_value(element)
23
+ end
24
+ else
25
+ v
26
+ end
27
+ end
28
+
29
+ end
30
+ end
@@ -0,0 +1,4 @@
1
+ module Tmdb
2
+ class Translation < Struct
3
+ end
4
+ end
data/lib/tmdb/tv.rb ADDED
@@ -0,0 +1,165 @@
1
+ module Tmdb
2
+ class TV < Struct
3
+
4
+ def self.detail(id, filters={})
5
+ result = Resource.new("/tv/#{id}", filters).get
6
+
7
+ create_new_instance_with_normalized_data(result)
8
+ end
9
+
10
+ def self.alternative_titles(id, filters={})
11
+ result = Resource.new("/tv/#{id}/alternative_titles", filters).get
12
+
13
+ result['results'].map do |entry|
14
+ self.new(entry)
15
+ end
16
+ end
17
+
18
+ def self.changes(id, filters={})
19
+ result = Resource.new("/tv/#{id}/changes", filters).get
20
+
21
+ result['changes'].map do |entry|
22
+ change = Change.new(entry)
23
+ change.convert_items!
24
+ change
25
+ end
26
+ end
27
+
28
+ def self.content_ratings(id, filters={})
29
+ result = Resource.new("/tv/#{id}/content_ratings", filters).get
30
+
31
+ result['results'].map do |entry|
32
+ Rating.new(entry)
33
+ end
34
+ end
35
+
36
+ def self.cast(id, filters={})
37
+ result = Resource.new("/tv/#{id}/credits", filters).get
38
+
39
+ result['cast'].map do |entry|
40
+ Person.new(entry)
41
+ end
42
+ end
43
+
44
+ def self.crew(id, filters={})
45
+ result = Resource.new("/tv/#{id}/credits", filters).get
46
+
47
+ result['crew'].map do |entry|
48
+ Person.new(entry)
49
+ end
50
+ end
51
+
52
+ def self.external_ids(id, filters={})
53
+ result = Resource.new("/tv/#{id}/external_ids", filters).get
54
+ self.new(result)
55
+ end
56
+
57
+ def self.backdrops(id, filters={})
58
+ result = Resource.new("/tv/#{id}/images", filters).get
59
+
60
+ result['backdrops'].map do |entry|
61
+ Backdrop.new(entry)
62
+ end
63
+ end
64
+
65
+ def self.posters(id, filters={})
66
+ result = Resource.new("/tv/#{id}/images", filters).get
67
+
68
+ result['posters'].map do |entry|
69
+ Poster.new(entry)
70
+ end
71
+ end
72
+
73
+ def self.keywords(id, filters={})
74
+ result = Resource.new("/tv/#{id}/keywords", filters).get
75
+
76
+ result['results'].map do |entry|
77
+ Keyword.new(entry)
78
+ end
79
+ end
80
+
81
+ def self.similar(id, filters={})
82
+ result = Resource.new("/tv/#{id}/similar", filters).get
83
+ self.new(result)
84
+ end
85
+
86
+ def self.translations(id, filters={})
87
+ result = Resource.new("/tv/#{id}/translations", filters).get
88
+
89
+ result['translations'].map do |entry|
90
+ Translation.new(entry)
91
+ end
92
+ end
93
+
94
+ def self.videos(id, filters={})
95
+ result = Resource.new("/tv/#{id}/videos", filters).get
96
+
97
+ result['results'].map do |entry|
98
+ Video.new(entry)
99
+ end
100
+ end
101
+
102
+ def self.latest(filters={})
103
+ result = Resource.new('/tv/latest', filters).get
104
+
105
+ create_new_instance_with_normalized_data(result)
106
+ end
107
+
108
+ def self.on_the_air(filters={})
109
+ result = Resource.new('/tv/on_the_air', filters).get
110
+ self.new(result)
111
+ end
112
+
113
+ def self.airing_today(filters={})
114
+ result = Resource.new('/tv/airing_today', filters).get
115
+ self.new(result)
116
+ end
117
+
118
+ def self.top_rated(filters={})
119
+ result = Resource.new('/tv/top_rated', filters).get
120
+ self.new(result)
121
+ end
122
+
123
+ def self.popular(filters={})
124
+ result = Resource.new('/tv/popular', filters).get
125
+ self.new(result)
126
+ end
127
+
128
+ def self.create_new_instance_with_normalized_data(result)
129
+ tv = self.new(
130
+ result.except(
131
+ 'created_by',
132
+ 'networks',
133
+ 'seasons',
134
+ 'genres',
135
+ 'production_companies'
136
+ )
137
+ )
138
+
139
+ tv.created_by = result['created_by'].map do |person|
140
+ Person.new(person)
141
+ end
142
+
143
+ tv.networks = result['networks'].map do |network|
144
+ Network.new(network)
145
+ end
146
+
147
+ tv.seasons = result['seasons'].map do |season|
148
+ Tv::Season.new(season)
149
+ end
150
+
151
+ tv.genres = result['genres'].map do |genre|
152
+ Genre.new(genre)
153
+ end
154
+
155
+ tv.production_companies = result['production_companies'].map do |company|
156
+ Company.new(company)
157
+ end
158
+
159
+ tv
160
+ end
161
+
162
+ private_class_method :create_new_instance_with_normalized_data
163
+
164
+ end
165
+ end
@@ -0,0 +1,89 @@
1
+ module Tmdb
2
+ module Tv
3
+ class Episode < Struct
4
+
5
+ def self.detail(id, season_number, episode_number, filters={})
6
+ result = Resource.new("/tv/#{id}/season/#{season_number}/episode/#{episode_number}", filters).get
7
+
8
+ create_new_instance_with_normalized_data(result)
9
+ end
10
+
11
+ def self.changes(id, filters={})
12
+ result = Resource.new("/tv/episode/#{id}/changes", filters).get
13
+
14
+ result['changes'].map do |entry|
15
+ change = Change.new(entry)
16
+ change.convert_items!
17
+ change
18
+ end
19
+ end
20
+
21
+ def self.cast(id, season_number, episode_number, filters={})
22
+ result = Resource.new("/tv/#{id}/season/#{season_number}/episode/#{episode_number}/credits", filters).get
23
+
24
+ result['cast'].map do |entry|
25
+ Person.new(entry)
26
+ end
27
+ end
28
+
29
+ def self.crew(id, season_number, episode_number, filters={})
30
+ result = Resource.new("/tv/#{id}/season/#{season_number}/episode/#{episode_number}/credits", filters).get
31
+
32
+ result['crew'].map do |entry|
33
+ Person.new(entry)
34
+ end
35
+ end
36
+
37
+ def self.guest_stars(id, season_number, episode_number, filters={})
38
+ result = Resource.new("/tv/#{id}/season/#{season_number}/episode/#{episode_number}/credits", filters).get
39
+
40
+ result['guest_stars'].map do |entry|
41
+ Person.new(entry)
42
+ end
43
+ end
44
+
45
+ def self.external_ids(id, season_number, episode_number, filters={})
46
+ result = Resource.new("/tv/#{id}/season/#{season_number}/episode/#{episode_number}/external_ids", filters).get
47
+ self.new(result)
48
+ end
49
+
50
+ def self.posters(id, season_number, episode_number, filters={})
51
+ result = Resource.new("/tv/#{id}/season/#{season_number}/episode/#{episode_number}/images", filters).get
52
+
53
+ result['stills'].map do |entry|
54
+ Poster.new(entry)
55
+ end
56
+ end
57
+
58
+ def self.videos(id, season_number, episode_number, filters={})
59
+ result = Resource.new("/tv/#{id}/season/#{season_number}/episode/#{episode_number}/videos", filters).get
60
+
61
+ result['results'].map do |entry|
62
+ Video.new(entry)
63
+ end
64
+ end
65
+
66
+ def self.create_new_instance_with_normalized_data(result)
67
+ episode = self.new(
68
+ result.except(
69
+ 'crew',
70
+ 'guest_stars'
71
+ )
72
+ )
73
+
74
+ episode.crew = result['crew'].map do |person|
75
+ Person.new(person)
76
+ end
77
+
78
+ episode.guest_stars = result['guest_stars'].map do |person|
79
+ Person.new(person)
80
+ end
81
+
82
+ episode
83
+ end
84
+
85
+ private_class_method :create_new_instance_with_normalized_data
86
+
87
+ end
88
+ end
89
+ end
@@ -0,0 +1,91 @@
1
+ module Tmdb
2
+ module Tv
3
+ class Season < Struct
4
+
5
+ def self.detail(id, season_number, filters={})
6
+ result = Resource.new("/tv/#{id}/season/#{season_number}", filters).get
7
+
8
+ create_new_instance_with_normalized_data(result)
9
+ end
10
+
11
+ def self.changes(id, filters={})
12
+ result = Resource.new("/tv/season/#{id}/changes", filters).get
13
+
14
+ result['changes'].map do |entry|
15
+ change = Change.new(entry)
16
+ change.convert_items!
17
+ change
18
+ end
19
+ end
20
+
21
+ def self.cast(id, season_number, filters={})
22
+ result = Resource.new("/tv/#{id}/season/#{season_number}/credits", filters).get
23
+
24
+ result['cast'].map do |entry|
25
+ Person.new(entry)
26
+ end
27
+ end
28
+
29
+ def self.crew(id, season_number, filters={})
30
+ result = Resource.new("/tv/#{id}/season/#{season_number}/credits", filters).get
31
+
32
+ result['crew'].map do |entry|
33
+ Person.new(entry)
34
+ end
35
+ end
36
+
37
+ def self.external_ids(id, season_number, filters={})
38
+ result = Resource.new("/tv/#{id}/season/#{season_number}/external_ids", filters).get
39
+ self.new(result)
40
+ end
41
+
42
+ def self.posters(id, season_number, filters={})
43
+ result = Resource.new("/tv/#{id}/season/#{season_number}/images", filters).get
44
+
45
+ result['posters'].map do |entry|
46
+ Poster.new(entry)
47
+ end
48
+ end
49
+
50
+ def self.videos(id, season_number, filters={})
51
+ result = Resource.new("/tv/#{id}/season/#{season_number}/videos", filters).get
52
+
53
+ result['results'].map do |entry|
54
+ Video.new(entry)
55
+ end
56
+ end
57
+
58
+ def self.create_new_instance_with_normalized_data(result)
59
+ season = self.new(
60
+ result.except(
61
+ 'episodes'
62
+ )
63
+ )
64
+
65
+ season.episodes = result['episodes'].map do |episode|
66
+ new_episode = Tv::Episode.new(
67
+ episode.except(
68
+ 'crew',
69
+ 'guest_stars'
70
+ )
71
+ )
72
+
73
+ new_episode.crew = episode['crew'].map do |entry|
74
+ Person.new(entry)
75
+ end
76
+
77
+ new_episode.guest_stars = episode['guest_stars'].map do |entry|
78
+ Person.new(entry)
79
+ end
80
+
81
+ new_episode
82
+ end
83
+
84
+ season
85
+ end
86
+
87
+ private_class_method :create_new_instance_with_normalized_data
88
+
89
+ end
90
+ end
91
+ end