fandango 1.0.0 → 2.0.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.
- checksums.yaml +7 -0
- data/.gitignore +0 -1
- data/.irbrc +2 -3
- data/.ruby-version +1 -0
- data/.travis.yml +2 -2
- data/Gemfile +2 -0
- data/Gemfile.lock +37 -0
- data/README.md +45 -22
- data/Rakefile +2 -2
- data/fandango.gemspec +3 -3
- data/lib/fandango.rb +13 -35
- data/lib/fandango/api.rb +14 -0
- data/lib/fandango/api/movies_near.rb +36 -0
- data/lib/fandango/api/theater_showtimes.rb +47 -0
- data/lib/fandango/movie.rb +34 -18
- data/lib/fandango/showtime.rb +18 -0
- data/lib/fandango/theater.rb +44 -35
- data/lib/fandango/version.rb +1 -1
- data/spec/api/movies_near.spec.rb +30 -0
- data/spec/api/theater_showtimes.spec.rb +36 -0
- data/spec/movie.spec.rb +17 -18
- data/spec/showtime.spec.rb +21 -0
- data/spec/spec_helper.rb +5 -10
- data/spec/support/fixture_helpers.rb +14 -0
- data/spec/support/fixtures/movies_near_me_73142.rss +185 -1
- data/spec/support/fixtures/{movies_near_me_73142.yaml → movies_near_me_73142.yml} +70 -70
- data/spec/support/fixtures/showtimes_amcquailspringsmall24_aaktw_2016_08_01.html +7264 -0
- data/spec/support/fixtures/theater_showtimes_amcquailspringsmall24.yml +203 -0
- data/spec/support/fixtures/theater_showtimes_amcquailspringsmall24_tomorrow.yml +190 -0
- data/spec/support/minitest.rb +9 -0
- data/spec/support/vcr.rb +6 -0
- data/spec/support/vcr_cassettes/theater_showtimes_amcquailspringsmall24.yml +10974 -0
- data/spec/support/vcr_cassettes/theater_showtimes_amcquailspringsmall24_tomorrow.yml +10759 -0
- data/spec/theater.spec.rb +58 -12
- metadata +79 -48
- data/.rvmrc +0 -1
- data/lib/fandango/parser.rb +0 -39
- data/spec/fandango.spec.rb +0 -41
- data/spec/parser.spec.rb +0 -12
- data/spec/support/fixtures/item.html +0 -1
- data/spec/support/helpers.rb +0 -25
    
        checksums.yaml
    ADDED
    
    | @@ -0,0 +1,7 @@ | |
| 1 | 
            +
            ---
         | 
| 2 | 
            +
            SHA1:
         | 
| 3 | 
            +
              metadata.gz: 852bc1a00a4783ec4b36469fe7db37179dd6201c
         | 
| 4 | 
            +
              data.tar.gz: 3c9bd3977acc1d8e629bfbf84c6bc258d138b214
         | 
| 5 | 
            +
            SHA512:
         | 
| 6 | 
            +
              metadata.gz: a3ae6deafd0527b381e036167ff321277d8f86d4eed21fbe719ae30d2334819934e396ad0f8a2fb212a66a61457ed883a6a675d22e2b0b6c8e5db34a76d652e3
         | 
| 7 | 
            +
              data.tar.gz: 9d6d73995bec4a0221385b667c65115e0e5cf99716f9894ea02428eb7c157d8156230bdfdda86ceca268aa9315ce2272e449d4afb6840ebc734b29058269ff20
         | 
    
        data/.gitignore
    CHANGED
    
    
    
        data/.irbrc
    CHANGED
    
    
    
        data/.ruby-version
    ADDED
    
    | @@ -0,0 +1 @@ | |
| 1 | 
            +
            ruby-2.3.1
         | 
    
        data/.travis.yml
    CHANGED
    
    
    
        data/Gemfile
    CHANGED
    
    
    
        data/Gemfile.lock
    ADDED
    
    | @@ -0,0 +1,37 @@ | |
| 1 | 
            +
            PATH
         | 
| 2 | 
            +
              remote: .
         | 
| 3 | 
            +
              specs:
         | 
| 4 | 
            +
                fandango (2.0.0)
         | 
| 5 | 
            +
                  nokogiri (~> 1.0)
         | 
| 6 | 
            +
             | 
| 7 | 
            +
            GEM
         | 
| 8 | 
            +
              remote: http://rubygems.org/
         | 
| 9 | 
            +
              specs:
         | 
| 10 | 
            +
                addressable (2.4.0)
         | 
| 11 | 
            +
                awesome_print (1.7.0)
         | 
| 12 | 
            +
                crack (0.4.3)
         | 
| 13 | 
            +
                  safe_yaml (~> 1.0.0)
         | 
| 14 | 
            +
                mini_portile2 (2.1.0)
         | 
| 15 | 
            +
                minitest (5.9.0)
         | 
| 16 | 
            +
                nokogiri (1.6.8.1)
         | 
| 17 | 
            +
                  mini_portile2 (~> 2.1.0)
         | 
| 18 | 
            +
                rake (11.2.2)
         | 
| 19 | 
            +
                safe_yaml (1.0.4)
         | 
| 20 | 
            +
                vcr (3.0.3)
         | 
| 21 | 
            +
                webmock (1.9.3)
         | 
| 22 | 
            +
                  addressable (>= 2.2.7)
         | 
| 23 | 
            +
                  crack (>= 0.3.2)
         | 
| 24 | 
            +
             | 
| 25 | 
            +
            PLATFORMS
         | 
| 26 | 
            +
              ruby
         | 
| 27 | 
            +
             | 
| 28 | 
            +
            DEPENDENCIES
         | 
| 29 | 
            +
              awesome_print
         | 
| 30 | 
            +
              fandango!
         | 
| 31 | 
            +
              minitest
         | 
| 32 | 
            +
              rake
         | 
| 33 | 
            +
              vcr
         | 
| 34 | 
            +
              webmock
         | 
| 35 | 
            +
             | 
| 36 | 
            +
            BUNDLED WITH
         | 
| 37 | 
            +
               1.13.1
         | 
    
        data/README.md
    CHANGED
    
    | @@ -6,34 +6,57 @@ Uses Fandango's RSS moviesnearme feed. E.g. http://www.fandango.com/rss/moviesne | |
| 6 6 |  | 
| 7 7 | 
             
            ## Usage
         | 
| 8 8 |  | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
            The movies are an array of hashes. Each hash contains title and Fandango's id.
         | 
| 13 | 
            -
             | 
| 14 | 
            -
            ### Example output format
         | 
| 15 | 
            -
             | 
| 16 | 
            -
            ```
         | 
| 9 | 
            +
            ```ruby
         | 
| 10 | 
            +
            theaters_and_movies = Fandango.movies_near(73142)
         | 
| 11 | 
            +
            =begin
         | 
| 17 12 | 
             
            [
         | 
| 18 13 | 
             
                [ 0] {
         | 
| 19 | 
            -
             | 
| 20 | 
            -
             | 
| 21 | 
            -
             | 
| 22 | 
            -
             | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 26 | 
            -
             | 
| 27 | 
            -
             | 
| 28 | 
            -
                               :id => "123456"
         | 
| 14 | 
            +
                              :name => "AMC Quail Springs Mall 24",
         | 
| 15 | 
            +
                                :id => "aaktw",
         | 
| 16 | 
            +
                           :address => "2501 West Memorial Oklahoma City, OK 73134",
         | 
| 17 | 
            +
                       :postal_code => "73134",
         | 
| 18 | 
            +
                    :showtimes_link => "http://www.fandango.com/amcquailspringsmall24_aaktw/theaterpage?wssaffid=11836&wssac=123",
         | 
| 19 | 
            +
                            :movies => [
         | 
| 20 | 
            +
                        [ 0] {
         | 
| 21 | 
            +
                            :title => "Abraham Lincoln: Vampire Hunter",
         | 
| 22 | 
            +
                               :id => "141897"
         | 
| 29 23 | 
             
                        },
         | 
| 30 | 
            -
                        #  | 
| 24 | 
            +
                        # ...
         | 
| 31 25 | 
             
                    ]
         | 
| 32 26 | 
             
                },
         | 
| 33 | 
            -
                #  | 
| 27 | 
            +
                # ...
         | 
| 34 28 | 
             
            ]
         | 
| 29 | 
            +
            =end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
            movies_and_showtimes = Fandango.theater_showtimes(theaters_and_movies.first.fetch(:showtimes_link))
         | 
| 32 | 
            +
            =begin
         | 
| 33 | 
            +
            [
         | 
| 34 | 
            +
              {
         | 
| 35 | 
            +
                      :title => "Bad Moms",
         | 
| 36 | 
            +
                         :id => "191125",
         | 
| 37 | 
            +
                    :runtime => 101,
         | 
| 38 | 
            +
                  :showtimes => [
         | 
| 39 | 
            +
                      [0] {
         | 
| 40 | 
            +
                          :datetime => #<DateTime: 2016-08-02T11:30:00-05:00 ((2457603j,59400s,0n),-18000s,2299161j)>
         | 
| 41 | 
            +
                      },
         | 
| 42 | 
            +
                      # ...
         | 
| 43 | 
            +
                  ]
         | 
| 44 | 
            +
              },
         | 
| 45 | 
            +
              # ...
         | 
| 46 | 
            +
            =end
         | 
| 47 | 
            +
            ```
         | 
| 48 | 
            +
             | 
| 49 | 
            +
            ### `theaters_and_movies` with id and different date
         | 
| 50 | 
            +
             | 
| 51 | 
            +
            ```ruby
         | 
| 52 | 
            +
            Fandango.theater_showtimes(
         | 
| 53 | 
            +
              :theater_id => theaters_and_movies.first.fetch(:id),
         | 
| 54 | 
            +
              :date => Date.tomorrow, # optional, defaults to `Date.today`
         | 
| 55 | 
            +
            )
         | 
| 35 56 | 
             
            ```
         | 
| 36 57 |  | 
| 37 | 
            -
            ##  | 
| 58 | 
            +
            ## Compatibility
         | 
| 38 59 |  | 
| 39 | 
            -
             | 
| 60 | 
            +
            Development of this gem will only officially support Ruby versions 2.3.0. (see `.travis.yml`)
         | 
| 61 | 
            +
            It used to support 1.9.2. and 1.9.3, and it still may work, but it's not tested as of now.
         | 
| 62 | 
            +
            Contributions are very welcome, and I will do what I can to help.
         | 
    
        data/Rakefile
    CHANGED
    
    
    
        data/fandango.gemspec
    CHANGED
    
    | @@ -21,7 +21,7 @@ Gem::Specification.new do |s| | |
| 21 21 | 
             
              s.add_runtime_dependency     'nokogiri', '~> 1.0'
         | 
| 22 22 |  | 
| 23 23 | 
             
              s.add_development_dependency 'awesome_print'
         | 
| 24 | 
            -
              s.add_development_dependency ' | 
| 25 | 
            -
              s.add_development_dependency 'minitest' | 
| 26 | 
            -
              s.add_development_dependency 'vcr' | 
| 24 | 
            +
              s.add_development_dependency 'webmock'
         | 
| 25 | 
            +
              s.add_development_dependency 'minitest'
         | 
| 26 | 
            +
              s.add_development_dependency 'vcr'
         | 
| 27 27 | 
             
            end
         | 
    
        data/lib/fandango.rb
    CHANGED
    
    | @@ -3,47 +3,25 @@ require "fandango/version" | |
| 3 3 | 
             
            require 'open-uri'
         | 
| 4 4 | 
             
            require 'nokogiri'
         | 
| 5 5 |  | 
| 6 | 
            -
            require 'fandango/ | 
| 6 | 
            +
            require 'fandango/api'
         | 
| 7 7 |  | 
| 8 | 
            -
             | 
| 9 | 
            -
             | 
| 10 | 
            -
             | 
| 11 | 
            -
             | 
| 12 | 
            -
                def movies_near(postal_code)
         | 
| 13 | 
            -
                  raise ArgumentError, "postal code cannot be blank" if postal_code.nil? || postal_code == ''
         | 
| 14 | 
            -
                  response = request(postal_code)
         | 
| 15 | 
            -
                  raise BadResponse.new(response) unless response.status.first == '200'
         | 
| 16 | 
            -
                  source = response.read
         | 
| 17 | 
            -
                  parse source
         | 
| 18 | 
            -
                end
         | 
| 19 | 
            -
             | 
| 20 | 
            -
                def request(postal_code)
         | 
| 21 | 
            -
                  open(url_for_postal_code(postal_code))
         | 
| 22 | 
            -
                end
         | 
| 8 | 
            +
            require 'fandango/theater'
         | 
| 9 | 
            +
            require 'fandango/movie'
         | 
| 10 | 
            +
            require 'fandango/showtime'
         | 
| 23 11 |  | 
| 24 | 
            -
             | 
| 25 | 
            -
                # Return hash of theaters and movies playing at each..
         | 
| 26 | 
            -
                def parse(source)
         | 
| 27 | 
            -
                  Parser.parse(source)
         | 
| 28 | 
            -
                end
         | 
| 29 | 
            -
             | 
| 30 | 
            -
              private
         | 
| 31 | 
            -
             | 
| 32 | 
            -
                def url_for_postal_code(postal_code)
         | 
| 33 | 
            -
                  cleaned_postal_code = clean_postal_code(postal_code)
         | 
| 34 | 
            -
                  "http://www.fandango.com/rss/moviesnearme_#{cleaned_postal_code}.rss"
         | 
| 35 | 
            -
                end
         | 
| 12 | 
            +
            module Fandango
         | 
| 36 13 |  | 
| 37 | 
            -
             | 
| 38 | 
            -
                def clean_postal_code(postal_code)
         | 
| 39 | 
            -
                  postal_code.to_s.gsub(' ', '')
         | 
| 40 | 
            -
                end
         | 
| 14 | 
            +
              module_function
         | 
| 41 15 |  | 
| 16 | 
            +
              def movies_near(postal_code)
         | 
| 17 | 
            +
                MoviesNear.(postal_code)
         | 
| 42 18 | 
             
              end
         | 
| 43 19 |  | 
| 44 | 
            -
               | 
| 45 | 
            -
                 | 
| 46 | 
            -
                   | 
| 20 | 
            +
              def theater_showtimes(showtimes_link_or_options)
         | 
| 21 | 
            +
                if showtimes_link_or_options.is_a?(Hash)
         | 
| 22 | 
            +
                  TheaterShowtimes.by_id_and_date(showtimes_link_or_options)
         | 
| 23 | 
            +
                else
         | 
| 24 | 
            +
                  TheaterShowtimes.(showtimes_link_or_options)
         | 
| 47 25 | 
             
                end
         | 
| 48 26 | 
             
              end
         | 
| 49 27 |  | 
    
        data/lib/fandango/api.rb
    ADDED
    
    | @@ -0,0 +1,14 @@ | |
| 1 | 
            +
            module Fandango
         | 
| 2 | 
            +
              autoload :MoviesNear,       'fandango/api/movies_near'
         | 
| 3 | 
            +
              autoload :TheaterShowtimes, 'fandango/api/theater_showtimes'
         | 
| 4 | 
            +
             | 
| 5 | 
            +
              module API
         | 
| 6 | 
            +
             | 
| 7 | 
            +
                class BadResponse < StandardError
         | 
| 8 | 
            +
                  def initialize(response)
         | 
| 9 | 
            +
                    super "Bad response:\n#{response.inspect}"
         | 
| 10 | 
            +
                  end
         | 
| 11 | 
            +
                end
         | 
| 12 | 
            +
             | 
| 13 | 
            +
              end
         | 
| 14 | 
            +
            end
         | 
| @@ -0,0 +1,36 @@ | |
| 1 | 
            +
            module Fandango
         | 
| 2 | 
            +
              module MoviesNear
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                module_function
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                def call(postal_code)
         | 
| 7 | 
            +
                  response = request(postal_code)
         | 
| 8 | 
            +
                  raise BadResponse.new(response) unless response.status.first == '200'
         | 
| 9 | 
            +
             | 
| 10 | 
            +
                  xml = response.read
         | 
| 11 | 
            +
                  Parser.(xml)
         | 
| 12 | 
            +
                end
         | 
| 13 | 
            +
             | 
| 14 | 
            +
                def request(postal_code)
         | 
| 15 | 
            +
                  cleaned_postal_code = postal_code.to_s.gsub(' ', '')
         | 
| 16 | 
            +
                  url_for_postal_code = "http://www.fandango.com/rss/moviesnearme_#{cleaned_postal_code}.rss"
         | 
| 17 | 
            +
                  open(url_for_postal_code)
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                module Parser
         | 
| 21 | 
            +
             | 
| 22 | 
            +
                  module_function
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                  def call(xml)
         | 
| 25 | 
            +
                    doc = Nokogiri.XML(xml)
         | 
| 26 | 
            +
                    doc.css('item').map do |item_node|
         | 
| 27 | 
            +
                      Theater.parse(item_node)
         | 
| 28 | 
            +
                    end
         | 
| 29 | 
            +
                  end
         | 
| 30 | 
            +
             | 
| 31 | 
            +
                end
         | 
| 32 | 
            +
             | 
| 33 | 
            +
                class BadResponse < API::BadResponse; end
         | 
| 34 | 
            +
             | 
| 35 | 
            +
              end
         | 
| 36 | 
            +
            end
         | 
| @@ -0,0 +1,47 @@ | |
| 1 | 
            +
            module Fandango
         | 
| 2 | 
            +
              module TheaterShowtimes
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                BASE_URL = 'http://www.fandango.com/theater_%{theater_id}/theaterpage?date=%{date}'
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                module_function
         | 
| 7 | 
            +
             | 
| 8 | 
            +
                def call(showtimes_link)
         | 
| 9 | 
            +
                  response = request(showtimes_link)
         | 
| 10 | 
            +
                  raise BadResponse.new(response) unless response.status.first == '200'
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                  html = response.read
         | 
| 13 | 
            +
                  Parser.(html)
         | 
| 14 | 
            +
                end
         | 
| 15 | 
            +
             | 
| 16 | 
            +
                def by_id_and_date(theater_id:, date: Date.today)
         | 
| 17 | 
            +
                  url = BASE_URL % {:theater_id => theater_id, :date => date}
         | 
| 18 | 
            +
                  call url
         | 
| 19 | 
            +
                end
         | 
| 20 | 
            +
             | 
| 21 | 
            +
                def request(showtimes_link)
         | 
| 22 | 
            +
                  open(showtimes_link)
         | 
| 23 | 
            +
                end
         | 
| 24 | 
            +
             | 
| 25 | 
            +
                module Parser
         | 
| 26 | 
            +
             | 
| 27 | 
            +
                  module_function
         | 
| 28 | 
            +
             | 
| 29 | 
            +
                  def call(html)
         | 
| 30 | 
            +
                    doc = Nokogiri.HTML(html)
         | 
| 31 | 
            +
                    doc.css('.showtimes-movie-container').map do |movie_node|
         | 
| 32 | 
            +
                      movie = Movie.parse(movie_node)
         | 
| 33 | 
            +
                      movie[:showtimes] =
         | 
| 34 | 
            +
                        movie_node.at_css('.showtimes-times').css('a').map do |showtime_node|
         | 
| 35 | 
            +
                          Showtime.parse(showtime_node)
         | 
| 36 | 
            +
                        end
         | 
| 37 | 
            +
                      movie
         | 
| 38 | 
            +
                    end
         | 
| 39 | 
            +
                  end
         | 
| 40 | 
            +
             | 
| 41 | 
            +
                end
         | 
| 42 | 
            +
             | 
| 43 | 
            +
              end
         | 
| 44 | 
            +
             | 
| 45 | 
            +
              class BadResponse < API::BadResponse; end
         | 
| 46 | 
            +
             | 
| 47 | 
            +
            end
         | 
    
        data/lib/fandango/movie.rb
    CHANGED
    
    | @@ -1,29 +1,45 @@ | |
| 1 1 | 
             
            module Fandango
         | 
| 2 2 | 
             
              module Movie
         | 
| 3 3 |  | 
| 4 | 
            -
                 | 
| 5 | 
            -
             | 
| 6 | 
            -
                  # Return array of movie attributes.
         | 
| 7 | 
            -
                  def parse(description_node)
         | 
| 8 | 
            -
                    description_node.css('li').map do |li|
         | 
| 9 | 
            -
                      {
         | 
| 10 | 
            -
                        title: parse_title(li),
         | 
| 11 | 
            -
                        id:    parse_id(li),
         | 
| 12 | 
            -
                      }
         | 
| 13 | 
            -
                    end
         | 
| 14 | 
            -
                  end
         | 
| 4 | 
            +
                module_function
         | 
| 15 5 |  | 
| 16 | 
            -
                 | 
| 6 | 
            +
                def parse(node)
         | 
| 7 | 
            +
                  a_tag = node.at_css('a.showtimes-movie-title') || node.at_css('a')
         | 
| 8 | 
            +
                  hash = {
         | 
| 9 | 
            +
                    title:   parse_title(a_tag),
         | 
| 10 | 
            +
                    id:      parse_id(a_tag),
         | 
| 11 | 
            +
                  }
         | 
| 17 12 |  | 
| 18 | 
            -
                   | 
| 19 | 
            -
                     | 
| 13 | 
            +
                  if a_tag.attr(:class)&.include?('showtimes-movie-title')
         | 
| 14 | 
            +
                    hash[:runtime] = parse_runtime(node)
         | 
| 20 15 | 
             
                  end
         | 
| 21 16 |  | 
| 22 | 
            -
                   | 
| 23 | 
            -
             | 
| 24 | 
            -
             | 
| 25 | 
            -
             | 
| 17 | 
            +
                  hash
         | 
| 18 | 
            +
                end
         | 
| 19 | 
            +
             | 
| 20 | 
            +
                def parse_title(a_tag)
         | 
| 21 | 
            +
                  a_tag.content
         | 
| 22 | 
            +
                end
         | 
| 23 | 
            +
             | 
| 24 | 
            +
                # E.g. '141081' in fandango.com/the+adventures+of+tintin+3d_141081/movietimes
         | 
| 25 | 
            +
                def parse_id(a_tag)
         | 
| 26 | 
            +
                  a_tag['href'].match(%r{fandango\.com/.*_(?<id>\d+)/})[:id]
         | 
| 27 | 
            +
                end
         | 
| 26 28 |  | 
| 29 | 
            +
                # <div class="showtimes-movie-rating-runtime">
         | 
| 30 | 
            +
                # <!-- Display rating -->
         | 
| 31 | 
            +
                # R , 
         | 
| 32 | 
            +
                #   <!-- Display runtime -->
         | 
| 33 | 
            +
                # 1 hr 41 min
         | 
| 34 | 
            +
                # </div>
         | 
| 35 | 
            +
                def parse_runtime(node)
         | 
| 36 | 
            +
                  rating_runtime = node.at_css('.showtimes-movie-rating-runtime')
         | 
| 37 | 
            +
                  %r{(?<hour>\d+)\s+hr\s+(?<min>\d+)} =~ rating_runtime.content
         | 
| 38 | 
            +
                  begin
         | 
| 39 | 
            +
                    Integer(hour) * 60 + Integer(min)
         | 
| 40 | 
            +
                  rescue TypeError
         | 
| 41 | 
            +
                    #puts rating_runtime
         | 
| 42 | 
            +
                  end
         | 
| 27 43 | 
             
                end
         | 
| 28 44 |  | 
| 29 45 | 
             
              end
         | 
| @@ -0,0 +1,18 @@ | |
| 1 | 
            +
            module Fandango
         | 
| 2 | 
            +
              module Showtime
         | 
| 3 | 
            +
             | 
| 4 | 
            +
                module_function
         | 
| 5 | 
            +
             | 
| 6 | 
            +
                def parse(node)
         | 
| 7 | 
            +
                  {
         | 
| 8 | 
            +
                    datetime: parse_datetime(node),
         | 
| 9 | 
            +
                  }
         | 
| 10 | 
            +
                end
         | 
| 11 | 
            +
             | 
| 12 | 
            +
                def parse_datetime(node)
         | 
| 13 | 
            +
                  datetime_str = node.at_css('time').attr('datetime')
         | 
| 14 | 
            +
                  DateTime.parse(datetime_str)
         | 
| 15 | 
            +
                end
         | 
| 16 | 
            +
             | 
| 17 | 
            +
              end
         | 
| 18 | 
            +
            end
         | 
    
        data/lib/fandango/theater.rb
    CHANGED
    
    | @@ -1,49 +1,58 @@ | |
| 1 1 | 
             
            module Fandango
         | 
| 2 2 | 
             
              module Theater
         | 
| 3 3 |  | 
| 4 | 
            -
                 | 
| 4 | 
            +
                module_function
         | 
| 5 5 |  | 
| 6 | 
            -
             | 
| 7 | 
            -
             | 
| 8 | 
            -
                  end
         | 
| 6 | 
            +
                def parse(item_node)
         | 
| 7 | 
            +
                  hash = {}
         | 
| 9 8 |  | 
| 10 | 
            -
                   | 
| 11 | 
            -
                    description_node ||= Fandango::Parser.parse_description(item_node)
         | 
| 12 | 
            -
                    name        = parse_name(item_node)
         | 
| 13 | 
            -
                    id          = parse_id(item_node)
         | 
| 14 | 
            -
                    address     = parse_address(description_node)
         | 
| 15 | 
            -
                    postal_code = parse_postal_code(address)
         | 
| 16 | 
            -
             | 
| 17 | 
            -
                    {
         | 
| 18 | 
            -
                      name:        name,
         | 
| 19 | 
            -
                      id:          id,
         | 
| 20 | 
            -
                      address:     address,
         | 
| 21 | 
            -
                      postal_code: postal_code,
         | 
| 22 | 
            -
                    }
         | 
| 23 | 
            -
                  end
         | 
| 9 | 
            +
                  description_node = parse_description_node(item_node)
         | 
| 24 10 |  | 
| 25 | 
            -
                   | 
| 11 | 
            +
                  hash[:name]           = parse_name(item_node)
         | 
| 12 | 
            +
                  hash[:id]             = parse_id(item_node)
         | 
| 13 | 
            +
                  hash[:address]        = parse_address(description_node)
         | 
| 14 | 
            +
                  hash[:postal_code]    = parse_postal_code(hash[:address])
         | 
| 15 | 
            +
                  hash[:showtimes_link] = parse_showtimes_link(item_node)
         | 
| 16 | 
            +
                  hash[:movies]         = parse_movies(description_node)
         | 
| 26 17 |  | 
| 27 | 
            -
                   | 
| 28 | 
            -
             | 
| 29 | 
            -
                  end
         | 
| 18 | 
            +
                  hash
         | 
| 19 | 
            +
                end
         | 
| 30 20 |  | 
| 31 | 
            -
             | 
| 32 | 
            -
             | 
| 33 | 
            -
             | 
| 34 | 
            -
             | 
| 35 | 
            -
             | 
| 36 | 
            -
             | 
| 37 | 
            -
                  end
         | 
| 21 | 
            +
                # Description content is in the form of HTML wrapped in CDATA.
         | 
| 22 | 
            +
                # Parse it and return a parsed Nokogiri node.
         | 
| 23 | 
            +
                def parse_description_node(item_node)
         | 
| 24 | 
            +
                  cdata = item_node.at_css('description')
         | 
| 25 | 
            +
                  Nokogiri::HTML(cdata.content)
         | 
| 26 | 
            +
                end
         | 
| 38 27 |  | 
| 39 | 
            -
             | 
| 40 | 
            -
             | 
| 41 | 
            -
             | 
| 28 | 
            +
                def parse_name(item_node)
         | 
| 29 | 
            +
                  item_node.at_css('title').content.strip
         | 
| 30 | 
            +
                end
         | 
| 42 31 |  | 
| 43 | 
            -
             | 
| 44 | 
            -
             | 
| 45 | 
            -
                   | 
| 32 | 
            +
                # E.g. 'aaicu' in http://www.fandango.com/northpark7_aaicu/theaterpage
         | 
| 33 | 
            +
                def parse_id(item_node)
         | 
| 34 | 
            +
                  item_node.
         | 
| 35 | 
            +
                    at_css('link').
         | 
| 36 | 
            +
                    content.
         | 
| 37 | 
            +
                    match(%r{fandango\.com/.*_(?<id>.*)/theaterpage})[:id]
         | 
| 38 | 
            +
                end
         | 
| 39 | 
            +
             | 
| 40 | 
            +
                def parse_address(description_node)
         | 
| 41 | 
            +
                  description_node.at_css('p').content
         | 
| 42 | 
            +
                end
         | 
| 43 | 
            +
             | 
| 44 | 
            +
                def parse_postal_code(address)
         | 
| 45 | 
            +
                  address.match(/(?<postal_code>\d+)$/)[:postal_code]
         | 
| 46 | 
            +
                end
         | 
| 47 | 
            +
             | 
| 48 | 
            +
                def parse_showtimes_link(item_node)
         | 
| 49 | 
            +
                  item_node.at_css('link').content.strip
         | 
| 50 | 
            +
                end
         | 
| 46 51 |  | 
| 52 | 
            +
                def parse_movies(description_node)
         | 
| 53 | 
            +
                  description_node.css('li').map do |li|
         | 
| 54 | 
            +
                    Movie.parse(li)
         | 
| 55 | 
            +
                  end
         | 
| 47 56 | 
             
                end
         | 
| 48 57 |  | 
| 49 58 | 
             
              end
         |