module Immedialist
  module RottenTomatoes
    class Movie < APIResource
      include Immedialist::RottenTomatoes

      def initialize(imdb_id)
        raise ArgumentError, "imdb_id can only have digits" if imdb_id =~ /\D/

        @imdb_id = imdb_id
      end

      def find
        @query_result = self.query_movie_by_imdb_id(imdb_id)
        compare_results_to_api_expectations!
        self
      end

      def method_missing(method_name)
        if active_attributes.include?(method_name)
          return query_result.send(method_name)
        else
          super
        end
      end

      def critics_score
        query_result.ratings.critics_score
      end

      def audience_score
        query_result.ratings.audience_score
      end

      private

      attr_reader :imdb_id, :query_result

      def active_attributes
        [
          :audience_score,
          :critics_consensus,
          :critics_score,
          :mpaa_rating,
        ]
      end

      def compare_results_to_api_expectations!
        if !query_result.is_a?(PatchedOpenStruct)
          raise TypeError, "Query result is not a PatchedOpenStruct"
        end

        if query_result.error.present?
          raise RottenTomatoes::QueryError,
            "RottenTomatoes could not find a movie with ID #{imdb_id}"
        end
      end
    end
  end
end

module Immedialist
  module RottenTomatoes
    class Movie < APIResource
      include Immedialist::RottenTomatoes

      def initialize(imdb_id)
        raise ArgumentError, "imdb_id can only have digits" if imdb_id =~ /\D/

        @imdb_id = imdb_id
      end

      def find
        @query_result = query_api
        compare_results_to_api_expectations!
        self
      end

      def method_missing(method_name)
        if active_attributes.include?(method_name)
          return query_result.send(method_name)
        else
          super
        end
      end

      def critics_score
        query_result.ratings.critics_score
      end

      def audience_score
        query_result.ratings.audience_score
      end

      private

      attr_reader :imdb_id, :query_result

      def query_api
        self.query_movie_by_imdb_id(imdb_id)
      end

      def active_attributes
        [
          :audience_score,
          :critics_consensus,
          :critics_score,
          :mpaa_rating,
        ]
      end

      def compare_results_to_api_expectations!
        if !query_result.is_a?(PatchedOpenStruct)
          raise TypeError, "Query result is not a PatchedOpenStruct"
        end

        if query_result.error.present?
          raise RottenTomatoes::QueryError,
            "RottenTomatoes could not find a movie with ID #{imdb_id}"
        end
      end
    end
  end
end

Refactor Immedialist::RottenTomatoes::Movie: extract method (query_api)
Refactor Immedialist::RottenTomatoes::Movie: extract method (query_api)
