googlecontacts 0.1.8 → 0.2.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.
@@ -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