public
Rubygem
Description: DataMapper adapter for google video
Homepage:
Clone URL: git://github.com/mattetti/dm-gvideo-adapter.git
dm-gvideo-adapter / lib / dm-gvideo-adapter.rb
100644 105 lines (85 sloc) 3.489 kb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
begin
  require 'minigems'
rescue LoadError
  require 'rubygems'
end
require 'dm-core'
require 'gvideo'
 
module GvideoInterface
  class FetchError < StandardError; end
  class SettingsError < StandardError; end
  class ConditionsError < StandardError; end
end
 
 
module DataMapper
  module Adapters
    class GvideoAdapter < AbstractAdapter
      
      attr_reader :google_user
      
      def initialize(name, uri_or_options)
        super(name, uri_or_options)
        @google_user = Gvideo::User.new(uri_or_options[:user_id])
        raise GvideoInterface::FetchError, "You must set a user_id" unless @google_user.g_id
      end
 
      # Reads in a set from a query.
      def read_many(query)
        Collection.new(query) do |set|
          read(query, set, true)
        end
      end
 
      def read_one(query)
        read(query, query.model, false)
      end
      
      private
      
        # query = the DM Query instance
        # set = a Collection instance
        # arr boolean used to specify if the returned value should be an array or a single object instance
        def read(query, set, arr = true)
          options = extract_options(query.conditions)
          
          repository_name = query.repository.name
          properties = query.fields
          
          begin
            results = @google_user.fetch_videos(options)
          rescue
            raise GvideoInterface::FetchError, "Couldn't retrieve the videos"
          end
 
          results.each do |result|
            values = result_values(result, properties, repository_name)
            # This is the core logic that handles the difference between all/first
            arr ? set.load(values) : (break set.load(values, query))
          end
          
        end
        
        def result_values(result, properties, repository_name)
          properties.map { |p| result.send(p.field(repository_name)) }
        end
        
        def extract_options(query_conditions)
          options = {}
          duration_range = { :min => nil, :max => nil }
          duration_matcher = nil
 
          query_conditions.each do |condition|
            operator, property, value = condition
            case property.name
              when :title
                case operator
                  when :eql then title_matcher = value
                  when :like then title_matcher = Regexp.new(value)
                end
                options.merge!(:title => title_matcher)
              when :duration
                raise GvideoInterface::ConditionsError, "duration in seconds needs to be expressed using an Integer" unless value.is_a?(Integer)
                case operator
                  when :eql then duration_matcher = value
                  when :gte then duration_range[:min] = value
                  when :gt then duration_range[:min] = value + 1
                  when :lte then duration_range[:max] = value
                  when :lt then duration_range[:max] = value - 1
                end
              else
                raise GvideoInterface::ConditionsError, "#{property.name} not supported as a condition"
            end
          end
 
          options.merge!(:duration => duration_matcher) if duration_matcher
          options.merge!(:duration => (duration_range[:min] || 0)..(duration_range[:max] || 9999)) if duration_range[:min] || duration_range[:max]
 
          options
        end
      
    end #GvideoAdapter
  end #Adapters
end #DataMapper