tmdb_party 0.4.1 → 0.5.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -4,6 +4,7 @@ Simple ruby wrapper to themoviedb.org (http://api.themoviedb.org/2.0/docs/) usin
4
4
 
5
5
  = usage:
6
6
  sudo gem install tmdb_party -s http://gemcutter.org
7
+ require 'rubygems'
7
8
  require 'tmdb_party'
8
9
 
9
10
  = example:
@@ -14,7 +15,7 @@ Simple ruby wrapper to themoviedb.org (http://api.themoviedb.org/2.0/docs/) usin
14
15
  results.length
15
16
  # => 5
16
17
 
17
- transformers = results.detect{|m| m.title == "Transformers"}
18
+ transformers = results.detect{|m| m.name == "Transformers"}
18
19
 
19
20
  transformers.popularity
20
21
  # => 31
@@ -37,6 +38,7 @@ It's a movie database, kind of like IMDB except it's more of a community wiki. T
37
38
 
38
39
  == Contributors
39
40
  Jon Maddox (http://github.com/maddox)
41
+ Magnus Bergmark (http://github.com/Mange)
40
42
 
41
43
  == Copyright
42
44
 
data/Rakefile CHANGED
@@ -12,7 +12,7 @@ begin
12
12
  gem.add_dependency('httparty', '>= 0.4.3')
13
13
 
14
14
  gem.add_development_dependency('fakeweb')
15
- gem.add_development_dependency('context')
15
+ gem.add_development_dependency('rspec')
16
16
  # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
17
17
  end
18
18
  Jeweler::GemcutterTasks.new
@@ -20,28 +20,18 @@ rescue LoadError
20
20
  puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
21
21
  end
22
22
 
23
- require 'rake/testtask'
24
- Rake::TestTask.new(:test) do |test|
25
- test.libs << 'lib' << 'test'
26
- test.pattern = 'test/**/*_test.rb'
27
- test.verbose = true
23
+ require 'spec/rake/spectask'
24
+ desc "Run all examples"
25
+ Spec::Rake::SpecTask.new('spec') do |t|
26
+ t.pattern = 'spec/**/*_spec.rb'
28
27
  end
29
28
 
30
- begin
31
- require 'rcov/rcovtask'
32
- Rcov::RcovTask.new do |test|
33
- test.libs << 'test'
34
- test.pattern = 'test/**/*_test.rb'
35
- test.verbose = true
36
- end
37
- rescue LoadError
38
- task :rcov do
39
- abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
40
- end
29
+ Spec::Rake::SpecTask.new('rcov') do |t|
30
+ t.pattern = 'spec/**/*_spec.rb'
31
+ t.rcov = true
41
32
  end
42
33
 
43
-
44
- task :default => :test
34
+ task :default => :spec
45
35
 
46
36
  require 'rake/rdoctask'
47
37
  Rake::RDocTask.new do |rdoc|
@@ -57,4 +47,3 @@ Rake::RDocTask.new do |rdoc|
57
47
  rdoc.rdoc_files.include('README*')
58
48
  rdoc.rdoc_files.include('lib/**/*.rb')
59
49
  end
60
-
@@ -1,4 +1,4 @@
1
1
  ---
2
- :patch: 1
2
+ :minor: 5
3
+ :patch: 0
3
4
  :major: 0
4
- :minor: 4
@@ -1,13 +1,9 @@
1
1
  # gem 'httparty'
2
2
  require 'httparty'
3
- require 'tmdb_party/core_extensions'
4
- require 'tmdb_party/httparty_icebox'
5
- require 'tmdb_party/attributes'
6
- require 'tmdb_party/video'
7
- require 'tmdb_party/genre'
8
- require 'tmdb_party/person'
9
- require 'tmdb_party/image'
10
- require 'tmdb_party/movie'
3
+
4
+ %w[core_extensions httparty_icebox attributes video genre person image country studio cast_member movie].each do |class_name|
5
+ require "tmdb_party/#{class_name}"
6
+ end
11
7
 
12
8
  module TMDBParty
13
9
  class Base
@@ -18,18 +14,13 @@ module TMDBParty
18
14
  base_uri 'http://api.themoviedb.org/2.1'
19
15
  format :json
20
16
 
21
- def initialize(key)
17
+ def initialize(key, lang = 'en')
22
18
  @api_key = key
23
- end
24
-
25
- def default_path_items
26
- path_items = ['en']
27
- path_items << 'json'
28
- path_items << @api_key
19
+ @lang = lang
29
20
  end
30
21
 
31
22
  def search(query)
32
- data = self.class.get("/Movie.search/" + default_path_items.join('/') + '/' + URI.escape(query))
23
+ data = self.class.get(method_url('Movie.search', query))
33
24
  if data.class != Array || data.first == "Nothing found."
34
25
  []
35
26
  else
@@ -37,8 +28,17 @@ module TMDBParty
37
28
  end
38
29
  end
39
30
 
31
+ def search_person(query)
32
+ data = self.class.get(method_url('Person.search', query))
33
+ if data.class != Array || data.first == "Nothing found."
34
+ []
35
+ else
36
+ data.collect { |person| Person.new(person, self) }
37
+ end
38
+ end
39
+
40
40
  def imdb_lookup(imdb_id)
41
- data = self.class.get("/Movie.imdbLookup/" + default_path_items.join('/') + '/' + imdb_id)
41
+ data = self.class.get(method_url('Movie.imdbLookup', imdb_id))
42
42
  if data.class != Array || data.first == "Nothing found."
43
43
  nil
44
44
  else
@@ -47,8 +47,22 @@ module TMDBParty
47
47
  end
48
48
 
49
49
  def get_info(id)
50
- data = self.class.get("/Movie.getInfo/" + default_path_items.join('/') + '/' + id.to_s)
50
+ data = self.class.get(method_url('Movie.getInfo', id))
51
51
  Movie.new(data.first, self)
52
52
  end
53
+
54
+ def get_person(id)
55
+ data = self.class.get(method_url('Person.getInfo', id))
56
+ Person.new(data.first, self)
57
+ end
58
+
59
+ private
60
+ def default_path_items
61
+ [@lang, 'json', @api_key]
62
+ end
63
+
64
+ def method_url(method, value)
65
+ '/' + ([method] + default_path_items + [URI.escape(value.to_s)]).join('/')
66
+ end
53
67
  end
54
68
  end
@@ -20,15 +20,14 @@ module TMDBParty
20
20
  end
21
21
 
22
22
  def attribute(name, options)
23
- options.replace({:type => 'nil', :lazy=>false}.merge(options))
24
- raise "Name can't be empty" if name.blank?
25
- lazy_load = "self.#{options[:lazy]} unless self.loaded?" if options[:lazy]
26
- class_eval <<-EOS
27
- def #{name}
28
- #{lazy_load}
29
- @#{name} ||= decode_raw_attribute(@attributes['#{name}'], #{options[:type]}) if @attributes
30
- end
31
- EOS
23
+ options = {:type => 'nil', :lazy => false}.merge(options)
24
+ raise ArgumentError, "Name can't be empty" if name.blank?
25
+
26
+ class_eval <<-EVAL
27
+ def #{name}
28
+ read_or_load_attribute('#{name}', #{options[:type]}, #{options[:lazy].inspect})
29
+ end
30
+ EVAL
32
31
  end
33
32
 
34
33
  end
@@ -43,10 +42,27 @@ module TMDBParty
43
42
  end
44
43
 
45
44
  private
46
- def decode_raw_attribute(value, type)
47
- return nil unless value
48
- type.respond_to?(:parse) ? type.parse(value) : value
49
- end
45
+ def read_or_load_attribute(name, type, lazy_method)
46
+ if lazy_method.is_a?(Symbol) and raw_attribute_missing?(name) and not loaded?
47
+ self.send(lazy_method)
48
+ end
49
+ read_attribute(name, type)
50
+ end
51
+
52
+ def read_attribute(name, type = nil)
53
+ @attributes_cache ||= {}
54
+ @attributes_cache[name] ||= decode_raw_attribute(@attributes[name], type) if @attributes
55
+ end
56
+
57
+ def raw_attribute_missing?(name)
58
+ not @attributes.has_key?(name.to_s)
59
+ end
60
+
61
+ def decode_raw_attribute(value, type)
62
+ return nil unless value
63
+ type.respond_to?(:parse) ? type.parse(value) : value
64
+ end
65
+
50
66
  end
51
67
  end
52
68
  end
@@ -0,0 +1,36 @@
1
+ module TMDBParty
2
+ class CastMember
3
+ include Attributes
4
+ attr_reader :tmdb
5
+ attributes :name, :url, :job, :department
6
+ attributes :id, :type => Integer
7
+
8
+ def initialize(values, tmdb)
9
+ @tmdb = tmdb
10
+ self.attributes = values
11
+ end
12
+
13
+ def character_name
14
+ read_attribute('character')
15
+ end
16
+
17
+ def image_url
18
+ read_attribute('profile')
19
+ end
20
+
21
+ def person
22
+ tmdb.get_person(id)
23
+ end
24
+
25
+ def self.parse(data, tmdb)
26
+ return unless data
27
+ if data.is_a?(Array)
28
+ data.collect do |person|
29
+ CastMember.new(person, tmdb)
30
+ end
31
+ else
32
+ [CastMember.new(data, tmdb)]
33
+ end
34
+ end
35
+ end
36
+ end
@@ -0,0 +1,25 @@
1
+ module TMDBParty
2
+ class Country
3
+ include Attributes
4
+ attributes :name, :code, :url
5
+ alias_method :code_string, :code
6
+
7
+ def self.parse(data)
8
+ return unless data
9
+ if data.is_a?(Array)
10
+ data.map { |row| Country.new(row) }
11
+ else
12
+ [Country.new(data)]
13
+ end
14
+ end
15
+
16
+ def initialize(attributes)
17
+ self.attributes = attributes
18
+ end
19
+
20
+ def code
21
+ code_string.downcase.to_sym
22
+ end
23
+
24
+ end
25
+ end
@@ -1,24 +1,49 @@
1
1
  module TMDBParty
2
2
  class Image
3
- attr_reader :url, :type, :size
3
+ def initialize(attributes)
4
+ @attributes = attributes
5
+ end
4
6
 
5
- def initialize(options={})
6
- @url = options["url"]
7
- @type = options["type"]
8
- @size = options["size"]
7
+ def id
8
+ @attributes['id']
9
9
  end
10
10
 
11
- def self.parse(data)
12
- puts data.inspect
13
- puts
14
- puts
15
- if data.is_a?(Array)
16
- data.collect do |image|
17
- Image.new(image["image"])
18
- end
11
+ def type
12
+ @attributes['type'].downcase.to_sym
13
+ end
14
+
15
+ def sizes
16
+ @attributes['sizes'].map { |size| size.downcase.to_sym }.to_set
17
+ end
18
+
19
+ def url
20
+ original_url
21
+ end
22
+
23
+ def method_missing(*args, &block)
24
+ if args.first.to_s =~ /\A(.*)_url\Z/
25
+ @attributes["#{$1}_url"]
19
26
  else
20
- Image.new(image["image"])
27
+ super
21
28
  end
22
29
  end
30
+
31
+ class << self
32
+ def parse(data)
33
+ data.map { |row| row['image'] }.group_by { |row| row['id'] }.map do |id, images|
34
+ Image.new(reduce_images(images))
35
+ end
36
+ end
37
+
38
+ protected
39
+ def reduce_images(images)
40
+ images.inject({'sizes' => []}) do |image, row|
41
+ image["#{row['size']}_url"] = row.delete('url')
42
+ image['sizes'] << row.delete('size')
43
+ image.merge(row)
44
+ end
45
+ end
46
+ end
47
+
23
48
  end
24
49
  end
@@ -3,20 +3,21 @@ module TMDBParty
3
3
  include Attributes
4
4
  attr_reader :tmdb
5
5
 
6
- attributes :name, :overview, :id, :score, :imdb_id, :movie_type, :url, :popularity, :alternative_title
6
+ attributes :name, :overview, :id, :imdb_id, :movie_type, :url, :alternative_title, :translated, :certification
7
7
  attributes :released
8
- attributes :id, :type => Integer
9
- attributes :popularity, :score, :type => Float
8
+ attributes :id, :popularity, :type => Integer
9
+ attributes :score, :type => Float
10
10
 
11
- attributes :posters, :backdrops, :lazy => :get_info!
11
+ attributes :tagline, :lazy => :get_info!
12
+ attributes :posters, :backdrops, :lazy => :get_info!, :type => Image
12
13
  attributes :homepage, :lazy => :get_info!
13
14
  attributes :trailer, :lazy => :get_info!
14
15
  attributes :runtime, :lazy => :get_info!, :type => Integer
15
16
  attributes :genres, :lazy => :get_info!, :type => Genre
16
- attributes :cast, :lazy => :get_info!, :type => Person
17
+ attributes :countries, :lazy => :get_info!, :type => Country
18
+ attributes :studios, :lazy => :get_info!, :type => Studio
17
19
 
18
- alias_method :flattened_posters, :posters
19
- alias_method :flattened_backdrops, :backdrops
20
+ alias_method :translated?, :translated
20
21
 
21
22
  def initialize(values, tmdb)
22
23
  @tmdb = tmdb
@@ -29,45 +30,41 @@ module TMDBParty
29
30
  @loaded = true
30
31
  end
31
32
 
33
+ def cast
34
+ # TODO: This needs refactoring
35
+ CastMember.parse(read_or_load_attribute('cast', nil, :get_info!), tmdb)
36
+ end
37
+
38
+ def language
39
+ read_attribute('language').downcase.to_sym
40
+ end
41
+
42
+ def last_modified_at
43
+ # Date from TMDB is always in MST, but no timezone is present in date string
44
+ Time.parse(read_attribute('last_modified_at') + ' MST')
45
+ end
46
+
32
47
  def directors
33
- find_cast('Director')
48
+ find_cast('Directing')
34
49
  end
35
50
 
36
51
  def actors
37
- find_cast('Actor')
52
+ find_cast('Actors')
38
53
  end
39
54
 
40
55
  def writers
41
- find_cast('Writer')
42
- end
43
-
44
- def posters
45
- process_art(flattened_posters)
56
+ find_cast('Writing')
46
57
  end
47
58
 
48
- def backdrops
49
- process_art(flattened_backdrops)
59
+ def producers
60
+ find_cast('Production')
50
61
  end
51
62
 
52
-
53
63
  private
54
64
 
55
- def process_art(art)
56
- image_groups = {}
57
- art.each do |image_hash|
58
- the_image = image_hash["image"]
59
- if image_groups[the_image["id"]]
60
- image_groups[the_image["id"]][the_image["size"]] = the_image["url"]
61
- else
62
- image_groups[the_image["id"]] = {the_image["size"] => the_image["url"]}
63
- end
64
- end
65
- image_groups.values
66
- end
67
-
68
65
  def find_cast(type)
69
66
  return [] unless cast
70
- guys = cast.select{|c| c.job == type}
67
+ guys = cast.select{|c| c.department == type}
71
68
  end
72
69
 
73
70
  end
@@ -1,21 +1,29 @@
1
1
  module TMDBParty
2
2
  class Person
3
3
  include Attributes
4
- attributes :name, :url, :job
4
+ attr_reader :tmdb
5
+ attributes :id, :popularity, :type => Integer
6
+ attributes :score, :type => Float
7
+ attributes :name, :url, :biography
5
8
 
6
- def initialize(values)
9
+ attributes :birthplace, :birthday, :lazy => :get_info!
10
+
11
+ def initialize(values, tmdb)
12
+ @tmdb = tmdb
7
13
  self.attributes = values
8
14
  end
9
15
 
10
- def self.parse(data)
11
- return unless data
12
- if data.is_a?(Array)
13
- data.collect do |person|
14
- Person.new(person)
15
- end
16
- else
17
- [Person.new(data)]
18
- end
16
+ def biography
17
+ # HTTParty does not parse the encoded hexadecimal properly. It does not consider 000F to be a hex, but 000f is
18
+ # A bug has been submitted about this
19
+ read_attribute('biography').gsub("\\n", "\n").gsub(/\\u([0-9A-F]{4})/) { [$1.hex].pack("U") }
20
+ end
21
+
22
+
23
+ def get_info!
24
+ person = tmdb.get_person(self.id)
25
+ @attributes.merge!(person.attributes) if person
26
+ @loaded = true
19
27
  end
20
28
  end
21
29
  end