tmdb_party 0.4.1 → 0.5.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.
@@ -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