motion-addressbook 1.0.0 → 1.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.
- data/.travis.yml +6 -0
- data/README.md +1 -1
- data/lib/motion-addressbook/version.rb +1 -1
- data/lib/motion-addressbook.rb +3 -0
- data/motion/address_book/addr_book.rb +44 -0
- data/motion/address_book/group.rb +99 -0
- data/motion/address_book/multi_valued.rb +91 -0
- data/motion/address_book/person.rb +189 -53
- data/motion/address_book.rb +5 -1
- data/spec/address_book/group_spec.rb +59 -0
- data/spec/address_book/multi_valued_spec.rb +66 -0
- data/spec/address_book/person_spec.rb +223 -43
- data/spec/helpers/person_helpers.rb +8 -0
- metadata +12 -4
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
# Addressbook for RubyMotion
|
1
|
+
# Addressbook for RubyMotion[](http://travis-ci.org/alexrothenberg/motion-addressbook) [](https://codeclimate.com/github/alexrothenberg/motion-addressbook) [](http://badge.fury.io/rb/motion-addressbook)
|
2
2
|
|
3
3
|
A RubyMotion wrapper around the iOS Address Book framework for RubyMotion apps.
|
4
4
|
|
data/lib/motion-addressbook.rb
CHANGED
@@ -4,7 +4,10 @@ BubbleWrap.require 'motion/address_book.rb' do
|
|
4
4
|
file('motion/address_book.rb').uses_framework('AddressBook')
|
5
5
|
end
|
6
6
|
BW.require 'motion/address_book/multi_value.rb'
|
7
|
+
BW.require 'motion/address_book/addr_book.rb'
|
7
8
|
BW.require 'motion/address_book/person.rb'
|
9
|
+
BW.require 'motion/address_book/group.rb'
|
10
|
+
BW.require 'motion/address_book/multi_valued.rb'
|
8
11
|
BW.require 'motion/address_book/picker.rb' do
|
9
12
|
file('motion/address_book/picker.rb').uses_framework('AddressBookUI')
|
10
13
|
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
module AddressBook
|
2
|
+
class AddrBook
|
3
|
+
attr_reader :ab
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@ab = AddressBook.address_book
|
7
|
+
end
|
8
|
+
def people
|
9
|
+
ABAddressBookCopyArrayOfAllPeople(ab).map do |ab_person|
|
10
|
+
AddressBook::Person.new({}, ab_person, :address_book => ab)
|
11
|
+
end
|
12
|
+
end
|
13
|
+
def count
|
14
|
+
ABAddressBookGetPersonCount(@ab)
|
15
|
+
end
|
16
|
+
def new_person(attributes)
|
17
|
+
Person.new(attributes, nil, :address_book => @ab)
|
18
|
+
end
|
19
|
+
def create_person(attributes)
|
20
|
+
p = Person.new(attributes, nil, :address_book => @ab)
|
21
|
+
p.save
|
22
|
+
p
|
23
|
+
end
|
24
|
+
def person(id)
|
25
|
+
(p = ABAddressBookGetPersonWithRecordID(ab, id)) && Person.new(nil, p, :address_book => ab)
|
26
|
+
end
|
27
|
+
|
28
|
+
def groups
|
29
|
+
ABAddressBookCopyArrayOfAllGroups(@ab).map do |ab_group|
|
30
|
+
AddressBook::Group.new(:ab_group => ab_group, :address_book => @ab)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
def new_group(attributes)
|
34
|
+
AddressBook::Group.new(:attributes => attributes, :address_book => @ab)
|
35
|
+
end
|
36
|
+
def group(id)
|
37
|
+
(g = ABAddressBookGetGroupWithRecordID(ab, id)) && Group.new(:ab_group => g, :address_book => @ab)
|
38
|
+
end
|
39
|
+
|
40
|
+
def notify_changes(callback, context)
|
41
|
+
ABAddressBookRegisterExternalChangeCallback(ab, callback, context)
|
42
|
+
end
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
# Wrapper for iOS ABGroup
|
2
|
+
#
|
3
|
+
# * groups are saved to the database immediately upon new()
|
4
|
+
# * members are added with <<
|
5
|
+
#
|
6
|
+
module AddressBook
|
7
|
+
class Group
|
8
|
+
attr_reader :attributes, :error
|
9
|
+
|
10
|
+
def initialize(opts)
|
11
|
+
@address_book = opts[:address_book]
|
12
|
+
if opts[:ab_group]
|
13
|
+
# import existing
|
14
|
+
@ab_group = opts[:ab_group]
|
15
|
+
@attributes = nil
|
16
|
+
else
|
17
|
+
# create new
|
18
|
+
@ab_group = nil
|
19
|
+
@attributes = opts[:attributes]
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
def address_book
|
24
|
+
@address_book ||= AddressBook.address_book
|
25
|
+
end
|
26
|
+
|
27
|
+
def save
|
28
|
+
ABAddressBookAddRecord(address_book, ab_group, error)
|
29
|
+
ABAddressBookSave(address_book, error)
|
30
|
+
@attributes = nil
|
31
|
+
@new_record = false
|
32
|
+
self
|
33
|
+
end
|
34
|
+
|
35
|
+
def new?
|
36
|
+
uid == KABRecordInvalidID
|
37
|
+
end
|
38
|
+
|
39
|
+
def delete!
|
40
|
+
unless new?
|
41
|
+
ABAddressBookRemoveRecord(address_book, ab_group, error)
|
42
|
+
ABAddressBookSave(address_book, error)
|
43
|
+
@ab_group = nil
|
44
|
+
self
|
45
|
+
end
|
46
|
+
end
|
47
|
+
|
48
|
+
def ab_group
|
49
|
+
@ab_group || convert_dict_to_ab
|
50
|
+
end
|
51
|
+
alias :ab_record :ab_group
|
52
|
+
|
53
|
+
def uid
|
54
|
+
ABRecordGetRecordID(ab_group)
|
55
|
+
end
|
56
|
+
|
57
|
+
def name
|
58
|
+
ABRecordCopyValue(ab_group, KABGroupNameProperty)
|
59
|
+
end
|
60
|
+
|
61
|
+
def size
|
62
|
+
members.count
|
63
|
+
end
|
64
|
+
|
65
|
+
def members
|
66
|
+
(ABGroupCopyArrayOfAllMembers(ab_group) || []).map do |ab_record|
|
67
|
+
case rectype = ABRecordGetRecordType(ab_record)
|
68
|
+
when KABPersonType
|
69
|
+
AddressBook::Person.new({}, ab_record, :address_book => address_book)
|
70
|
+
when KABGroupType
|
71
|
+
AddressBook::Group.new(:ab_group => ab_record, :address_book => address_book)
|
72
|
+
else
|
73
|
+
warn "Unrecognized record type #{rectype} in AB group #{name}"
|
74
|
+
nil
|
75
|
+
end
|
76
|
+
end
|
77
|
+
end
|
78
|
+
|
79
|
+
def <<(person_or_group)
|
80
|
+
raise "Must save member before adding to group" if person_or_group.new?
|
81
|
+
ABGroupAddMember(ab_group, person_or_group.ab_record, error)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def convert_dict_to_ab
|
87
|
+
@ab_group = ABGroupCreate()
|
88
|
+
|
89
|
+
# groups only have a single regular attribute (name)
|
90
|
+
if v = @attributes[:name]
|
91
|
+
ABRecordSetValue(@ab_group, KABGroupNameProperty, v, error)
|
92
|
+
end
|
93
|
+
|
94
|
+
save
|
95
|
+
|
96
|
+
@ab_group
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,91 @@
|
|
1
|
+
module AddressBook
|
2
|
+
class MultiValued
|
3
|
+
def initialize(opts)
|
4
|
+
unless opts.one?
|
5
|
+
raise ArgumentError, "MultiValued requires :attributes *or* :ab_multi_value argument"
|
6
|
+
end
|
7
|
+
|
8
|
+
if opts[:ab_multi_value]
|
9
|
+
# @ab_multi_value = ABMultiValueCreateMutableCopy(opts[:ab_multi_value])
|
10
|
+
@ab_multi_value = opts[:ab_multi_value]
|
11
|
+
else
|
12
|
+
@attributes = opts[:attributes]
|
13
|
+
end
|
14
|
+
end
|
15
|
+
|
16
|
+
def count
|
17
|
+
ABMultiValueGetCount(ab_multi_value)
|
18
|
+
end
|
19
|
+
alias :size :count
|
20
|
+
|
21
|
+
def attributes
|
22
|
+
@attributes ||= convert_multi_value_into_dictionary
|
23
|
+
end
|
24
|
+
|
25
|
+
def convert_multi_value_into_dictionary
|
26
|
+
count.times.map do |i|
|
27
|
+
label = ABMultiValueCopyLabelAtIndex(@ab_multi_value, i)
|
28
|
+
label_val = ABAddressBookCopyLocalizedLabel(label)
|
29
|
+
data = ab_record_to_dict(ABMultiValueCopyValueAtIndex(@ab_multi_value, i))
|
30
|
+
data.merge(:label => label_val)
|
31
|
+
end
|
32
|
+
end
|
33
|
+
|
34
|
+
def ab_multi_value
|
35
|
+
@ab_multi_value ||= convert_dictionary_into_multi_value
|
36
|
+
end
|
37
|
+
|
38
|
+
def convert_dictionary_into_multi_value
|
39
|
+
if @attributes.find {|rec| rec[:value]}
|
40
|
+
mv = ABMultiValueCreateMutable(KABMultiStringPropertyType)
|
41
|
+
@attributes.each do |rec|
|
42
|
+
ABMultiValueAddValueAndLabel(mv, rec[:value], rec[:label], nil)
|
43
|
+
end
|
44
|
+
mv
|
45
|
+
else
|
46
|
+
mv = ABMultiValueCreateMutable(KABMultiDictionaryPropertyType)
|
47
|
+
@attributes.each do |rec|
|
48
|
+
ABMultiValueAddValueAndLabel(mv, dict_to_ab_record(rec), rec[:label], nil)
|
49
|
+
end
|
50
|
+
mv
|
51
|
+
end
|
52
|
+
end
|
53
|
+
|
54
|
+
# these are for mapping fields in a kABMultiDictionaryPropertyType record
|
55
|
+
# to keys in a standard hash (NSDictionary)
|
56
|
+
@@attribute_map = {
|
57
|
+
KABPersonAddressStreetKey => :street,
|
58
|
+
KABPersonAddressCityKey => :city,
|
59
|
+
KABPersonAddressStateKey => :state,
|
60
|
+
KABPersonAddressZIPKey => :postalcode,
|
61
|
+
KABPersonAddressCountryKey => :country,
|
62
|
+
KABPersonAddressCountryCodeKey => :country_code,
|
63
|
+
|
64
|
+
KABPersonSocialProfileURLKey => :url,
|
65
|
+
KABPersonSocialProfileServiceKey => :service,
|
66
|
+
KABPersonSocialProfileUsernameKey => :username,
|
67
|
+
KABPersonSocialProfileUserIdentifierKey => :userid,
|
68
|
+
|
69
|
+
# these keys are identical to the SocialProfile keys above
|
70
|
+
KABPersonInstantMessageServiceKey => :service,
|
71
|
+
KABPersonInstantMessageUsernameKey => :username
|
72
|
+
}
|
73
|
+
|
74
|
+
def dict_to_ab_record(h)
|
75
|
+
@@attribute_map.each_with_object({}) do |(ab_key, attr_key), ab_record|
|
76
|
+
ab_record[ab_key] = h[attr_key] if h[attr_key]
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
def ab_record_to_dict(ab_record)
|
81
|
+
case ab_record
|
82
|
+
when String
|
83
|
+
{:value => ab_record}
|
84
|
+
else
|
85
|
+
@@attribute_map.each_with_object({}) do |(ab_key, attr_key), dict|
|
86
|
+
dict[attr_key] = ab_record[ab_key] if ab_record[ab_key]
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
@@ -1,24 +1,25 @@
|
|
1
1
|
module AddressBook
|
2
2
|
class Person
|
3
|
-
attr_reader :
|
3
|
+
attr_reader :error
|
4
4
|
|
5
|
-
def initialize(attributes={}, existing_ab_person = nil)
|
6
|
-
@
|
5
|
+
def initialize(attributes={}, existing_ab_person = nil, opts = {})
|
6
|
+
@address_book = opts[:address_book]
|
7
7
|
if existing_ab_person.nil?
|
8
|
-
@
|
8
|
+
@ab_person = nil
|
9
|
+
@attributes = attributes
|
9
10
|
else
|
10
11
|
@ab_person = existing_ab_person
|
11
|
-
|
12
|
-
@new_record = false
|
12
|
+
@attributes = nil
|
13
13
|
end
|
14
14
|
end
|
15
15
|
|
16
16
|
def self.all
|
17
|
-
|
17
|
+
ab = AddressBook.address_book
|
18
|
+
ab_people = ABAddressBookCopyArrayOfAllPeople(ab)
|
18
19
|
return [] if ab_people.nil?
|
19
20
|
|
20
21
|
people = ab_people.map do |ab_person|
|
21
|
-
new({}, ab_person)
|
22
|
+
new({}, ab_person, :address_book => ab)
|
22
23
|
end
|
23
24
|
people.sort! { |a,b| "#{a.first_name} #{a.last_name}" <=> "#{b.first_name} #{b.last_name}" }
|
24
25
|
people
|
@@ -32,9 +33,26 @@ module AddressBook
|
|
32
33
|
|
33
34
|
def save
|
34
35
|
ABAddressBookAddRecord(address_book, ab_person, error)
|
35
|
-
ABAddressBookSave(address_book, error
|
36
|
-
@
|
37
|
-
|
36
|
+
ABAddressBookSave(address_book, error)
|
37
|
+
@attributes = nil # force refresh
|
38
|
+
uid
|
39
|
+
end
|
40
|
+
|
41
|
+
def attributes
|
42
|
+
@attributes || import_ab_person
|
43
|
+
end
|
44
|
+
|
45
|
+
def ab_person
|
46
|
+
if @ab_person.nil?
|
47
|
+
@ab_person = ABPersonCreate()
|
48
|
+
load_ab_person
|
49
|
+
end
|
50
|
+
@ab_person
|
51
|
+
end
|
52
|
+
alias :ab_record :ab_person
|
53
|
+
|
54
|
+
def uid
|
55
|
+
ABRecordGetRecordID(ab_person)
|
38
56
|
end
|
39
57
|
|
40
58
|
def self.where(conditions)
|
@@ -45,16 +63,27 @@ module AddressBook
|
|
45
63
|
|
46
64
|
def meets?(conditions)
|
47
65
|
conditions.keys.all? do |attribute|
|
48
|
-
|
66
|
+
case attribute
|
67
|
+
when :email
|
68
|
+
emails.attributes.map {|rec| rec[:value]}.any? {|v| v == conditions[attribute]}
|
69
|
+
else
|
70
|
+
send(attribute) == conditions[attribute]
|
71
|
+
end
|
49
72
|
end
|
50
73
|
end
|
51
74
|
|
52
75
|
def self.attribute_map
|
53
|
-
{
|
76
|
+
{
|
77
|
+
:first_name => KABPersonFirstNameProperty,
|
78
|
+
:middle_name => KABPersonMiddleNameProperty,
|
54
79
|
:last_name => KABPersonLastNameProperty,
|
80
|
+
:suffix => KABPersonSuffixProperty,
|
81
|
+
:nickname => KABPersonNicknameProperty,
|
55
82
|
:job_title => KABPersonJobTitleProperty,
|
56
83
|
:department => KABPersonDepartmentProperty,
|
57
|
-
:organization => KABPersonOrganizationProperty
|
84
|
+
:organization => KABPersonOrganizationProperty,
|
85
|
+
# :dob => KABPersonBirthdayProperty,
|
86
|
+
:note => KABPersonNoteProperty
|
58
87
|
}
|
59
88
|
end
|
60
89
|
def attribute_map
|
@@ -136,14 +165,26 @@ module AddressBook
|
|
136
165
|
attributes[attribute_name.to_sym] = value
|
137
166
|
end
|
138
167
|
|
168
|
+
def self.find_by_uid(criteria)
|
169
|
+
find_by :uid, criteria
|
170
|
+
end
|
171
|
+
|
139
172
|
def self.find_all_by(attribute_name, criteria)
|
140
173
|
where({attribute_name.to_sym => criteria})
|
141
174
|
end
|
142
175
|
def self.find_by(attribute_name, criteria)
|
143
176
|
find_all_by(attribute_name, criteria).first
|
144
177
|
end
|
178
|
+
def self.new_by(attribute_name, criteria)
|
179
|
+
case attr_sym = attribute_name.to_sym
|
180
|
+
when :email
|
181
|
+
new({:emails => [{:value => criteria}]})
|
182
|
+
else
|
183
|
+
new({attr_sym => criteria})
|
184
|
+
end
|
185
|
+
end
|
145
186
|
def self.find_or_new_by(attribute_name, criteria)
|
146
|
-
find_by(attribute_name, criteria) ||
|
187
|
+
find_by(attribute_name, criteria) || new_by(attribute_name, criteria)
|
147
188
|
end
|
148
189
|
|
149
190
|
def photo
|
@@ -154,39 +195,51 @@ module AddressBook
|
|
154
195
|
ABPersonSetImageData(ab_person, photo_data, error)
|
155
196
|
end
|
156
197
|
|
198
|
+
def get_multi_valued(field)
|
199
|
+
MultiValued.new(:ab_multi_value => ABRecordCopyValue(ab_person, field))
|
200
|
+
end
|
157
201
|
|
158
|
-
def
|
159
|
-
|
202
|
+
def phones
|
203
|
+
get_multi_valued(KABPersonPhoneProperty)
|
160
204
|
end
|
161
205
|
|
162
|
-
def
|
163
|
-
|
206
|
+
def phone_values
|
207
|
+
phones.attributes.map {|r| r[:value]}
|
164
208
|
end
|
165
209
|
|
166
210
|
def emails
|
167
|
-
|
211
|
+
get_multi_valued(KABPersonEmailProperty)
|
168
212
|
end
|
169
213
|
|
170
214
|
def email_values
|
171
|
-
emails.
|
215
|
+
emails.attributes.map {|r| r[:value]}
|
172
216
|
end
|
173
217
|
|
174
|
-
|
175
|
-
|
176
|
-
@attributes[:email] ||= email_values.first
|
218
|
+
def addresses
|
219
|
+
get_multi_valued(KABPersonAddressProperty)
|
177
220
|
end
|
178
|
-
|
179
|
-
|
221
|
+
|
222
|
+
def urls
|
223
|
+
get_multi_valued(KABPersonURLProperty)
|
180
224
|
end
|
181
225
|
|
182
|
-
def
|
183
|
-
|
184
|
-
|
185
|
-
|
186
|
-
|
187
|
-
|
226
|
+
def social_profiles
|
227
|
+
get_multi_valued(KABPersonSocialProfileProperty)
|
228
|
+
end
|
229
|
+
|
230
|
+
def im_profiles
|
231
|
+
get_multi_valued(KABPersonInstantMessageProperty)
|
232
|
+
end
|
233
|
+
|
234
|
+
def related_names
|
235
|
+
get_multi_valued(KABPersonRelatedNamesProperty)
|
188
236
|
end
|
189
237
|
|
238
|
+
def email; email_values.first; end
|
239
|
+
def phone; phone_values.first; end
|
240
|
+
def url; urls.attributes.first[:value]; end
|
241
|
+
def address; addresses.attributes.first; end
|
242
|
+
|
190
243
|
def find_or_new
|
191
244
|
if new_record?
|
192
245
|
new_ab_person
|
@@ -196,45 +249,129 @@ module AddressBook
|
|
196
249
|
end
|
197
250
|
|
198
251
|
def new_record?
|
199
|
-
|
252
|
+
uid == KABRecordInvalidID
|
200
253
|
end
|
254
|
+
alias :new? :new_record?
|
201
255
|
def exists?
|
202
256
|
!new_record?
|
203
257
|
end
|
204
|
-
|
205
|
-
|
206
|
-
|
207
|
-
|
258
|
+
|
259
|
+
def delete!
|
260
|
+
unless new_record?
|
261
|
+
ABAddressBookRemoveRecord(address_book, ab_person, error)
|
262
|
+
ABAddressBookSave(address_book, error)
|
263
|
+
@ab_person = nil
|
264
|
+
self
|
208
265
|
end
|
266
|
+
end
|
209
267
|
|
210
|
-
|
268
|
+
def composite_name
|
269
|
+
ABRecordCopyCompositeName(ab_person)
|
270
|
+
end
|
271
|
+
|
272
|
+
def person?
|
273
|
+
get_field(KABPersonKindProperty) == KABPersonKindPerson
|
274
|
+
end
|
275
|
+
def organization?
|
276
|
+
get_field(KABPersonKindProperty) == KABPersonKindOrganization
|
277
|
+
end
|
278
|
+
|
279
|
+
# must stash date values in instance variables or RubyMotion throws a malloc error
|
280
|
+
def creation_date
|
281
|
+
@creation_date = get_field(KABPersonCreationDateProperty)
|
282
|
+
end
|
283
|
+
|
284
|
+
def modification_date
|
285
|
+
@modification_date = get_field(KABPersonModificationDateProperty)
|
211
286
|
end
|
212
287
|
|
213
288
|
private
|
214
289
|
|
290
|
+
def single_value_property_map
|
291
|
+
{
|
292
|
+
KABPersonFirstNameProperty => :first_name,
|
293
|
+
KABPersonLastNameProperty => :last_name,
|
294
|
+
KABPersonMiddleNameProperty => :middle_name,
|
295
|
+
KABPersonSuffixProperty => :suffix,
|
296
|
+
KABPersonNicknameProperty => :nickname,
|
297
|
+
KABPersonJobTitleProperty => :job_title,
|
298
|
+
KABPersonDepartmentProperty => :department,
|
299
|
+
KABPersonOrganizationProperty => :organization,
|
300
|
+
# KABPersonBirthdayProperty => :dob,
|
301
|
+
KABPersonNoteProperty => :note
|
302
|
+
}
|
303
|
+
end
|
304
|
+
|
305
|
+
def multi_value_property_map
|
306
|
+
{
|
307
|
+
KABPersonPhoneProperty => :phones,
|
308
|
+
KABPersonEmailProperty => :emails,
|
309
|
+
KABPersonAddressProperty => :addresses,
|
310
|
+
KABPersonURLProperty => :urls,
|
311
|
+
KABPersonSocialProfileProperty => :social_profiles,
|
312
|
+
KABPersonInstantMessageProperty => :im_profiles,
|
313
|
+
KABPersonRelatedNamesProperty => :related_names
|
314
|
+
}
|
315
|
+
end
|
316
|
+
|
317
|
+
# instantiates ABPerson record from attributes
|
215
318
|
def load_ab_person
|
216
|
-
|
217
|
-
|
218
|
-
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
319
|
+
@attributes ||= {}
|
320
|
+
|
321
|
+
single_value_property_map.each do |ab_property, attr_key|
|
322
|
+
if attributes[attr_key]
|
323
|
+
set_field(ab_property, attributes[attr_key])
|
324
|
+
end
|
325
|
+
end
|
326
|
+
|
327
|
+
if attributes[:is_org]
|
328
|
+
set_field(KABPersonKindProperty, KABPersonKindOrganization)
|
329
|
+
else
|
330
|
+
set_field(KABPersonKindProperty, KABPersonKindPerson)
|
331
|
+
end
|
332
|
+
|
333
|
+
multi_value_property_map.each do |ab_property, attr_key|
|
334
|
+
if attributes[attr_key]
|
335
|
+
set_multi_valued(ab_property, attributes[attr_key])
|
336
|
+
end
|
337
|
+
end
|
338
|
+
end
|
339
|
+
|
340
|
+
def import_ab_person
|
341
|
+
@attributes = {}
|
342
|
+
single_value_property_map.each do |ab_property, attr_key|
|
343
|
+
if value = get_field(ab_property)
|
344
|
+
@attributes[attr_key] = value
|
345
|
+
end
|
346
|
+
end
|
347
|
+
|
348
|
+
if organization?
|
349
|
+
@attributes[:is_org] = true
|
350
|
+
end
|
351
|
+
|
352
|
+
multi_value_property_map.each do |ab_property, attr_key|
|
353
|
+
if (value = get_multi_valued(ab_property).attributes) && value.any?
|
354
|
+
@attributes[attr_key] = value
|
355
|
+
end
|
356
|
+
end
|
357
|
+
|
358
|
+
@attributes
|
223
359
|
end
|
224
360
|
|
225
361
|
def set_field(field, value)
|
226
|
-
|
362
|
+
if value
|
363
|
+
ABRecordSetValue(ab_person, field, value, error)
|
364
|
+
end
|
227
365
|
end
|
228
366
|
def get_field(field)
|
229
367
|
ABRecordCopyValue(ab_person, field)
|
230
368
|
end
|
231
369
|
|
232
|
-
def
|
233
|
-
|
234
|
-
|
235
|
-
|
236
|
-
|
237
|
-
MultiValue.new({}, ABRecordCopyValue(ab_person, field))
|
370
|
+
def set_multi_valued(field, values)
|
371
|
+
if values && values.any?
|
372
|
+
multi_field = MultiValued.new(:attributes => values)
|
373
|
+
ABRecordSetValue(ab_person, field, multi_field.ab_multi_value, nil)
|
374
|
+
end
|
238
375
|
end
|
239
376
|
|
240
377
|
def existing_records
|
@@ -253,6 +390,5 @@ module AddressBook
|
|
253
390
|
def address_book
|
254
391
|
@address_book ||= AddressBook.address_book
|
255
392
|
end
|
256
|
-
|
257
393
|
end
|
258
394
|
end
|
data/motion/address_book.rb
CHANGED
@@ -9,6 +9,10 @@ module AddressBook
|
|
9
9
|
end
|
10
10
|
end
|
11
11
|
|
12
|
+
def count
|
13
|
+
ABAddressBookGetPersonCount(address_book)
|
14
|
+
end
|
15
|
+
|
12
16
|
def ios6_create
|
13
17
|
error = nil
|
14
18
|
@address_book = ABAddressBookCreateWithOptions(nil, error)
|
@@ -17,7 +21,7 @@ module AddressBook
|
|
17
21
|
end
|
18
22
|
|
19
23
|
def ios5_create
|
20
|
-
ABAddressBookCreate()
|
24
|
+
@address_book = ABAddressBookCreate()
|
21
25
|
end
|
22
26
|
|
23
27
|
def request_authorization(&block)
|
@@ -0,0 +1,59 @@
|
|
1
|
+
describe AddressBook::Group do
|
2
|
+
before do
|
3
|
+
@ab = AddressBook::AddrBook.new
|
4
|
+
end
|
5
|
+
|
6
|
+
describe 'an empty group' do
|
7
|
+
before do
|
8
|
+
@group = @ab.new_group(:name => 'Test Group')
|
9
|
+
end
|
10
|
+
after do
|
11
|
+
@group.delete!
|
12
|
+
end
|
13
|
+
|
14
|
+
it "should have a name" do
|
15
|
+
@group.name.should.equal 'Test Group'
|
16
|
+
end
|
17
|
+
|
18
|
+
it "should be empty" do
|
19
|
+
@group.members.should.be.empty
|
20
|
+
@group.size.should.equal 0
|
21
|
+
end
|
22
|
+
|
23
|
+
it "should not be new" do
|
24
|
+
@group.should.not.be.new
|
25
|
+
end
|
26
|
+
end
|
27
|
+
|
28
|
+
describe 'a group with members' do
|
29
|
+
before do
|
30
|
+
@p1 = @ab.new_person({:first_name => 'Alice', :emails => [{:label => 'home', :value => 'alice@example.com'}]})
|
31
|
+
@p1.save
|
32
|
+
@p2 = @ab.new_person({:first_name => 'Bob', :emails => [{:label => 'home', :value => 'bob@example.com'}]})
|
33
|
+
@p2.save
|
34
|
+
@group = @ab.new_group(:name => 'Test Group')
|
35
|
+
@group << @p1
|
36
|
+
@group << @p2
|
37
|
+
@group.save
|
38
|
+
end
|
39
|
+
after do
|
40
|
+
@group.delete!
|
41
|
+
@p1.delete!
|
42
|
+
@p2.delete!
|
43
|
+
end
|
44
|
+
|
45
|
+
it "should have 2 members" do
|
46
|
+
@group.size.should.equal 2
|
47
|
+
end
|
48
|
+
|
49
|
+
it "should have the expected members" do
|
50
|
+
@group.members.map {|person| person.first_name}.should.equal ['Alice', 'Bob']
|
51
|
+
end
|
52
|
+
|
53
|
+
it "should search by id" do
|
54
|
+
@ab.group(@group.uid).name.should.equal @group.name
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
# TODO: nested groups
|
59
|
+
end
|
@@ -0,0 +1,66 @@
|
|
1
|
+
describe AddressBook::MultiValued do
|
2
|
+
describe 'a string multi-value' do
|
3
|
+
before do
|
4
|
+
@attributes = [
|
5
|
+
{
|
6
|
+
:label => 'home page',
|
7
|
+
:value => "http://www.mysite.com/"
|
8
|
+
}, {
|
9
|
+
:label => 'work',
|
10
|
+
:value => 'http://dept.bigco.com/'
|
11
|
+
}, {
|
12
|
+
:label => 'school',
|
13
|
+
:value => 'http://state.edu/college'
|
14
|
+
}
|
15
|
+
]
|
16
|
+
@mv = AddressBook::MultiValued.new(:attributes => @attributes)
|
17
|
+
end
|
18
|
+
|
19
|
+
it 'should be countable' do
|
20
|
+
@mv.count.should.equal 3
|
21
|
+
end
|
22
|
+
|
23
|
+
it 'should be reversible' do
|
24
|
+
abmv = @mv.ab_multi_value
|
25
|
+
mv2 = AddressBook::MultiValued.new(:ab_multi_value => abmv)
|
26
|
+
mv2.attributes.should.equal @attributes
|
27
|
+
end
|
28
|
+
end
|
29
|
+
|
30
|
+
describe 'a dictionary multi-value' do
|
31
|
+
before do
|
32
|
+
@attributes = [
|
33
|
+
{
|
34
|
+
:label => 'home',
|
35
|
+
:street => '123 Boring St',
|
36
|
+
:city => 'Snoozeville',
|
37
|
+
:state => "CA"
|
38
|
+
}, {
|
39
|
+
:label => 'work',
|
40
|
+
:street => '99 Exciting Ave, Suite #200',
|
41
|
+
:city => 'Las Vegas',
|
42
|
+
:state => "NV"
|
43
|
+
}
|
44
|
+
]
|
45
|
+
@mv = AddressBook::MultiValued.new(:attributes => @attributes)
|
46
|
+
end
|
47
|
+
|
48
|
+
it 'should count the records' do
|
49
|
+
@mv.count.should.equal 2
|
50
|
+
@mv.size.should.equal 2
|
51
|
+
end
|
52
|
+
|
53
|
+
it 'should store the initial data correctly' do
|
54
|
+
@mv.attributes.should.equal @attributes
|
55
|
+
end
|
56
|
+
|
57
|
+
it 'should have correct internal representation' do
|
58
|
+
internal = @mv.ab_multi_value
|
59
|
+
ABMultiValueGetCount(internal).should.equal 2
|
60
|
+
ABMultiValueCopyLabelAtIndex(internal, 0).should.equal "home"
|
61
|
+
ABMultiValueCopyLabelAtIndex(internal, 1).should.equal "work"
|
62
|
+
ABMultiValueCopyValueAtIndex(internal, 0).keys.count.should.equal 3
|
63
|
+
ABMultiValueCopyValueAtIndex(internal, 1).keys.count.should.equal 3
|
64
|
+
end
|
65
|
+
end
|
66
|
+
end
|
@@ -1,28 +1,54 @@
|
|
1
1
|
describe AddressBook::Person do
|
2
|
+
before do
|
3
|
+
@ab = AddressBook::AddrBook.new
|
4
|
+
end
|
2
5
|
describe 'ways of creating and finding people' do
|
3
6
|
describe 'new' do
|
4
7
|
before do
|
5
|
-
@
|
8
|
+
@data = new_alex
|
9
|
+
@alex = @ab.new_person(@data)
|
6
10
|
end
|
7
11
|
it 'should create but not save in the address book' do
|
8
12
|
@alex.should.be.new_record
|
13
|
+
end
|
14
|
+
it 'should have initial values' do
|
9
15
|
@alex.first_name.should == 'Alex'
|
10
16
|
@alex.last_name.should == 'Testy'
|
11
|
-
@alex.email_values.should
|
17
|
+
@alex.email_values.should == [@data[:emails][0][:value]]
|
18
|
+
@alex.email.should == @data[:emails][0][:value]
|
19
|
+
end
|
20
|
+
it "should round-trip attributes without loss" do
|
21
|
+
@alex.attributes.should.equal @data
|
22
|
+
end
|
23
|
+
it 'should have a composite name' do
|
24
|
+
@alex.composite_name.should == 'Alex Testy'
|
12
25
|
end
|
13
26
|
end
|
14
27
|
|
15
28
|
describe 'existing' do
|
16
29
|
before do
|
17
30
|
@email = unique_email
|
18
|
-
@alex =
|
31
|
+
@alex = @ab.create_person(new_alex(@email))
|
32
|
+
end
|
33
|
+
after do
|
34
|
+
@alex.delete!
|
19
35
|
end
|
20
|
-
describe '.
|
36
|
+
describe '.find_by_uid' do
|
37
|
+
it 'should find match' do
|
38
|
+
alex = @ab.person(@alex.uid)
|
39
|
+
alex.uid.should == @alex.uid
|
40
|
+
alex.email_values.should.include? @email
|
41
|
+
alex.first_name.should == 'Alex'
|
42
|
+
alex.last_name.should == 'Testy'
|
43
|
+
alex.attributes.should.equal @alex.attributes
|
44
|
+
end
|
45
|
+
end
|
46
|
+
describe '.find_all_by_email' do
|
21
47
|
it 'should find matches' do
|
22
48
|
alexes = AddressBook::Person.find_all_by_email @email
|
23
49
|
alexes.should.not.be.empty
|
24
50
|
alexes.each do |alex|
|
25
|
-
alex.
|
51
|
+
alex.email_values.should.include? @email
|
26
52
|
alex.first_name.should == 'Alex'
|
27
53
|
alex.last_name.should == 'Testy'
|
28
54
|
end
|
@@ -35,7 +61,7 @@ describe AddressBook::Person do
|
|
35
61
|
describe '.find_by_email' do
|
36
62
|
it 'should find match' do
|
37
63
|
alex = AddressBook::Person.find_by_email @email
|
38
|
-
alex.
|
64
|
+
alex.email_values.should.include? @email
|
39
65
|
alex.first_name.should == 'Alex'
|
40
66
|
alex.last_name.should == 'Testy'
|
41
67
|
end
|
@@ -49,7 +75,7 @@ describe AddressBook::Person do
|
|
49
75
|
alexes = AddressBook::Person.where(:email => @email)
|
50
76
|
alexes.should.not.be.empty
|
51
77
|
alexes.each do |alex|
|
52
|
-
alex.
|
78
|
+
alex.email_values.should.include? @email
|
53
79
|
alex.first_name.should == 'Alex'
|
54
80
|
alex.last_name.should == 'Testy'
|
55
81
|
end
|
@@ -62,16 +88,17 @@ describe AddressBook::Person do
|
|
62
88
|
|
63
89
|
describe '.all' do
|
64
90
|
it 'should have the person we created' do
|
65
|
-
all_names =
|
91
|
+
all_names = @ab.people.map do |person|
|
66
92
|
[person.first_name, person.last_name]
|
67
93
|
end
|
68
94
|
all_names.should.include? [@alex.first_name, @alex.last_name]
|
69
95
|
end
|
70
96
|
|
71
97
|
it 'should get bigger when we create another' do
|
72
|
-
initial_people_count =
|
73
|
-
@person =
|
74
|
-
|
98
|
+
initial_people_count = @ab.people.size
|
99
|
+
@person = @ab.create_person({:first_name => 'Alex2', :last_name=>'Rothenberg2'})
|
100
|
+
@ab.people.size.should == (initial_people_count + 1)
|
101
|
+
@person.delete!
|
75
102
|
end
|
76
103
|
end
|
77
104
|
end
|
@@ -79,37 +106,64 @@ describe AddressBook::Person do
|
|
79
106
|
describe '.find_or_new_by_XXX - new or existing' do
|
80
107
|
before do
|
81
108
|
@email = unique_email
|
82
|
-
|
109
|
+
@alex = @ab.create_person(new_alex(@email))
|
110
|
+
end
|
111
|
+
after do
|
112
|
+
@alex.delete!
|
83
113
|
end
|
114
|
+
|
84
115
|
it 'should find an existing person' do
|
85
116
|
alex = AddressBook::Person.find_or_new_by_email(@email)
|
86
117
|
alex.should.not.be.new_record
|
87
|
-
alex.email.should == @email
|
88
118
|
alex.first_name.should == 'Alex'
|
89
119
|
alex.last_name.should == 'Testy'
|
120
|
+
alex.emails.attributes.map{|r| r[:value]}.should == [@email]
|
90
121
|
end
|
91
122
|
it 'should return new person when no match found' do
|
92
123
|
never_before_used_email = unique_email
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
124
|
+
new_person = AddressBook::Person.find_or_new_by_email(never_before_used_email)
|
125
|
+
new_person.should.be.new_record
|
126
|
+
new_person.email_values.should == [never_before_used_email]
|
127
|
+
new_person.first_name.should == nil
|
97
128
|
end
|
98
129
|
end
|
99
130
|
end
|
100
131
|
|
101
132
|
describe 'save' do
|
102
133
|
before do
|
103
|
-
@attributes = {
|
104
|
-
|
105
|
-
|
106
|
-
|
107
|
-
|
134
|
+
@attributes = {
|
135
|
+
:first_name=>'Alex',
|
136
|
+
:middle_name=>'Q.',
|
137
|
+
:last_name=>'Testy',
|
138
|
+
:suffix => 'III',
|
139
|
+
:nickname => 'Geekster',
|
140
|
+
:job_title => 'Developer',
|
141
|
+
:department => 'Development',
|
142
|
+
:organization => 'The Company',
|
143
|
+
:note => 'some important guy',
|
144
|
+
# :mobile_phone => '123 456 7890', :office_phone => '987 654 3210',
|
145
|
+
:phones => [
|
146
|
+
{:label => 'mobile', :value => '123 456 7899'},
|
147
|
+
{:label => 'office', :value => '987 654 3210'}
|
148
|
+
],
|
149
|
+
# :email => unique_email,
|
150
|
+
:emails => [
|
151
|
+
{:label => 'work', :value => unique_email}
|
152
|
+
],
|
153
|
+
:addresses => [
|
154
|
+
{:label => 'home', :city => 'Dogpatch', :state => 'KY'}
|
155
|
+
],
|
156
|
+
:urls => [
|
157
|
+
{ :label => 'home page', :value => "http://www.mysite.com/" },
|
158
|
+
{ :label => 'work', :value => 'http://dept.bigco.com/' },
|
159
|
+
{ :label => 'school', :value => 'http://state.edu/college' }
|
160
|
+
]
|
161
|
+
}
|
108
162
|
end
|
109
163
|
|
110
164
|
describe 'a new person' do
|
111
165
|
before do
|
112
|
-
@ab_person =
|
166
|
+
@ab_person = @ab.new_person(@attributes)
|
113
167
|
end
|
114
168
|
|
115
169
|
it 'should not be existing' do
|
@@ -120,9 +174,21 @@ describe AddressBook::Person do
|
|
120
174
|
it 'should be able to get each of the single value fields' do
|
121
175
|
@ab_person.first_name.should.equal @attributes[:first_name ]
|
122
176
|
@ab_person.last_name.should.equal @attributes[:last_name ]
|
177
|
+
@ab_person.middle_name.should.equal @attributes[:middle_name ]
|
178
|
+
@ab_person.suffix.should.equal @attributes[:suffix ]
|
179
|
+
@ab_person.nickname.should.equal @attributes[:nickname ]
|
123
180
|
@ab_person.job_title.should.equal @attributes[:job_title ]
|
124
181
|
@ab_person.department.should.equal @attributes[:department ]
|
125
182
|
@ab_person.organization.should.equal @attributes[:organization]
|
183
|
+
@ab_person.note.should.equal @attributes[:note]
|
184
|
+
@ab_person.should.be.person?
|
185
|
+
end
|
186
|
+
|
187
|
+
it 'should get a value back for singular requests against multi-value attributes' do
|
188
|
+
@ab_person.email.should.equal @attributes[:emails].first[:value]
|
189
|
+
@ab_person.phone.should.equal @attributes[:phones].first[:value]
|
190
|
+
@ab_person.url.should.equal @attributes[:urls].first[:value]
|
191
|
+
@ab_person.address.should.equal @attributes[:addresses].first
|
126
192
|
end
|
127
193
|
|
128
194
|
describe 'setting each field' do
|
@@ -147,7 +213,7 @@ describe AddressBook::Person do
|
|
147
213
|
@ab_person.organization.should.equal 'new organization'
|
148
214
|
end
|
149
215
|
|
150
|
-
it 'should be able to set the
|
216
|
+
it 'should be able to set the photo' do
|
151
217
|
image = CIImage.emptyImage
|
152
218
|
data = UIImagePNGRepresentation(UIImage.imageWithCIImage image)
|
153
219
|
@ab_person.photo = data
|
@@ -155,31 +221,90 @@ describe AddressBook::Person do
|
|
155
221
|
end
|
156
222
|
end
|
157
223
|
|
158
|
-
it 'should be able to get the phone numbers' do
|
159
|
-
@ab_person.
|
224
|
+
it 'should be able to count & get the phone numbers' do
|
225
|
+
@ab_person.phones.size.should.equal 2
|
226
|
+
@ab_person.phones.attributes.should.equal @attributes[:phones]
|
227
|
+
end
|
228
|
+
|
229
|
+
it 'should be able to count & get the emails' do
|
230
|
+
@ab_person.emails.size.should.equal 1
|
231
|
+
@ab_person.emails.attributes.should.equal @attributes[:emails]
|
160
232
|
end
|
161
233
|
|
162
|
-
it 'should be able to
|
163
|
-
@ab_person.
|
234
|
+
it 'should be able to count & inspect the addresses' do
|
235
|
+
@ab_person.addresses.count.should.equal 1
|
236
|
+
@ab_person.addresses.attributes.should.equal @attributes[:addresses]
|
164
237
|
end
|
165
|
-
|
238
|
+
|
239
|
+
it 'should be able to count & inspect the URLs' do
|
240
|
+
@ab_person.urls.count.should.equal 3
|
241
|
+
@ab_person.urls.attributes.should.equal @attributes[:urls]
|
242
|
+
end
|
243
|
+
|
244
|
+
describe 'once saved' do
|
166
245
|
before do
|
246
|
+
@before_count = AddressBook.count
|
167
247
|
@ab_person.save
|
168
248
|
end
|
169
|
-
|
249
|
+
after do
|
250
|
+
@ab_person.delete!
|
251
|
+
end
|
252
|
+
|
253
|
+
it 'should no longer be new' do
|
170
254
|
@ab_person.should.not.be.new_record
|
171
255
|
@ab_person.should.be.exists
|
172
256
|
end
|
257
|
+
|
258
|
+
it "should increment the count" do
|
259
|
+
AddressBook.count.should.equal @before_count+1
|
260
|
+
end
|
261
|
+
|
262
|
+
it 'should round-trip all attributes without loss' do
|
263
|
+
@ab_person.attributes.should.equal @attributes
|
264
|
+
end
|
265
|
+
|
266
|
+
it 'should have scalar properties' do
|
267
|
+
[:first_name, :middle_name, :last_name, :job_title, :department, :organization, :note].each do |attr|
|
268
|
+
@ab_person.send(attr).should.equal @attributes[attr]
|
269
|
+
end
|
270
|
+
end
|
271
|
+
|
272
|
+
it 'should have a composite name' do
|
273
|
+
@ab_person.composite_name.should == 'Alex Q. Testy III'
|
274
|
+
end
|
275
|
+
|
276
|
+
it 'should be able to count the emails' do
|
277
|
+
@ab_person.emails.size.should.equal 1
|
278
|
+
end
|
279
|
+
|
280
|
+
it 'should be able to count the addresses' do
|
281
|
+
@ab_person.addresses.count.should.equal 1
|
282
|
+
end
|
283
|
+
|
284
|
+
it 'should be able to retrieve the addresses' do
|
285
|
+
@ab_person.addresses.attributes.should.equal @attributes[:addresses]
|
286
|
+
end
|
287
|
+
end
|
288
|
+
|
289
|
+
describe 'once deleted' do
|
290
|
+
before do
|
291
|
+
@ab_person.save
|
292
|
+
@ab_person.delete!
|
293
|
+
end
|
294
|
+
it 'should no longer exist' do
|
295
|
+
@ab_person.should.not.be.exists
|
296
|
+
# @ab_person.should.be.new_record
|
297
|
+
end
|
173
298
|
end
|
174
299
|
end
|
175
300
|
|
176
|
-
describe '
|
301
|
+
describe 'an existing person' do
|
177
302
|
before do
|
178
|
-
|
179
|
-
@attributes[:
|
180
|
-
|
181
|
-
|
182
|
-
@ab_person
|
303
|
+
@orig_ab_person = @ab.create_person(@attributes)
|
304
|
+
@ab_person = AddressBook::Person.find_or_new_by_email(@attributes[:emails][0][:value])
|
305
|
+
end
|
306
|
+
after do
|
307
|
+
@ab_person.delete!
|
183
308
|
end
|
184
309
|
|
185
310
|
it 'should know it is not new' do
|
@@ -189,23 +314,75 @@ describe AddressBook::Person do
|
|
189
314
|
@ab_person.department.should == 'Development'
|
190
315
|
end
|
191
316
|
|
192
|
-
|
193
|
-
|
317
|
+
it 'should not change ID' do
|
318
|
+
@ab_person.uid.should.equal @orig_ab_person.uid
|
319
|
+
end
|
320
|
+
|
321
|
+
describe 'when updated' do
|
322
|
+
before do
|
323
|
+
@ab_person.first_name = 'New First Name'
|
194
324
|
@ab_person.save
|
195
|
-
@new_ab_person = AddressBook::Person.find_by_email @ab_person.email
|
196
|
-
@new_ab_person.first_name = 'New First Name'
|
197
|
-
@new_ab_person.save
|
198
|
-
AddressBook::Person.find_by_email(@ab_person.email).first_name.should == 'New First Name'
|
199
325
|
end
|
326
|
+
|
327
|
+
it 'should be able to get each of the single value fields' do
|
328
|
+
@match = AddressBook::Person.find_by_email(@ab_person.email_values.first)
|
329
|
+
@match.first_name.should == 'New First Name'
|
330
|
+
@match.uid.should.equal @ab_person.uid
|
331
|
+
end
|
332
|
+
end
|
333
|
+
end
|
334
|
+
|
335
|
+
describe "input with bad attributes" do
|
336
|
+
before do
|
337
|
+
@attributes[:junk] = 'this should be ignored'
|
338
|
+
@attributes[:last_name] = nil
|
339
|
+
@attributes[:urls] = [
|
340
|
+
{ :value => "http://www.mysite.com/" },
|
341
|
+
{ :label => 'work' },
|
342
|
+
{ :label => 'work', :url => 'http://state.edu/college' }
|
343
|
+
]
|
344
|
+
@ab_person = @ab.create_person(@attributes)
|
345
|
+
end
|
346
|
+
after do
|
347
|
+
@ab_person.delete!
|
348
|
+
end
|
349
|
+
|
350
|
+
# entries with missing label should be OK
|
351
|
+
# entries with missing value should be ignored
|
352
|
+
# entries with illegal fields should raise an exception
|
353
|
+
it "should save without errors" do
|
354
|
+
@ab_person.should.be.exists
|
355
|
+
end
|
356
|
+
|
357
|
+
it "should have the expected values" do
|
358
|
+
@ab_person.urls.count.should.equal 1
|
359
|
+
urldata = [{:value => "http://www.mysite.com/", :label => ""}]
|
360
|
+
@ab_person.urls.attributes.should.equal urldata
|
361
|
+
@ab_person.attributes.keys.should.not.include?(:junk)
|
362
|
+
@ab_person.last_name.should.equal nil
|
200
363
|
end
|
364
|
+
end
|
365
|
+
end
|
201
366
|
|
367
|
+
describe "organization record" do
|
368
|
+
before do
|
369
|
+
@person = @ab.new_person(
|
370
|
+
:first_name => 'John',
|
371
|
+
:last_name => 'Whorfin',
|
372
|
+
:organization => 'Acme Inc.',
|
373
|
+
:is_org => true,
|
374
|
+
:note => 'big important company'
|
375
|
+
)
|
202
376
|
end
|
203
377
|
|
378
|
+
it "should know that it is an organization" do
|
379
|
+
@person.should.be.organization?
|
380
|
+
end
|
204
381
|
end
|
205
382
|
|
206
383
|
describe 'method missing magic' do
|
207
384
|
before do
|
208
|
-
@person =
|
385
|
+
@person = @ab.new_person({})
|
209
386
|
end
|
210
387
|
describe 'getters' do
|
211
388
|
it 'should have a getter for each attribute' do
|
@@ -236,6 +413,9 @@ describe AddressBook::Person do
|
|
236
413
|
@person.setter?('find_all_by_email').should.be falsey
|
237
414
|
@person.setter?('find_by_email' ).should.be falsey
|
238
415
|
end
|
416
|
+
it 'should not have a setter for uid' do
|
417
|
+
@person.setter?('uid=').should.be falsey
|
418
|
+
end
|
239
419
|
end
|
240
420
|
describe 'all_finders' do
|
241
421
|
it 'should have a finder for each attribute' do
|
@@ -2,3 +2,11 @@ def unique_email(email='alex_testy@example.com')
|
|
2
2
|
name, domain = email.split('@')
|
3
3
|
"#{name}_#{Time.now.to_i}_#{rand(1000)}@#{domain}"
|
4
4
|
end
|
5
|
+
|
6
|
+
def new_alex(emailaddr = unique_email)
|
7
|
+
{
|
8
|
+
:first_name => 'Alex',
|
9
|
+
:last_name => 'Testy',
|
10
|
+
:emails => [{:label => 'home', :value => emailaddr}]
|
11
|
+
}
|
12
|
+
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: motion-addressbook
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.2.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2013-
|
12
|
+
date: 2013-04-04 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: bubble-wrap
|
@@ -67,6 +67,7 @@ extensions: []
|
|
67
67
|
extra_rdoc_files: []
|
68
68
|
files:
|
69
69
|
- .gitignore
|
70
|
+
- .travis.yml
|
70
71
|
- Gemfile
|
71
72
|
- LICENSE
|
72
73
|
- README.md
|
@@ -75,10 +76,15 @@ files:
|
|
75
76
|
- lib/motion-addressbook/version.rb
|
76
77
|
- motion-addressbook.gemspec
|
77
78
|
- motion/address_book.rb
|
79
|
+
- motion/address_book/addr_book.rb
|
80
|
+
- motion/address_book/group.rb
|
78
81
|
- motion/address_book/multi_value.rb
|
82
|
+
- motion/address_book/multi_valued.rb
|
79
83
|
- motion/address_book/person.rb
|
80
84
|
- motion/address_book/picker.rb
|
85
|
+
- spec/address_book/group_spec.rb
|
81
86
|
- spec/address_book/multi_value_spec.rb
|
87
|
+
- spec/address_book/multi_valued_spec.rb
|
82
88
|
- spec/address_book/person_spec.rb
|
83
89
|
- spec/address_book/picker_spec.rb
|
84
90
|
- spec/helpers/bacon_matchers.rb
|
@@ -98,7 +104,7 @@ required_ruby_version: !ruby/object:Gem::Requirement
|
|
98
104
|
version: '0'
|
99
105
|
segments:
|
100
106
|
- 0
|
101
|
-
hash:
|
107
|
+
hash: 3256350264444301144
|
102
108
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
103
109
|
none: false
|
104
110
|
requirements:
|
@@ -107,7 +113,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
107
113
|
version: '0'
|
108
114
|
segments:
|
109
115
|
- 0
|
110
|
-
hash:
|
116
|
+
hash: 3256350264444301144
|
111
117
|
requirements: []
|
112
118
|
rubyforge_project:
|
113
119
|
rubygems_version: 1.8.24
|
@@ -115,7 +121,9 @@ signing_key:
|
|
115
121
|
specification_version: 3
|
116
122
|
summary: A RubyMotion wrapper around the iOS Address Book framework
|
117
123
|
test_files:
|
124
|
+
- spec/address_book/group_spec.rb
|
118
125
|
- spec/address_book/multi_value_spec.rb
|
126
|
+
- spec/address_book/multi_valued_spec.rb
|
119
127
|
- spec/address_book/person_spec.rb
|
120
128
|
- spec/address_book/picker_spec.rb
|
121
129
|
- spec/helpers/bacon_matchers.rb
|