googlecontacts 0.1.8 → 0.2.0

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,4 @@
1
+ *.gem
2
+ .bundle
3
+ Gemfile.lock
4
+ pkg/*
data/Gemfile ADDED
@@ -0,0 +1,9 @@
1
+ source "http://rubygems.org"
2
+
3
+ gemspec
4
+
5
+ group :test do
6
+ gem "rake"
7
+ gem "rspec", "~> 2.7"
8
+ gem "fakeweb", "~> 1.3.0"
9
+ end
data/LICENSE CHANGED
@@ -1,4 +1,4 @@
1
- Copyright (c) 2010 Pieter Noordhuis
1
+ Copyright (c) 2010-2011 Pieter Noordhuis
2
2
 
3
3
  Permission is hereby granted, free of charge, to any person obtaining
4
4
  a copy of this software and associated documentation files (the
data/Rakefile CHANGED
@@ -1,51 +1,8 @@
1
- require 'rubygems'
2
- require 'rake'
1
+ require "bundler/gem_tasks"
2
+ require "rspec/core/rake_task"
3
3
 
4
- begin
5
- require 'jeweler'
6
- Jeweler::Tasks.new do |gem|
7
- gem.name = "googlecontacts"
8
- gem.summary = %Q{Contacts API on steroids}
9
- gem.description = %Q{Google Contacts API implementation}
10
- gem.email = "pcnoordhuis@gmail.com"
11
- gem.homepage = "http://github.com/pietern/googlecontacts"
12
- gem.authors = ["Pieter Noordhuis"]
13
- gem.add_development_dependency "rspec", ">= 1.2.9"
14
- gem.add_development_dependency "fakeweb", ">= 1.2.8"
15
- gem.add_development_dependency "mocha", ">= 0.9.8"
16
- gem.add_runtime_dependency "activesupport", ">= 2.3.4"
17
- gem.add_runtime_dependency "nokogiri", ">= 1.4.1"
18
- gem.add_runtime_dependency "oauth", ">= 0.3.6"
19
- # gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
20
- end
21
- Jeweler::GemcutterTasks.new
22
- rescue LoadError
23
- puts "Jeweler (or a dependency) not available. Install it with: gem install jeweler"
4
+ RSpec::Core::RakeTask.new(:spec) do |t|
5
+ t.rspec_opts = ['--backtrace', '--color', '--format nested']
24
6
  end
25
7
 
26
- require 'spec/rake/spectask'
27
- Spec::Rake::SpecTask.new(:spec) do |spec|
28
- spec.libs << 'lib' << 'spec'
29
- spec.spec_files = FileList['spec/**/*_spec.rb']
30
- end
31
-
32
- Spec::Rake::SpecTask.new(:rcov) do |spec|
33
- spec.libs << 'lib' << 'spec'
34
- spec.pattern = 'spec/**/*_spec.rb'
35
- spec.rcov = true
36
- spec.rcov_opts += ['--exclude', ENV['GEM_HOME']]
37
- end
38
-
39
- task :spec => :check_dependencies
40
-
41
8
  task :default => :spec
42
-
43
- require 'rake/rdoctask'
44
- Rake::RDocTask.new do |rdoc|
45
- version = File.exist?('VERSION') ? File.read('VERSION') : ""
46
-
47
- rdoc.rdoc_dir = 'rdoc'
48
- rdoc.title = "googlecontacts #{version}"
49
- rdoc.rdoc_files.include('README*')
50
- rdoc.rdoc_files.include('lib/**/*.rb')
51
- end
@@ -0,0 +1,23 @@
1
+ # -*- encoding: utf-8 -*-
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+ require "google_contacts/version"
4
+
5
+ Gem::Specification.new do |s|
6
+ s.name = "googlecontacts"
7
+ s.version = GoogleContacts::VERSION
8
+ s.authors = ["Pieter Noordhuis"]
9
+ s.email = ["pcnoordhuis@gmail.com"]
10
+ s.homepage = ""
11
+ s.summary = %q{Google Contacts API implementation}
12
+
13
+ s.rubyforge_project = "googlecontacts"
14
+
15
+ s.files = `git ls-files`.split("\n")
16
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
17
+ s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
18
+ s.require_paths = ["lib"]
19
+
20
+ s.add_runtime_dependency "activesupport", "~> 3.0"
21
+ s.add_runtime_dependency "nokogiri", "~> 1.5.0"
22
+ s.add_runtime_dependency "oauth", "~> 0.4.5"
23
+ end
@@ -1,18 +1,16 @@
1
1
  $:.unshift File.dirname(__FILE__)
2
- require 'rubygems'
3
- require 'active_support'
4
- require 'active_support/core_ext/hash'
5
- require 'active_support/core_ext/module'
6
- require 'oauth'
7
- require 'nokogiri'
2
+ require "rubygems"
3
+ require "active_support/basic_object"
4
+ require "active_support/core_ext/hash"
5
+ require "oauth"
6
+ require "nokogiri"
8
7
 
9
- require 'google_contacts/auth'
10
- require 'google_contacts/wrapper'
11
- require 'google_contacts/base'
12
- require 'google_contacts/contact'
13
- require 'google_contacts/group'
8
+ require "google_contacts/auth"
9
+ require "google_contacts/wrapper"
10
+ require "google_contacts/contact"
11
+ require "google_contacts/group"
14
12
 
15
- require 'google_contacts/proxies/array'
16
- require 'google_contacts/proxies/hash'
17
- require 'google_contacts/proxies/emails'
18
- require 'google_contacts/proxies/tag'
13
+ require "google_contacts/proxies/array"
14
+ require "google_contacts/proxies/hash"
15
+ require "google_contacts/proxies/emails"
16
+ require "google_contacts/proxies/tag"
@@ -1,10 +1,10 @@
1
1
  module GoogleContacts
2
2
  class Auth
3
3
  GOOGLE_OAUTH = {
4
- :site => 'https://www.google.com',
5
- :request_token_path => '/accounts/OAuthGetRequestToken',
6
- :authorize_path => '/accounts/OAuthAuthorizeToken',
7
- :access_token_path => '/accounts/OAuthGetAccessToken',
4
+ :site => "https://www.google.com",
5
+ :request_token_path => "/accounts/OAuthGetRequestToken",
6
+ :authorize_path => "/accounts/OAuthAuthorizeToken",
7
+ :access_token_path => "/accounts/OAuthGetAccessToken",
8
8
  }.freeze
9
9
 
10
10
  class << self
@@ -21,7 +21,7 @@ module GoogleContacts
21
21
  self.class.consumer.get_request_token({
22
22
  :oauth_callback => options[:callback]
23
23
  }, {
24
- :scope => 'http://www.google.com/m8/feeds/'
24
+ :scope => "http://www.google.com/m8/feeds/"
25
25
  })
26
26
  end
27
27
  end
@@ -1,27 +1,29 @@
1
+ require "time"
2
+
1
3
  module GoogleContacts
2
4
  class Base
3
5
  NAMESPACES = {
4
- 'atom' => 'http://www.w3.org/2005/Atom',
5
- 'openSearch' => 'http://a9.com/-/spec/opensearch/1.1/',
6
- 'gContact' => 'http://schemas.google.com/contact/2008',
7
- 'batch' => 'http://schemas.google.com/gdata/batch',
8
- 'gd' => 'http://schemas.google.com/g/2005',
6
+ "atom" => "http://www.w3.org/2005/Atom",
7
+ "openSearch" => "http://a9.com/-/spec/opensearch/1.1/",
8
+ "gContact" => "http://schemas.google.com/contact/2008",
9
+ "batch" => "http://schemas.google.com/gdata/batch",
10
+ "gd" => "http://schemas.google.com/g/2005",
9
11
  }.freeze
10
12
 
11
13
  attr_reader :xml
12
14
  def initialize(wrapper, xml = nil)
13
- raise "Cannot create instance of Base" if self.class.name.split(/::/).last == 'Base'
15
+ raise "Cannot create instance of Base" if self.class.name.split(/::/).last == "Base"
14
16
  @wrapper = wrapper
15
17
 
16
18
  # If a root node is given, create a new XML document based on
17
19
  # a deep copy. Otherwise, initialize a new XML document.
18
- @xml = if xml.present?
20
+ @xml = if xml
19
21
  self.class.new_xml_document(xml).root
20
22
  else
21
23
  self.class.initialize_xml_document.root
22
24
  end
23
25
 
24
- @proxies = HashWithIndifferentAccess.new
26
+ @proxies = Hash.new
25
27
  register_base_proxies
26
28
  end
27
29
 
@@ -40,40 +42,40 @@ module GoogleContacts
40
42
  end
41
43
 
42
44
  def self.feed_for_batch
43
- new_xml_document('feed').root
45
+ new_xml_document("feed").root
44
46
  end
45
47
 
46
48
  # Create new XML::Document that can be used in a
47
49
  # Google Contacts batch operation.
48
50
  def entry_for_batch(operation)
49
51
  root = self.class.new_xml_document(xml).root
50
- root.xpath('./xmlns:link' ).remove
51
- root.xpath('./xmlns:updated').remove
52
+ root.xpath("./xmlns:link" ).remove
53
+ root.xpath("./xmlns:updated").remove
52
54
 
53
55
  if operation == :update || operation == :delete
54
- root.at('./xmlns:id').content = url(:edit)
56
+ root.at("./xmlns:id").content = url(:edit)
55
57
  end
56
58
 
57
- self.class.insert_xml(root, 'batch:id')
58
- self.class.insert_xml(root, 'batch:operation', :type => operation)
59
+ self.class.insert_xml(root, "batch:id")
60
+ self.class.insert_xml(root, "batch:operation", :type => operation)
59
61
 
60
62
  root
61
63
  end
62
64
 
63
65
  def new?
64
- xml.at_xpath('./xmlns:id').nil?
66
+ xml.at_xpath("./xmlns:id").nil?
65
67
  end
66
68
 
67
69
  def href
68
- xml.at_xpath('./xmlns:id').text.strip unless new?
70
+ xml.at_xpath("./xmlns:id").text.strip unless new?
69
71
  end
70
72
 
71
73
  def updated_at
72
- Time.parse xml.at_xpath('./xmlns:updated').text.strip unless new?
74
+ Time.parse xml.at_xpath("./xmlns:updated").text.strip unless new?
73
75
  end
74
76
 
75
77
  def url(rel)
76
- rel = 'http://schemas.google.com/contacts/2008/rel#photo' if rel == :photo
78
+ rel = "http://schemas.google.com/contacts/2008/rel#photo" if rel == :photo
77
79
  xml.at_xpath(%{xmlns:link[@rel="#{rel}"]})[:href]
78
80
  end
79
81
 
@@ -101,12 +103,18 @@ module GoogleContacts
101
103
  properties[prop] = value
102
104
  end
103
105
 
104
- # Alias the xmlns:title tag be be accessible using #name(=)?
105
- alias_attribute :name, :title
106
+ # Alias "name" to "title"
107
+ def name
108
+ method_missing(:title)
109
+ end
110
+
111
+ def name=(v)
112
+ method_missing(:title=, v)
113
+ end
106
114
 
107
115
  protected
108
116
  def register_proxy(name, proxy)
109
- @proxies[name.to_sym] = proxy
117
+ @proxies[name.to_s] = proxy
110
118
  end
111
119
 
112
120
  def synchronize_proxies
@@ -114,11 +122,11 @@ module GoogleContacts
114
122
  end
115
123
 
116
124
  def register_base_proxies
117
- register_proxy :title, Proxies::Tag.new(self, :tag => 'xmlns:title')
125
+ register_proxy :title, Proxies::Tag.new(self, :tag => "xmlns:title")
118
126
  register_proxy :properties, Proxies::Hash.new(self,
119
- :tag => 'gd:extendedProperty',
120
- :key => 'name',
121
- :value => 'value')
127
+ :tag => "gd:extendedProperty",
128
+ :key => "name",
129
+ :value => "value")
122
130
  end
123
131
 
124
132
  # Try to proxy missing method to one of the proxies
@@ -143,7 +151,7 @@ module GoogleContacts
143
151
  def self.insert_xml(parent, tag, attributes = {}, &blk)
144
152
  # Construct new node with the right namespace
145
153
  matches = tag.match /^((\w+):)?(\w+)$/
146
- ns = matches[2] == 'xmlns' ? 'atom' : (matches[2] || 'atom')
154
+ ns = matches[2] == "xmlns" ? "atom" : (matches[2] || "atom")
147
155
  tag = matches[3]
148
156
  node = Nokogiri::XML::Node.new(tag, parent)
149
157
  node.namespace = namespace(parent, ns) || raise("Unknown namespace: #{ns}")
@@ -169,16 +177,16 @@ module GoogleContacts
169
177
  end
170
178
 
171
179
  def self.initialize_xml_document
172
- doc = new_xml_document('entry')
173
- insert_xml(doc.root, 'atom:category', {
174
- :scheme => 'http://schemas.google.com/g/2005#kind',
180
+ doc = new_xml_document("entry")
181
+ insert_xml(doc.root, "atom:category", {
182
+ :scheme => "http://schemas.google.com/g/2005#kind",
175
183
  :term => const_get(:CATEGORY_TERM)
176
184
  })
177
185
  doc
178
186
  end
179
187
 
180
188
  def self.decorate_document_with_namespaces(doc)
181
- doc.root.default_namespace = NAMESPACES['atom']
189
+ doc.root.default_namespace = NAMESPACES["atom"]
182
190
  NAMESPACES.each_pair do |prefix, href|
183
191
  doc.root.add_namespace(prefix, href)
184
192
  end
@@ -1,18 +1,29 @@
1
+ require "google_contacts/base"
2
+
1
3
  module GoogleContacts
2
4
  class Contact < Base
3
- CATEGORY_TERM = 'http://schemas.google.com/contact/2008#contact'
5
+ CATEGORY_TERM = "http://schemas.google.com/contact/2008#contact"
4
6
 
5
- alias_attribute :name, :title
6
7
  def initialize(*args)
7
8
  super
8
9
  register_proxy :emails, Proxies::Emails.new(self)
9
10
  register_proxy :groups, Proxies::Array.new(self,
10
- :tag => 'gContact:groupMembershipInfo',
11
- :attr => 'href')
11
+ :tag => "gContact:groupMembershipInfo",
12
+ :attr => "href")
13
+ end
14
+
15
+ # Alias "name" to "title"
16
+ def name
17
+ method_missing(:title)
18
+ end
19
+
20
+ def name=(v)
21
+ method_missing(:title=, v)
12
22
  end
13
23
 
14
24
  def email
15
- emails.primary.try(:address)
25
+ primary = emails.primary
26
+ primary && primary.address
16
27
  end
17
28
 
18
29
  def email=(address)
@@ -1,9 +1,11 @@
1
+ require "google_contacts/base"
2
+
1
3
  module GoogleContacts
2
4
  class Group < Base
3
- CATEGORY_TERM = 'http://schemas.google.com/contact/2008#group'
5
+ CATEGORY_TERM = "http://schemas.google.com/contact/2008#group"
4
6
 
5
7
  def system_group?
6
- @xml.xpath('./gContact:systemGroup').size > 0
8
+ @xml.xpath("./gContact:systemGroup").size > 0
7
9
  end
8
10
 
9
11
  def inspect
@@ -48,7 +48,7 @@ module GoogleContacts
48
48
  def synchronize
49
49
  @parent.remove_xml("./gd:email")
50
50
  @new.each_pair do |address, email|
51
- @parent.insert_xml('gd:email', email)
51
+ @parent.insert_xml("gd:email", email)
52
52
  end
53
53
  end
54
54
 
@@ -74,11 +74,9 @@ module GoogleContacts
74
74
 
75
75
  class Email < ::HashWithIndifferentAccess
76
76
  DEFAULTS = {
77
- :rel => 'http://schemas.google.com/g/2005#home'
77
+ :rel => "http://schemas.google.com/g/2005#home"
78
78
  }.freeze
79
79
 
80
- alias_attribute :name, :displayName
81
-
82
80
  def initialize(parent, attributes = {})
83
81
  super(DEFAULTS)
84
82
  @parent = parent
@@ -88,6 +86,15 @@ module GoogleContacts
88
86
  end
89
87
  end
90
88
 
89
+ # Alias "name" to "displayName"
90
+ def name
91
+ method_missing(:displayName)
92
+ end
93
+
94
+ def name=(v)
95
+ method_missing(:displayName=, v)
96
+ end
97
+
91
98
  def primary!
92
99
  @parent.primary! self[:address]
93
100
  end
@@ -103,7 +110,7 @@ module GoogleContacts
103
110
  end
104
111
 
105
112
  def []=(key, value)
106
- if "#{key}" == 'address' && self[key]
113
+ if "#{key}" == "address" && self[key]
107
114
  raise "Cannot modify email address"
108
115
  end
109
116
  super(key, value.to_s)
@@ -116,10 +123,10 @@ module GoogleContacts
116
123
  def method_missing(sym, *args, &blk)
117
124
  if sym.to_s =~ /^(\w+)(=|\?)?$/
118
125
  case $2
119
- when '='
126
+ when "="
120
127
  send(:[]=, $1, *args)
121
- when '?'
122
- send(:[], $1) == 'true'
128
+ when "?"
129
+ send(:[], $1) == "true"
123
130
  else
124
131
  send(:[], $1)
125
132
  end
@@ -11,13 +11,13 @@ module GoogleContacts
11
11
  end
12
12
 
13
13
  def reinitialize
14
- @current = HashWithIndifferentAccess.new
14
+ @current = ::HashWithIndifferentAccess.new
15
15
  @parent.xml.xpath("./#{@tag}").map do |entry|
16
16
  @current[entry[@key]] = entry[@value]
17
17
  end
18
18
 
19
19
  # create a deep copy
20
- @new = HashWithIndifferentAccess.new
20
+ @new = ::HashWithIndifferentAccess.new
21
21
  @current.each { |k,v| @new[k.dup] = v.dup }
22
22
  end
23
23
 
@@ -12,7 +12,7 @@ module GoogleContacts
12
12
  end
13
13
 
14
14
  def reinitialize
15
- @current = node.try(:content)
15
+ @current = node && node.content
16
16
  @new = @current ? @current.dup : nil
17
17
  end
18
18