nelumba 0.0.13

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.
Files changed (95) hide show
  1. data/.gitignore +6 -0
  2. data/.travis.yml +9 -0
  3. data/Gemfile +20 -0
  4. data/README.md +242 -0
  5. data/Rakefile +7 -0
  6. data/assets/lotus_logo_purple.png +0 -0
  7. data/assets/lotus_logo_purple.svg +262 -0
  8. data/lib/nelumba.rb +47 -0
  9. data/lib/nelumba/activity.rb +250 -0
  10. data/lib/nelumba/application.rb +11 -0
  11. data/lib/nelumba/article.rb +11 -0
  12. data/lib/nelumba/atom/account.rb +50 -0
  13. data/lib/nelumba/atom/address.rb +56 -0
  14. data/lib/nelumba/atom/author.rb +176 -0
  15. data/lib/nelumba/atom/category.rb +41 -0
  16. data/lib/nelumba/atom/comment.rb +96 -0
  17. data/lib/nelumba/atom/entry.rb +216 -0
  18. data/lib/nelumba/atom/feed.rb +198 -0
  19. data/lib/nelumba/atom/generator.rb +40 -0
  20. data/lib/nelumba/atom/link.rb +79 -0
  21. data/lib/nelumba/atom/name.rb +57 -0
  22. data/lib/nelumba/atom/organization.rb +62 -0
  23. data/lib/nelumba/atom/person.rb +179 -0
  24. data/lib/nelumba/atom/portable_contacts.rb +117 -0
  25. data/lib/nelumba/atom/source.rb +179 -0
  26. data/lib/nelumba/atom/thread.rb +60 -0
  27. data/lib/nelumba/audio.rb +39 -0
  28. data/lib/nelumba/badge.rb +11 -0
  29. data/lib/nelumba/binary.rb +52 -0
  30. data/lib/nelumba/bookmark.rb +30 -0
  31. data/lib/nelumba/category.rb +49 -0
  32. data/lib/nelumba/collection.rb +34 -0
  33. data/lib/nelumba/comment.rb +47 -0
  34. data/lib/nelumba/crypto.rb +144 -0
  35. data/lib/nelumba/device.rb +11 -0
  36. data/lib/nelumba/discover.rb +362 -0
  37. data/lib/nelumba/event.rb +57 -0
  38. data/lib/nelumba/feed.rb +173 -0
  39. data/lib/nelumba/file.rb +43 -0
  40. data/lib/nelumba/generator.rb +53 -0
  41. data/lib/nelumba/group.rb +11 -0
  42. data/lib/nelumba/identity.rb +63 -0
  43. data/lib/nelumba/image.rb +30 -0
  44. data/lib/nelumba/link.rb +56 -0
  45. data/lib/nelumba/note.rb +34 -0
  46. data/lib/nelumba/notification.rb +229 -0
  47. data/lib/nelumba/object.rb +251 -0
  48. data/lib/nelumba/person.rb +306 -0
  49. data/lib/nelumba/place.rb +34 -0
  50. data/lib/nelumba/product.rb +30 -0
  51. data/lib/nelumba/publisher.rb +44 -0
  52. data/lib/nelumba/question.rb +30 -0
  53. data/lib/nelumba/review.rb +30 -0
  54. data/lib/nelumba/service.rb +11 -0
  55. data/lib/nelumba/subscription.rb +117 -0
  56. data/lib/nelumba/version.rb +3 -0
  57. data/lib/nelumba/video.rb +43 -0
  58. data/nelumba.gemspec +28 -0
  59. data/spec/activity_spec.rb +116 -0
  60. data/spec/application_spec.rb +136 -0
  61. data/spec/article_spec.rb +136 -0
  62. data/spec/atom/comment_spec.rb +455 -0
  63. data/spec/atom/feed_spec.rb +684 -0
  64. data/spec/audio_spec.rb +164 -0
  65. data/spec/badge_spec.rb +136 -0
  66. data/spec/binary_spec.rb +218 -0
  67. data/spec/bookmark.rb +150 -0
  68. data/spec/collection_spec.rb +152 -0
  69. data/spec/comment_spec.rb +128 -0
  70. data/spec/crypto_spec.rb +126 -0
  71. data/spec/device_spec.rb +136 -0
  72. data/spec/event_spec.rb +239 -0
  73. data/spec/feed_spec.rb +252 -0
  74. data/spec/file_spec.rb +190 -0
  75. data/spec/group_spec.rb +136 -0
  76. data/spec/helper.rb +10 -0
  77. data/spec/identity_spec.rb +67 -0
  78. data/spec/image_spec.rb +150 -0
  79. data/spec/link_spec.rb +30 -0
  80. data/spec/note_spec.rb +163 -0
  81. data/spec/notification_spec.rb +89 -0
  82. data/spec/person_spec.rb +244 -0
  83. data/spec/place_spec.rb +162 -0
  84. data/spec/product_spec.rb +150 -0
  85. data/spec/question_spec.rb +156 -0
  86. data/spec/review_spec.rb +149 -0
  87. data/spec/service_spec.rb +136 -0
  88. data/spec/video_spec.rb +164 -0
  89. data/test/example_feed.atom +393 -0
  90. data/test/example_feed_empty_author.atom +336 -0
  91. data/test/example_feed_false_connected.atom +359 -0
  92. data/test/example_feed_link_without_href.atom +134 -0
  93. data/test/example_page.html +4 -0
  94. data/test/mime_type_bug_feed.atom +874 -0
  95. metadata +288 -0
@@ -0,0 +1,47 @@
1
+ # Base Activity Objects
2
+ require 'nelumba/object'
3
+ require 'nelumba/activity'
4
+ require 'nelumba/collection'
5
+
6
+ # Activity Objects
7
+ require 'nelumba/article'
8
+ require 'nelumba/audio'
9
+ require 'nelumba/badge'
10
+ require 'nelumba/binary'
11
+ require 'nelumba/bookmark'
12
+ require 'nelumba/comment'
13
+ require 'nelumba/device'
14
+ require 'nelumba/event'
15
+ require 'nelumba/file'
16
+ require 'nelumba/group'
17
+ require 'nelumba/image'
18
+ require 'nelumba/note'
19
+ require 'nelumba/place'
20
+ require 'nelumba/question'
21
+ require 'nelumba/review'
22
+ require 'nelumba/service'
23
+ require 'nelumba/video'
24
+
25
+ # Data Structures
26
+ require 'nelumba/feed'
27
+ require 'nelumba/person'
28
+ require 'nelumba/identity'
29
+ require 'nelumba/notification'
30
+ require 'nelumba/link'
31
+
32
+ # Crypto
33
+ require 'nelumba/crypto'
34
+
35
+ # Pub-Sub
36
+ require 'nelumba/subscription'
37
+ require 'nelumba/publisher'
38
+
39
+ # Discovery
40
+ require 'nelumba/discover'
41
+
42
+ # This module contains elements that allow federated interaction. It also
43
+ # contains methods to construct these objects from external sources.
44
+ module Nelumba
45
+ # This module isolates Atom generation.
46
+ module Atom; end
47
+ end
@@ -0,0 +1,250 @@
1
+ module Nelumba
2
+ # This class represents an Activity object that represents an action taken
3
+ # by a Person.
4
+ class Activity
5
+ require 'time-lord/units'
6
+ require 'time-lord/scale'
7
+ require 'time-lord/period'
8
+
9
+ include Nelumba::Object
10
+
11
+ STANDARD_TYPES = [:article, :audio, :bookmark, :comment, :file, :folder,
12
+ :group, :list, :note, :person, :image,
13
+ :place, :playlist, :product, :review, :service, :status,
14
+ :video]
15
+
16
+ # Holds a hash containing the information about interactions where keys
17
+ # are verbs.
18
+ #
19
+ # For instance, it could have a :share key, with a hash containing the
20
+ # number of times it has been shared.
21
+ attr_reader :interactions
22
+
23
+ # The object of this activity.
24
+ attr_reader :object
25
+
26
+ # The type of object for this activity.
27
+ #
28
+ # The field can be a String for uncommon types. Several are standard:
29
+ # :article, :audio, :bookmark, :comment, :file, :folder, :group,
30
+ # :list, :note, :person, :image, :place, :playlist,
31
+ # :product, :review, :service, :video
32
+ attr_reader :type
33
+
34
+ # The action being invoked in this activity.
35
+ #
36
+ # The field can be a String for uncommon verbs. Several are standard:
37
+ # :favorite, :follow, :like, :"make-friend", :join, :play,
38
+ # :post, :save, :share, :tag, :update
39
+ attr_reader :verb
40
+
41
+ # The target of the action.
42
+ attr_reader :target
43
+
44
+ # Holds an Nelumba::Person.
45
+ attr_reader :actor
46
+
47
+ # Holds the source of this entry as an Nelumba::Feed.
48
+ attr_reader :source
49
+
50
+ # Holds an array of related Nelumba::Activity's that this entry is a response
51
+ # to.
52
+ attr_reader :in_reply_to
53
+
54
+ # Holds an array of related Nelumba::Activity's that are replies to this one.
55
+ attr_reader :replies
56
+
57
+ # Holds an array of Nelumba::Person's that have favorited this activity.
58
+ attr_reader :likes
59
+
60
+ # Holds an array of Nelumba::Person's that have shared this activity.
61
+ attr_reader :shares
62
+
63
+ # Holds an array of Nelumba::Person's that are mentioned in this activity.
64
+ attr_reader :mentions
65
+
66
+ # Create a new entry with the given action and object.
67
+ #
68
+ # options:
69
+ # :object => The object of this activity.
70
+ # :type => The type of object for this activity.
71
+ # :target => The target of this activity.
72
+ # :verb => The action of the activity.
73
+ #
74
+ # :actor => An Nelumba::Person responsible for generating this entry.
75
+ # :source => An Nelumba::Feed where this Entry originated. This
76
+ # should be used when an Entry is copied into this feed
77
+ # from another.
78
+ # :published => The DateTime depicting when the entry was originally
79
+ # published.
80
+ # :updated => The DateTime depicting when the entry was modified.
81
+ # :url => The canonical url of the entry.
82
+ # :uid => The unique id that identifies this entry.
83
+ # :in_reply_to => An Nelumba::Entry for which this entry is a response.
84
+ # Or an array of Nelumba::Entry's that this entry is a
85
+ # response to. Use this when this Entry is a reply
86
+ # to an existing Entry.
87
+ def initialize(options = {}, &blk)
88
+ super(options, &blk)
89
+
90
+ @object = options[:object]
91
+
92
+ @type = options[:type]
93
+ if STANDARD_TYPES.map(&:to_s).include? @type
94
+ @type = @type.intern
95
+ end
96
+
97
+ @target = options[:target]
98
+ @verb = options[:verb]
99
+
100
+ @actor = options[:actor]
101
+ @source = options[:source]
102
+ @published = options[:published]
103
+ @updated = options[:updated]
104
+ @url = options[:url]
105
+ @uid = options[:uid]
106
+
107
+ unless options[:in_reply_to].nil? or options[:in_reply_to].is_a?(Array)
108
+ options[:in_reply_to] = [options[:in_reply_to]]
109
+ end
110
+
111
+ @in_reply_to = options[:in_reply_to] || []
112
+ @replies = options[:replies] || []
113
+
114
+ @mentions = options[:mentions] || []
115
+ @likes = options[:likes] || []
116
+ @shares = options[:shares] || []
117
+
118
+ @interactions = options[:interactions] || {}
119
+ end
120
+
121
+ # Returns the number of times the given verb has been used with this
122
+ # Activity.
123
+ def interaction_count(verb)
124
+ hash = self.interactions
125
+ if hash && hash.has_key?(verb)
126
+ hash[verb][:count] || 0
127
+ else
128
+ 0
129
+ end
130
+ end
131
+
132
+ def published_ago_in_words
133
+ TimeLord::Period.new(self.published.to_time, Time.now).to_words
134
+ end
135
+
136
+ def updated_ago_in_words
137
+ TimeLord::Period.new(self.updated.to_time, Time.now).to_words
138
+ end
139
+
140
+ # Returns a hash of all relevant fields.
141
+ def to_hash(scheme = 'https', domain = 'example.org', port = nil)
142
+ {
143
+ :source => self.source,
144
+
145
+ :in_reply_to => self.in_reply_to.dup,
146
+ :replies => self.replies.dup,
147
+
148
+ :mentions => self.mentions.dup,
149
+ :likes => self.likes.dup,
150
+ :shares => self.shares.dup,
151
+
152
+ :object => self.object,
153
+ :target => self.target,
154
+ :actor => self.actor,
155
+ :verb => self.verb,
156
+ :type => self.type,
157
+ }.merge(super(scheme, domain, port))
158
+ end
159
+
160
+ # Returns a string containing the Atom representation of this Activity.
161
+ def to_atom
162
+ require 'nelumba/atom/entry'
163
+
164
+ Nelumba::Atom::Entry.from_canonical(self).to_xml
165
+ end
166
+
167
+ # Returns a hash of all relevant fields with JSON activity streams
168
+ # conventions.
169
+ def to_json_hash(scheme = 'https', domain = 'example.org', port = nil)
170
+ {
171
+ :objectType => "activity",
172
+ :object => @object,
173
+ :actor => @actor,
174
+ :target => @target,
175
+ :type => @type,
176
+ :verb => @verb,
177
+ :source => self.source,
178
+ :in_reply_to => self.in_reply_to.dup,
179
+ :replies => self.replies.dup,
180
+ :mentions => self.mentions.dup,
181
+ :likes => self.likes.dup,
182
+ :shares => self.shares.dup,
183
+ }.merge(super(scheme, domain, port))
184
+ end
185
+
186
+ # Generates a sentence describing this activity in the current or given
187
+ # locale.
188
+ #
189
+ # Usage:
190
+ # # The default locale
191
+ # Nelumba::Activity.new(:verb => :post,
192
+ # :object => Nelumba::Note(:content => "hello"),
193
+ # :actor => Nelumba::Person.new(:name => "wilkie"))
194
+ # .sentence
195
+ # # => "wilkie posted a note"
196
+ #
197
+ # Nelumba::Activity.new(:verb => :follow,
198
+ # :object => Nelumba::Person.new(:name => "carol"),
199
+ # :actor => Nelumba::Person.new(:name => "wilkie"))
200
+ # .sentence
201
+ # # => "wilkie followed carol"
202
+ #
203
+ # # In Spanish
204
+ # Nelumba::Activity.new(:verb => :post,
205
+ # :object => Nelumba::Note(:content => "hello"),
206
+ # :actor => Nelumba::Person.new(:name => "wilkie"))
207
+ # .sentence(:locale => :es)
208
+ # # => "wilkie puso una nota"
209
+ def sentence(options = {})
210
+ object_owner = nil
211
+
212
+ if self.verb == :favorite || self.verb == :share
213
+ if self.object.author
214
+ object_owner = self.object.author.name
215
+ elsif self.object.actor.is_a? Nelumba::Person
216
+ object_owner = self.object.actor.name
217
+ end
218
+ end
219
+
220
+ object = self.type
221
+
222
+ if self.verb == :favorite || self.verb == :share
223
+ if self.object
224
+ object = self.object.type
225
+ end
226
+ end
227
+
228
+ actor = nil
229
+
230
+ if self.actor
231
+ actor = self.actor.preferred_display_name
232
+ end
233
+
234
+ person = nil
235
+
236
+ if self.object.is_a?(Nelumba::Person)
237
+ person = self.object.name
238
+ end
239
+
240
+ Nelumba::I18n.sentence({
241
+ :actor => actor,
242
+ :object => object,
243
+ :object_owner => object_owner,
244
+ :person => person,
245
+ :verb => self.verb,
246
+ :target => self.target ? self.target.preferred_display_name : nil
247
+ }.merge(options))
248
+ end
249
+ end
250
+ end
@@ -0,0 +1,11 @@
1
+ module Nelumba
2
+ class Application
3
+ include Nelumba::Object
4
+
5
+ def to_json_hash
6
+ {
7
+ :objectType => "application"
8
+ }.merge(super)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,11 @@
1
+ module Nelumba
2
+ class Article
3
+ include Nelumba::Object
4
+
5
+ def to_json_hash
6
+ {
7
+ :objectType => "article"
8
+ }.merge(super)
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,50 @@
1
+ module Nelumba
2
+ require 'atom'
3
+
4
+ module Atom
5
+ # This class represents an PortableContacts Account object.
6
+ class Account
7
+ include ::Atom::Xml::Parseable
8
+
9
+ # The XML namespace the specifies this content.
10
+ POCO_NAMESPACE = 'http://portablecontacts.net/spec/1.0'
11
+
12
+ namespace POCO_NAMESPACE
13
+
14
+ element :domain
15
+ element :username
16
+ element :userid
17
+
18
+ def initialize(o = {})
19
+ case o
20
+ when XML::Reader
21
+ o.read
22
+ parse(o)
23
+ when Hash
24
+ o.each do |k, v|
25
+ if k.to_s.include? '_'
26
+ k = k.to_s.gsub(/_(.)/){"#{$1.upcase}"}.intern
27
+ end
28
+ self.send("#{k.to_s}=", v)
29
+ end
30
+ else
31
+ raise ArgumentError, "Got #{o.class} but expected a Hash or XML::Reader"
32
+ end
33
+
34
+ yield(self) if block_given?
35
+ end
36
+
37
+ def to_hash
38
+ {
39
+ :domain => self.domain,
40
+ :username => self.username,
41
+ :userid => self.userid
42
+ }
43
+ end
44
+
45
+ def to_canonical
46
+ to_hash
47
+ end
48
+ end
49
+ end
50
+ end
@@ -0,0 +1,56 @@
1
+ module Nelumba
2
+ require 'atom'
3
+
4
+ module Atom
5
+ # This class represents an OStatus PortableContacts Address object.
6
+ class Address
7
+ include ::Atom::Xml::Parseable
8
+
9
+ # The XML namespace the specifies this content.
10
+ POCO_NAMESPACE = 'http://portablecontacts.net/spec/1.0'
11
+
12
+ namespace POCO_NAMESPACE
13
+
14
+ element :formatted
15
+ element :streetAddress
16
+ element :locality
17
+ element :region
18
+ element :postalCode
19
+ element :country
20
+
21
+ def initialize(o = {})
22
+ case o
23
+ when XML::Reader
24
+ o.read
25
+ parse(o, :test=>true)
26
+ when Hash
27
+ o.each do |k, v|
28
+ if k.to_s.include? '_'
29
+ k = k.to_s.gsub(/_(.)/){"#{$1.upcase}"}.intern
30
+ end
31
+ self.send("#{k.to_s}=", v)
32
+ end
33
+ else
34
+ raise ArgumentError, "Got #{o.class} but expected a Hash or XML::Reader"
35
+ end
36
+
37
+ yield(self) if block_given?
38
+ end
39
+
40
+ def to_hash
41
+ {
42
+ :formatted => self.formatted,
43
+ :street_address => self.streetAddress,
44
+ :locality => self.locality,
45
+ :region => self.region,
46
+ :postal_code => self.postalCode,
47
+ :country => self.country
48
+ }
49
+ end
50
+
51
+ def to_canonical
52
+ to_hash
53
+ end
54
+ end
55
+ end
56
+ end
@@ -0,0 +1,176 @@
1
+ module Nelumba
2
+ require 'atom'
3
+
4
+ module Atom
5
+ # Holds information about the author of the Feed.
6
+ class Author < ::Atom::Person
7
+ require 'date'
8
+
9
+ include ::Atom::SimpleExtensions
10
+
11
+ # The XML namespace the specifies this content.
12
+ POCO_NAMESPACE = 'http://portablecontacts.net/spec/1.0'
13
+
14
+ # The XML namespace that identifies the conforming specification.
15
+ ACTIVITY_NAMESPACE = 'http://activitystrea.ms/spec/1.0/'
16
+
17
+ add_extension_namespace :activity, ACTIVITY_NAMESPACE
18
+ element 'activity:object-type'
19
+
20
+ namespace ::Atom::NAMESPACE
21
+ element :email
22
+ element :uri
23
+
24
+ elements :links, :class => ::Atom::Link
25
+
26
+ add_extension_namespace :poco, POCO_NAMESPACE
27
+ element 'poco:id'
28
+ element 'poco:organization', :class => Nelumba::Atom::Organization
29
+ element 'poco:address', :class => Nelumba::Atom::Address
30
+ element 'poco:account', :class => Nelumba::Atom::Account
31
+ element 'poco:displayName'
32
+ element 'poco:nickname'
33
+ element 'poco:updated', :class => DateTime, :content_only => true
34
+ element 'poco:published', :class => DateTime, :content_only => true
35
+ element 'poco:birthday', :class => Date, :content_only => true
36
+ element 'poco:anniversary', :class => Date, :content_only => true
37
+ element 'poco:gender'
38
+ element 'poco:note'
39
+ element 'poco:preferredUsername'
40
+
41
+ element 'pronoun'
42
+
43
+ # unfortunately ratom doesn't handle elements with the same local name well.
44
+ # this is a workaround for that.
45
+ attr_writer :name, :poco_name
46
+
47
+ def name
48
+ @name or self[::Atom::NAMESPACE, 'name'].first
49
+ end
50
+
51
+ def poco_name
52
+ return @poco_name if @poco_name
53
+ name = self[POCO_NAMESPACE, 'name'].first
54
+ if name
55
+ name = "<name>#{name}</name>"
56
+ reader = XML::Reader.string(name)
57
+ reader.read
58
+ reader.read
59
+ Nelumba::Atom::Name.new(reader)
60
+ else
61
+ nil
62
+ end
63
+ end
64
+
65
+ def to_xml(*args)
66
+ x = super(true)
67
+
68
+ if self.name
69
+ node = XML::Node.new('name')
70
+ node << self.name
71
+ x << node
72
+ end
73
+
74
+ if self.poco_name
75
+ x << self.poco_name.to_xml(true, root_name = 'poco:name')
76
+ end
77
+
78
+ x
79
+ end
80
+
81
+ def initialize *args
82
+ self.activity_object_type = "http://activitystrea.ms/schema/1.0/person"
83
+ super(*args)
84
+ end
85
+
86
+ # Gives an instance of an Nelumba::Activity that parses the fields
87
+ # having an activity prefix.
88
+ def activity
89
+ Nelumba::Activity.new(self)
90
+ end
91
+
92
+ def self.from_canonical(obj)
93
+ hash = obj.to_hash
94
+ hash.keys.each do |k|
95
+ to_k = k
96
+ if k == :display_name
97
+ to_k = :displayName
98
+ elsif k == :preferred_username
99
+ to_k = :preferredUsername
100
+ end
101
+
102
+ if k == :extended_name
103
+ if hash[:extended_name]
104
+ hash[:"poco_name"] = Nelumba::Atom::Name.new(hash[:extended_name])
105
+ end
106
+ hash.delete :extended_name
107
+ elsif k == :organization
108
+ if hash[:organization]
109
+ hash[:"poco_organization"] = Nelumba::Atom::Organization.new(hash[:organization])
110
+ end
111
+ hash.delete :organization
112
+ elsif k == :address
113
+ if hash[:address]
114
+ hash[:"poco_address"] = Nelumba::Atom::Address.new(hash[:address])
115
+ end
116
+ hash.delete :address
117
+ elsif k == :account
118
+ if hash[:account]
119
+ hash[:"poco_account"] = Nelumba::Atom::Account.new(hash[:account])
120
+ end
121
+ hash.delete :account
122
+ elsif k == :uid
123
+ if hash[:uid]
124
+ hash[:"poco_id"] = hash[:uid]
125
+ end
126
+ hash.delete :uid
127
+ elsif k == :pronoun
128
+ elsif (k != :uri) && (k != :name) && (k != :email)
129
+ hash[:"poco_#{to_k}"] = hash[k]
130
+ hash.delete k
131
+ end
132
+ end
133
+
134
+ # Remove any blank entries
135
+ hash.keys.each do |key|
136
+ if hash[key].nil? || hash[key] == ""
137
+ hash.delete key
138
+ end
139
+ end
140
+
141
+ self.new(hash)
142
+ end
143
+
144
+ def to_canonical
145
+ organization = self.poco_organization
146
+ organization = organization.to_canonical if organization
147
+
148
+ address = self.poco_address
149
+ address = address.to_canonical if address
150
+
151
+ account = self.poco_account
152
+ account = account.to_canonical if account
153
+
154
+ ext_name = self.poco_name
155
+ ext_name = ext_name.to_canonical if ext_name
156
+ Nelumba::Person.new(:uid => self.poco_id,
157
+ :extended_name => ext_name,
158
+ :organization => organization,
159
+ :address => address,
160
+ :account => account,
161
+ :gender => self.poco_gender,
162
+ :note => self.poco_note,
163
+ :nickname => self.poco_nickname,
164
+ :display_name => self.poco_displayName,
165
+ :preferred_username => self.poco_preferredUsername,
166
+ :updated => self.poco_updated,
167
+ :published => self.poco_published,
168
+ :birthday => self.poco_birthday,
169
+ :anniversary => self.poco_anniversary,
170
+ :uri => self.uri,
171
+ :email => self.email,
172
+ :name => self.name)
173
+ end
174
+ end
175
+ end
176
+ end