googlecontacts 0.1.1 → 0.1.2
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.
- data/VERSION +1 -1
- data/lib/google_contacts.rb +1 -0
- data/lib/google_contacts/base.rb +8 -20
- data/lib/google_contacts/contact.rb +3 -2
- data/lib/google_contacts/proxies/emails.rb +5 -1
- data/lib/google_contacts/proxies/tag.rb +46 -0
- data/spec/base_spec.rb +5 -5
- data/spec/contact_spec.rb +23 -1
- data/spec/proxies/tag_spec.rb +87 -0
- metadata +4 -1
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.1.
|
1
|
+
0.1.2
|
data/lib/google_contacts.rb
CHANGED
data/lib/google_contacts/base.rb
CHANGED
@@ -15,7 +15,7 @@ module GoogleContacts
|
|
15
15
|
raise "Cannot create instance of Base" if self.class.name.split(/::/).last == 'Base'
|
16
16
|
@wrapper = wrapper
|
17
17
|
@xml = self.class.decorate_with_namespaces(xml || initialize_xml_document)
|
18
|
-
@proxies =
|
18
|
+
@proxies = HashWithIndifferentAccess.new
|
19
19
|
end
|
20
20
|
|
21
21
|
def self.namespace(node, prefix)
|
@@ -27,7 +27,7 @@ module GoogleContacts
|
|
27
27
|
def self.insert_xml(parent, tag, attributes = {}, &blk)
|
28
28
|
# Construct new node with the right namespace
|
29
29
|
matches = tag.match /^((\w+):)?(\w+)$/
|
30
|
-
ns = matches[2] || 'atom'
|
30
|
+
ns = matches[2] == 'xmlns' ? 'atom' : (matches[2] || 'atom')
|
31
31
|
tag = matches[3]
|
32
32
|
node = Nokogiri::XML::Node.new(tag, parent)
|
33
33
|
node.namespace = namespace(parent, ns) || raise("Unknown namespace: #{ns}")
|
@@ -80,32 +80,20 @@ module GoogleContacts
|
|
80
80
|
end
|
81
81
|
|
82
82
|
def new?
|
83
|
-
|
83
|
+
xml.at_xpath('./xmlns:id').nil?
|
84
84
|
end
|
85
85
|
|
86
86
|
def id
|
87
|
-
|
87
|
+
xml.at_xpath('./xmlns:id').text.strip unless new?
|
88
88
|
end
|
89
89
|
|
90
90
|
def updated_at
|
91
|
-
Time.parse
|
91
|
+
Time.parse xml.at_xpath('./xmlns:updated').text.strip unless new?
|
92
92
|
end
|
93
93
|
|
94
94
|
def url(rel)
|
95
95
|
rel = 'http://schemas.google.com/contacts/2008/rel#photo' if rel == :photo
|
96
|
-
at_xpath(%{xmlns:link[@rel="#{rel}"]})[:href]
|
97
|
-
end
|
98
|
-
|
99
|
-
def at(*args)
|
100
|
-
xml.at(*args)
|
101
|
-
end
|
102
|
-
|
103
|
-
def at_xpath(*args)
|
104
|
-
xml.at_xpath(*args)
|
105
|
-
end
|
106
|
-
|
107
|
-
def xpath(*args)
|
108
|
-
xml.xpath(*args)
|
96
|
+
xml.at_xpath(%{xmlns:link[@rel="#{rel}"]})[:href]
|
109
97
|
end
|
110
98
|
|
111
99
|
def changed?
|
@@ -131,9 +119,9 @@ module GoogleContacts
|
|
131
119
|
def method_missing(sym, *args, &blk)
|
132
120
|
if sym.to_s =~ /^(\w+)(=)?$/ && @proxies[$1.to_sym]
|
133
121
|
if $2
|
134
|
-
@proxies[
|
122
|
+
@proxies[$1].replace(args.first)
|
135
123
|
else
|
136
|
-
@proxies[
|
124
|
+
@proxies[$1]
|
137
125
|
end
|
138
126
|
else
|
139
127
|
super
|
@@ -1,11 +1,12 @@
|
|
1
1
|
module GoogleContacts
|
2
2
|
class Contact < Base
|
3
3
|
CATEGORY_TERM = 'http://schemas.google.com/contact/2008#contact'
|
4
|
-
|
5
|
-
|
4
|
+
|
5
|
+
alias_attribute :name, :title
|
6
6
|
def initialize(*args)
|
7
7
|
super
|
8
8
|
|
9
|
+
register_proxy :title, Proxies::Tag.new(self, :tag => 'xmlns:title')
|
9
10
|
register_proxy :emails, Proxies::Emails.new(self)
|
10
11
|
register_proxy :groups, Proxies::Array.new(self,
|
11
12
|
:tag => 'gContact:groupMembershipInfo',
|
@@ -47,6 +47,10 @@ module GoogleContacts
|
|
47
47
|
@parent.insert_xml('gd:email', email)
|
48
48
|
end
|
49
49
|
end
|
50
|
+
|
51
|
+
def inspect
|
52
|
+
@new.values.inspect
|
53
|
+
end
|
50
54
|
|
51
55
|
private
|
52
56
|
def add(address)
|
@@ -104,7 +108,7 @@ module GoogleContacts
|
|
104
108
|
def dup
|
105
109
|
self.class.new(@parent, self)
|
106
110
|
end
|
107
|
-
|
111
|
+
|
108
112
|
def method_missing(sym, *args, &blk)
|
109
113
|
if sym.to_s =~ /^(\w+)(=|\?)?$/
|
110
114
|
case $2
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module GoogleContacts
|
2
|
+
module Proxies
|
3
|
+
class Tag < BlankSlate
|
4
|
+
def initialize(parent, options)
|
5
|
+
@parent = parent
|
6
|
+
@tag = options[:tag]
|
7
|
+
|
8
|
+
reinitialize
|
9
|
+
end
|
10
|
+
|
11
|
+
def reinitialize
|
12
|
+
@current = node.try(:content)
|
13
|
+
@new = @current ? @current.dup : nil
|
14
|
+
end
|
15
|
+
|
16
|
+
def changed?
|
17
|
+
@current != @new
|
18
|
+
end
|
19
|
+
|
20
|
+
def replace(content)
|
21
|
+
@new = content.to_s
|
22
|
+
end
|
23
|
+
|
24
|
+
def synchronize
|
25
|
+
(node || insert_node).content = @new
|
26
|
+
end
|
27
|
+
|
28
|
+
private
|
29
|
+
def node
|
30
|
+
@parent.xml.at_xpath("./#{@tag}")
|
31
|
+
end
|
32
|
+
|
33
|
+
def insert_node
|
34
|
+
@parent.insert_xml(@tag)
|
35
|
+
end
|
36
|
+
|
37
|
+
def method_missing(sym, *args, &blk)
|
38
|
+
if @new.respond_to?(sym)
|
39
|
+
@new.send(sym, *args, &blk)
|
40
|
+
else
|
41
|
+
super
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end # class Tag
|
45
|
+
end # module Proxies
|
46
|
+
end # module GoogleContacts
|
data/spec/base_spec.rb
CHANGED
@@ -19,17 +19,17 @@ describe Base do
|
|
19
19
|
it "should default namespace to document default" do
|
20
20
|
node = @t.insert_xml 'tag'
|
21
21
|
node.namespace.href.should == 'http://www.w3.org/2005/Atom'
|
22
|
-
@t.xpath('xmlns:tag').should have(1).node
|
22
|
+
@t.xml.xpath('xmlns:tag').should have(1).node
|
23
23
|
end
|
24
24
|
|
25
25
|
it "should set namespace when specified in tag" do
|
26
26
|
node = @t.insert_xml 'gd:extendedProperty'
|
27
27
|
node.namespace.href.should == 'http://schemas.google.com/g/2005'
|
28
|
-
@t.xpath('gd:extendedProperty').should have(1).node
|
28
|
+
@t.xml.xpath('gd:extendedProperty').should have(1).node
|
29
29
|
|
30
30
|
node = @t.insert_xml 'gContact:birthday'
|
31
31
|
node.namespace.href.should == 'http://schemas.google.com/contact/2008'
|
32
|
-
@t.xpath('gContact:birthday').should have(1).node
|
32
|
+
@t.xml.xpath('gContact:birthday').should have(1).node
|
33
33
|
end
|
34
34
|
|
35
35
|
it "should raise on unknown namespace" do
|
@@ -45,10 +45,10 @@ describe Base do
|
|
45
45
|
|
46
46
|
it "should allow removing xml" do
|
47
47
|
@t.insert_xml 'gd:extendedProperty'
|
48
|
-
@t.xpath('./gd:extendedProperty').should have(1).node
|
48
|
+
@t.xml.xpath('./gd:extendedProperty').should have(1).node
|
49
49
|
|
50
50
|
@t.remove_xml 'gd:extendedProperty'
|
51
|
-
@t.xpath('./gd:extendedProperty').should have(:no).nodes
|
51
|
+
@t.xml.xpath('./gd:extendedProperty').should have(:no).nodes
|
52
52
|
end
|
53
53
|
end
|
54
54
|
|
data/spec/contact_spec.rb
CHANGED
@@ -25,6 +25,10 @@ describe Contact do
|
|
25
25
|
@contact[:pet].should == 'hamster'
|
26
26
|
end
|
27
27
|
|
28
|
+
it "should initialize the title tag" do
|
29
|
+
@contact.title.should == 'Fitzwilliam Darcy'
|
30
|
+
end
|
31
|
+
|
28
32
|
it "should not be changed? initially" do
|
29
33
|
@contact.changed?.should be_false
|
30
34
|
end
|
@@ -42,9 +46,18 @@ describe Contact do
|
|
42
46
|
@contact.url(:photo).should == 'http://www.google.com/m8/feeds/photos/media/liz%40gmail.com/c9012de'
|
43
47
|
end
|
44
48
|
end
|
49
|
+
|
50
|
+
describe "updating" do
|
51
|
+
it "should update the title-tag" do
|
52
|
+
@contact.xml.at('./xmlns:title').content.should == 'Fitzwilliam Darcy'
|
53
|
+
@contact.title = 'foo'
|
54
|
+
@contact.title.synchronize
|
55
|
+
@contact.xml.at('./xmlns:title').content.should == 'foo'
|
56
|
+
end
|
57
|
+
end
|
45
58
|
end
|
46
59
|
|
47
|
-
describe "
|
60
|
+
describe "from scratch" do
|
48
61
|
before(:each) do
|
49
62
|
@contact = Contact.new(wrapper)
|
50
63
|
@root = @contact.xml.document.root
|
@@ -76,5 +89,14 @@ describe Contact do
|
|
76
89
|
@contact.emails['foo@bar.com'].should be_primary
|
77
90
|
@contact.emails.size.should == 1
|
78
91
|
end
|
92
|
+
|
93
|
+
describe "when updating" do
|
94
|
+
it "should update the title-tag" do
|
95
|
+
@contact.xml.at('./xmlns:title').should be_nil
|
96
|
+
@contact.title = 'foo'
|
97
|
+
@contact.title.synchronize
|
98
|
+
@contact.xml.at('./xmlns:title').content.should == 'foo'
|
99
|
+
end
|
100
|
+
end
|
79
101
|
end
|
80
102
|
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
require File.dirname(__FILE__) + '/../spec_helper'
|
2
|
+
|
3
|
+
describe Proxies::Tag do
|
4
|
+
describe "with existing entries" do
|
5
|
+
before(:each) do
|
6
|
+
create_proxy_from_xml <<-XML
|
7
|
+
<entry xmlns:atom="http://www.w3.org/2005/Atom">
|
8
|
+
<atom:title>Example</atom:title>
|
9
|
+
</entry>
|
10
|
+
XML
|
11
|
+
end
|
12
|
+
|
13
|
+
it "should initialize" do
|
14
|
+
@proxy.should == 'Example'
|
15
|
+
end
|
16
|
+
|
17
|
+
it "should not be changed when initialized" do
|
18
|
+
@proxy.changed?.should be_false
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
describe "without existing entries" do
|
23
|
+
before(:each) do
|
24
|
+
create_proxy_from_xml <<-XML
|
25
|
+
<entry xmlns:atom="http://www.w3.org/2005/Atom">
|
26
|
+
</entry>
|
27
|
+
XML
|
28
|
+
end
|
29
|
+
|
30
|
+
it "should initialize the value to nil" do
|
31
|
+
@proxy.nil?.should be_true
|
32
|
+
end
|
33
|
+
|
34
|
+
it "should not create the tag when initializing" do
|
35
|
+
@parent.xml.xpath('./atom:title').should have(:no).entries
|
36
|
+
end
|
37
|
+
|
38
|
+
it "should not be changed when initialized" do
|
39
|
+
@proxy.changed?.should be_false
|
40
|
+
end
|
41
|
+
|
42
|
+
it "should be changed when replace is called" do
|
43
|
+
@proxy.replace("Test")
|
44
|
+
@proxy.changed?.should be_true
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
describe "synchronize to xml document" do
|
49
|
+
describe "when tag doesn't exist" do
|
50
|
+
before(:each) do
|
51
|
+
create_proxy_from_xml <<-XML
|
52
|
+
<entry xmlns:atom="http://www.w3.org/2005/Atom">
|
53
|
+
</entry>
|
54
|
+
XML
|
55
|
+
end
|
56
|
+
|
57
|
+
it "should create the tag" do
|
58
|
+
@node = mock('node') { expects(:content=).with('Example') }
|
59
|
+
@parent.expects(:insert_xml).with('atom:title').returns(@node)
|
60
|
+
@proxy.replace("Example")
|
61
|
+
@proxy.synchronize
|
62
|
+
end
|
63
|
+
end
|
64
|
+
|
65
|
+
describe "when tag exists" do
|
66
|
+
before(:each) do
|
67
|
+
create_proxy_from_xml <<-XML
|
68
|
+
<entry xmlns:atom="http://www.w3.org/2005/Atom">
|
69
|
+
<atom:title>Example</atom:title>
|
70
|
+
</entry>
|
71
|
+
XML
|
72
|
+
end
|
73
|
+
|
74
|
+
it "should update the tag" do
|
75
|
+
@proxy.replace("Replacement")
|
76
|
+
@proxy.synchronize
|
77
|
+
@parent.xml.at('./atom:title').content.should == 'Replacement'
|
78
|
+
end
|
79
|
+
end
|
80
|
+
end
|
81
|
+
|
82
|
+
def create_proxy_from_xml(str)
|
83
|
+
@parent = stub('parent', :xml => Nokogiri::XML.parse(str).root)
|
84
|
+
@proxy = Proxies::Tag.new(@parent, :tag => 'atom:title')
|
85
|
+
end
|
86
|
+
end
|
87
|
+
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: googlecontacts
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Pieter Noordhuis
|
@@ -97,6 +97,7 @@ files:
|
|
97
97
|
- lib/google_contacts/proxies/array.rb
|
98
98
|
- lib/google_contacts/proxies/emails.rb
|
99
99
|
- lib/google_contacts/proxies/hash.rb
|
100
|
+
- lib/google_contacts/proxies/tag.rb
|
100
101
|
- lib/google_contacts/wrapper.rb
|
101
102
|
- lib/googlecontacts.rb
|
102
103
|
- spec/assets/contacts_full.xml
|
@@ -107,6 +108,7 @@ files:
|
|
107
108
|
- spec/proxies/array_spec.rb
|
108
109
|
- spec/proxies/emails_spec.rb
|
109
110
|
- spec/proxies/hash_spec.rb
|
111
|
+
- spec/proxies/tag_spec.rb
|
110
112
|
- spec/spec.opts
|
111
113
|
- spec/spec_helper.rb
|
112
114
|
- spec/wrapper_spec.rb
|
@@ -146,5 +148,6 @@ test_files:
|
|
146
148
|
- spec/proxies/array_spec.rb
|
147
149
|
- spec/proxies/emails_spec.rb
|
148
150
|
- spec/proxies/hash_spec.rb
|
151
|
+
- spec/proxies/tag_spec.rb
|
149
152
|
- spec/spec_helper.rb
|
150
153
|
- spec/wrapper_spec.rb
|