Class: RExchange::GenericItem

Inherits:
Object
  • Object
show all
Includes:
Enumerable, REXML
Defined in:
lib/rexchange/generic_item.rb

Direct Known Subclasses

Appointment, Contact, Message, Note, Task

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(session, dav_property_node) ⇒ GenericItem

Returns a new instance of GenericItem.


18
19
20
21
22
23
24
25
26
27
28
29
30
31
# File 'lib/rexchange/generic_item.rb', line 18

def initialize(session, dav_property_node)
  @attributes = {}
  @session = session

  dav_property_node.elements.each do |element|
    namespaced_name = element.namespace + element.name
    
    if element.name =~ /date$/i || self.class::ATTRIBUTE_MAPPINGS.find { |k,v| v == namespaced_name && k.to_s =~ /\_(at|on)$/ }
      @attributes[namespaced_name] = Time::parse(element.text) rescue element.text
    else
      @attributes[namespaced_name] = element.text
    end
  end
end

Instance Attribute Details

#attributesObject

Returns the value of attribute attributes


16
17
18
# File 'lib/rexchange/generic_item.rb', line 16

def attributes
  @attributes
end

Class Method Details

.attribute_mappings(mappings) ⇒ Object

Defines what attributes are used in queries, and what methods they map to in instances. You should pass a Hash of method_name symbols and namespaced-attribute-name pairs.


81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
# File 'lib/rexchange/generic_item.rb', line 81

def self.attribute_mappings(mappings)
  
  mappings.merge! :uid => 'DAV:uid',
    :modified_at => 'DAV:getlastmodified',
    :href => 'DAV:href'
  
  const_set('ATTRIBUTE_MAPPINGS', mappings)

  mappings.each_pair do |k,v|
    
    define_method(k) do
      @attributes[v]
    end
    
    define_method("#{k.to_s.sub(/\?$/, '')}=") do |value|
      @attributes[v] = value
    end
    
  end
end

.find(credentials, path, conditions = nil) ⇒ Object

Retrieve an Array of items (such as Contact, Message, etc)


103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/rexchange/generic_item.rb', line 103

def self.find(credentials, path, conditions = nil)
  qbody = <<-QBODY
    <?xml version="1.0"?>
	<D:searchrequest xmlns:D = "DAV:">
		 <D:sql>
       #{conditions.nil? ? query(path) : search(path, conditions)}
       </D:sql>
    </D:searchrequest>
  QBODY
  
  response = DavSearchRequest.execute(credentials, :body => qbody)

  items = []
  xpath_query = "//a:propstat[a:status/text() = 'HTTP/1.1 200 OK']/a:prop"

  Document.new(response.body).elements.each(xpath_query) do |m|
    items << self.new(credentials, m)
  end

  items
end

.inherited(base) ⇒ Object

Set the default CONTENT_CLASS to the class name, and define a dynamic query method for the derived class.


35
36
37
38
39
40
41
42
43
44
45
46
47
48
# File 'lib/rexchange/generic_item.rb', line 35

def self.inherited(base)
  base.const_set('CONTENT_CLASS', base.to_s.split('::').last.downcase)
  
  def base.query(path)
    <<-QBODY
      SELECT
        #{self::ATTRIBUTE_MAPPINGS.values.map { |f| '"' + f + '"' }.join(',')}
      FROM SCOPE('shallow traversal of "#{path}"')
      WHERE "DAV:ishidden" = false
        AND "DAV:isfolder" = false
        AND "DAV:contentclass" = 'urn:content-classes:#{self::CONTENT_CLASS}'
    QBODY
  end
end

.set_content_class(dav_name) ⇒ Object

–Normally Not Used– By default the CONTENT_CLASS is determined by the name of your class. So for the Appointment class the CONTENT_CLASS would be 'appointment'. If for some reason this convention doesn't suit you, you can use this method to set the appropriate value (which is used in queries). For example, the DAV:content-class for contacts is:

'urn:content-classes:person'

Person doesn't strike me as the best name for our class though. Most people would refer to an entry in a Contacts folder as a Contact. So that's what we call our class, and we use this method to make sure everything still works as it should.


72
73
74
75
76
# File 'lib/rexchange/generic_item.rb', line 72

def self.set_content_class(dav_name)
  verbosity, $VERBOSE = $VERBOSE, nil # disable warnings for the next operation
  const_set('CONTENT_CLASS', dav_name)
  $VERBOSE = verbosity # revert to the original verbosity
end

.set_folder_type(dav_name) ⇒ Object

This handy method is meant to be called from any inheriting classes. It is used to bind types of folders to particular Entity classes so that the folder knows what type it's enumerating. So for a “calendarfolder” you'd call:

set_folder_type 'calendarfolder' # or just 'calendar'

55
56
57
# File 'lib/rexchange/generic_item.rb', line 55

def self.set_folder_type(dav_name)
  Folder::CONTENT_TYPES[dav_name.sub(/folder$/, '')] = self
end