geni 0.0.5 → 0.0.6

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 (53) hide show
  1. data/.gitignore +2 -1
  2. data/README.md +8 -3
  3. data/Rakefile +9 -0
  4. data/geni.gemspec +7 -15
  5. data/lib/geni.rb +8 -2
  6. data/lib/geni/base.rb +30 -3
  7. data/lib/geni/client.rb +41 -19
  8. data/lib/geni/document.rb +9 -0
  9. data/lib/geni/photo.rb +10 -0
  10. data/lib/geni/profile.rb +68 -37
  11. data/lib/geni/profile/immediate_family.rb +51 -0
  12. data/lib/geni/project.rb +19 -0
  13. data/lib/geni/taggable.rb +27 -0
  14. data/lib/geni/union.rb +15 -0
  15. data/lib/geni/video.rb +9 -0
  16. data/spec/geni/client_spec.rb +79 -0
  17. data/spec/geni/document_spec.rb +53 -0
  18. data/spec/geni/immediate_family_spec.rb +45 -0
  19. data/spec/geni/photo_spec.rb +67 -0
  20. data/spec/geni/profile_spec.rb +73 -0
  21. data/spec/geni/project_spec.rb +44 -0
  22. data/spec/geni/union_spec.rb +44 -0
  23. data/spec/geni/video_spec.rb +56 -0
  24. data/spec/spec_helper.rb +91 -0
  25. data/spec/support/mocked_responses/06668c1bc97e251b3c2965712e3b990e.json +1 -0
  26. data/spec/support/mocked_responses/09df004f19d20d8d685db52796b552bf.json +1 -0
  27. data/spec/support/mocked_responses/12536c37e1bcef230f105a0fa930eae9.json +1 -0
  28. data/spec/support/mocked_responses/155ed9f9c6912c19cd4d6be2ad4b9163.json +1 -0
  29. data/spec/support/mocked_responses/1b640e767a27039b60daab80aa3e38da.json +1 -0
  30. data/spec/support/mocked_responses/44795c1cebac8aee4c72ab4cde5b7c34.json +1 -0
  31. data/spec/support/mocked_responses/4e55df6914e067b371e7ea54ac372591.json +1 -0
  32. data/spec/support/mocked_responses/55c9a8f9e64187f2e7389b7cecec4bd0.json +1 -0
  33. data/spec/support/mocked_responses/5643d7ffaa0b17a4340b57446228f455.json +1 -0
  34. data/spec/support/mocked_responses/6df2af74f5544a90b96921edc9aa346d.json +1 -0
  35. data/spec/support/mocked_responses/7215a02ec26d1c9df055275958824c7b.json +1 -0
  36. data/spec/support/mocked_responses/7c4840e03bece51bb7154893682ec2a6.json +1 -0
  37. data/spec/support/mocked_responses/9ae308e89eb74fc5aea5164c8affa422.json +1 -0
  38. data/spec/support/mocked_responses/9e1dcf9ed89704ecac0e1734f9ac9e6e.json +1 -0
  39. data/spec/support/mocked_responses/a060207b22ab180a065704b8dd031511.json +1 -0
  40. data/spec/support/mocked_responses/a4a8ee1c8c387c8cad34c7c62f2d1d27.json +1 -0
  41. data/spec/support/mocked_responses/a5a1df59373b2159fbd3b906b9494f6f.json +1 -0
  42. data/spec/support/mocked_responses/b28e773e9568bf5e2ac10e425241bf51.json +1 -0
  43. data/spec/support/mocked_responses/b4856ae6ff428888301f716b52ea161b.json +1 -0
  44. data/spec/support/mocked_responses/b73322abb23cf869241bda85b20080f5.json +1 -0
  45. data/spec/support/mocked_responses/c21daf2c09c09b947b5b8de0a69278d9.json +1 -0
  46. data/spec/support/mocked_responses/c234b7016ed809af64cfaf699a509512.json +1 -0
  47. data/spec/support/mocked_responses/d2e9479730282f7493eaf6513497d454.json +1 -0
  48. data/spec/support/mocked_responses/d5b2f2087b8831ce4df5e7e9f5a1085a.json +1 -0
  49. data/spec/support/mocked_responses/dee607809468ee9a94e56eeae28ecc34.json +1 -0
  50. data/spec/support/mocked_responses/deea226a6d94d6165febb07a56ba4261.json +1 -0
  51. data/spec/support/mocked_responses/f4f38a4038abc4227a1b4b18fd12b978.json +1 -0
  52. metadata +83 -8
  53. data/lib/geni/family.rb +0 -39
data/.gitignore CHANGED
@@ -4,4 +4,5 @@ Thumbs.db
4
4
  *.gem
5
5
  .rvmrc
6
6
  ~*
7
- test.rb
7
+ test.rb
8
+ notes.txt
data/README.md CHANGED
@@ -33,12 +33,17 @@ Simple Ruby client to the [Geni](http://www.geni.com) REST/OAuth API.
33
33
  puts profile.name
34
34
  end
35
35
 
36
+ Support is available for profiles, documents, photos, projects, unions, videos.
37
+
36
38
  I've also put [a demo Rails app](https://github.com/aurels/geni-rails-example) online to show the usage of the gem with Rails or Sinatra.
37
39
 
38
- # Not done yet
40
+ # Tests
41
+
42
+ To run the specs :
43
+
44
+ $ rake spec
39
45
 
40
- + This gem needs some specs
41
- + This gem only access profile and immediate family information. I don't have a paid account, I cannot implement everything now.
46
+ All request responses are stubbed via Faraday in `spec/support/mocked_responses`.
42
47
 
43
48
  # Feedback and help
44
49
 
@@ -0,0 +1,9 @@
1
+ require 'rake'
2
+ require 'rspec/core/rake_task'
3
+
4
+ desc "Run all examples"
5
+ RSpec::Core::RakeTask.new(:spec) do |t|
6
+ t.rspec_opts = %w[--color]
7
+ end
8
+
9
+ task :default => :spec
@@ -2,10 +2,10 @@
2
2
 
3
3
  Gem::Specification.new do |s|
4
4
  s.name = %q{geni}
5
- s.version = "0.0.5"
5
+ s.version = "0.0.6"
6
6
 
7
7
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
8
- s.authors = ["Aurélien Malisart","Matt Johnston"]
8
+ s.authors = ["Aurélien Malisart", "Matt Johnston"]
9
9
  s.date = %q{2011-02-03}
10
10
  s.description = %q{A Ruby client to the geni.com API}
11
11
  s.email = %q{aurelien.malisart@gmail.com}
@@ -15,19 +15,8 @@ Gem::Specification.new do |s|
15
15
  "README.md"
16
16
  ]
17
17
 
18
- s.files = [
19
- ".gitignore",
20
- "README.md",
21
- "lib/geni.rb",
22
- "lib/array_hacks.rb",
23
- "lib/oauth_hacks.rb",
24
- "lib/geni/base.rb",
25
- "lib/geni/client.rb",
26
- "lib/geni/family.rb",
27
- "lib/geni/profile.rb",
28
- "geni.gemspec",
29
- "LICENSE"
30
- ]
18
+ s.files = `git ls-files`.split("\n")
19
+ s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
31
20
  s.homepage = %q{http://github.com/aurels/geni}
32
21
  s.rdoc_options = ["--charset=UTF-8"]
33
22
  s.require_paths = ['lib']
@@ -40,5 +29,8 @@ Gem::Specification.new do |s|
40
29
  s.specification_version = 3
41
30
  s.add_dependency(%q<oauth2>, ["= 0.1.1"])
42
31
  s.add_dependency(%q<json>, ["= 1.5.0"])
32
+
33
+ s.add_development_dependency("rake", "~> 0.8.7")
34
+ s.add_development_dependency("rspec", "2.5.0")
43
35
  end
44
36
  end
@@ -1,7 +1,13 @@
1
1
  require 'oauth2'
2
2
  require 'oauth_hacks'
3
3
  require 'array_hacks'
4
- require 'geni/client'
4
+
5
5
  require 'geni/base'
6
+ require 'geni/taggable'
6
7
  require 'geni/profile'
7
- require 'geni/family'
8
+ require 'geni/union'
9
+ require 'geni/project'
10
+ require 'geni/photo'
11
+ require 'geni/document'
12
+ require 'geni/video'
13
+ require 'geni/client'
@@ -1,12 +1,39 @@
1
1
  module Geni
2
2
  class Base
3
- attr_reader :client
4
-
3
+ attr_reader :id, :client
4
+
5
5
  def initialize(params = {})
6
+ @id = params[:id]
6
7
  @client = params[:client]
7
- params[:attrs].each_pair do |attr, value|
8
+ @fetched = params[:fetched] || false
9
+
10
+ if params.has_key?(:attrs)
11
+ params[:attrs].each_pair do |key, value|
12
+ instance_variable_set("@#{key}", value)
13
+ end
14
+ end
15
+ end
16
+
17
+ def fetched?
18
+ @fetched
19
+ end
20
+
21
+ def fetch
22
+ client.access_token.get("/api/#{id}").each_pair do |attr, value|
8
23
  instance_variable_set("@#{attr}".to_sym, value)
9
24
  end
25
+ @fetched = true
26
+ end
27
+
28
+ class << self
29
+ def has_fetchable_attributes(attribute_names)
30
+ attribute_names.each do |attribute_name|
31
+ define_method "#{attribute_name}" do
32
+ self.fetch unless self.fetched?
33
+ instance_variable_get("@#{attribute_name}")
34
+ end
35
+ end
36
+ end
10
37
  end
11
38
  end
12
39
  end
@@ -18,33 +18,55 @@ module Geni
18
18
 
19
19
  @access_token = OAuth2::AccessToken.new(oauth_client, params[:token])
20
20
  end
21
+
22
+ TYPES = {
23
+ 'profile' => Geni::Profile,
24
+ 'union' => Geni::Union,
25
+ 'project' => Geni::Project,
26
+ 'photo' => Geni::Photo,
27
+ 'document' => Geni::Document,
28
+ 'video' => Geni::Video
29
+ }
21
30
 
22
- def get_profile(id_or_ids = nil)
23
- if id_or_ids.nil?
24
- url = "/api/profile"
25
- elsif id_or_ids.kind_of?(Array)
26
- if id_or_ids.any?
27
- url = "/api/profile-#{id_or_ids.join(',')}"
28
- else
29
- return []
30
- end
31
- else
32
- url = "/api/profile-#{id_or_ids}"
31
+ TYPES.each_pair do |type, klass|
32
+ define_method "get_#{type}" do |id|
33
+ entity = klass.new({
34
+ :client => self,
35
+ :id => id
36
+ })
33
37
  end
34
-
35
- results = access_token.get(url)
36
- results = results['results'] if results.has_key?('results')
38
+ end
39
+
40
+ def get_profiles(ids)
41
+ return [] if ids.empty?
42
+ return [get_profile(ids.first)] if ids.one?
43
+
44
+ numbers = ids.collect { |id| id.gsub(/profile-/, '') }.join(',')
45
+ url = "/api/profile-#{numbers}"
46
+ results = access_token.get(url)['results']
37
47
 
38
- profiles = [results].flatten.collect do |profile_attrs|
48
+ results.collect do |profile_attrs|
39
49
  Geni::Profile.new({
40
- :client => self,
41
- :attrs => profile_attrs
50
+ :client => self,
51
+ :attrs => profile_attrs,
52
+ :fetched => true
42
53
  })
43
54
  end
44
-
45
- id_or_ids.kind_of?(Array) ? profiles : profiles.first
46
55
  end
47
56
 
57
+ def me
58
+ Geni::Profile.new({
59
+ :client => self,
60
+ :attrs => access_token.get('/api/profile'),
61
+ :fetched => true
62
+ })
63
+ end
64
+
65
+ def [](entity_id)
66
+ entity_type = entity_id.split('-').first
67
+ send("get_#{entity_type}", entity_id)
68
+ end
69
+
48
70
  def redirect_uri(request)
49
71
  uri = URI.parse(request.url)
50
72
  uri.path = @callback
@@ -0,0 +1,9 @@
1
+ module Geni
2
+ class Document < Base
3
+ has_fetchable_attributes %w[
4
+ title url date date_parts content_type description sizes
5
+ ]
6
+
7
+ include Taggable
8
+ end
9
+ end
@@ -0,0 +1,10 @@
1
+ module Geni
2
+ class Photo < Base
3
+
4
+ has_fetchable_attributes %w[
5
+ title url date date_parts content_type sizes album_id created_on
6
+ ]
7
+
8
+ include Taggable
9
+ end
10
+ end
@@ -1,36 +1,22 @@
1
+ require 'geni/profile/immediate_family'
2
+
1
3
  module Geni
2
4
  class Profile < Base
3
- attr_reader :id
4
- attr_reader :first_name
5
- attr_reader :middle_name
6
- attr_reader :maiden_name
7
- attr_reader :last_name
8
- attr_reader :suffix
9
- attr_reader :display_name
10
- attr_reader :name
11
- attr_reader :gender
12
- attr_reader :current_residence
13
- attr_reader :created_by
14
- attr_reader :managers
15
- attr_reader :merged_into
16
- attr_reader :requested_merges
17
- attr_reader :merge_note
18
- attr_reader :public
19
- attr_reader :big_tree
20
- attr_reader :claimed
21
- attr_reader :locked
22
- attr_reader :birth_date
23
- attr_reader :birth_location
24
- attr_reader :birth_location
25
- attr_reader :death_date
26
- attr_reader :death_location
27
- attr_reader :burial_date
28
- attr_reader :url
29
- attr_reader :language
30
- attr_reader :curator
31
- attr_reader :mugshot_urls
32
- attr_reader :birth_date_parts
33
- attr_reader :relationship
5
+
6
+ has_fetchable_attributes %w[
7
+ first_name middle_name maiden_name last_name suffix display_name name gender
8
+ current_residence created_by merge_note public big_tree claimed locked birth_date
9
+ borth_date_parts birth_location baptism_date baptism_date_parts baptism_location
10
+ death_date death_date_parts death_location burial_date blurial_date_parts blurial_location
11
+ url language mugshot_urls relationship is_alive
12
+ ]
13
+
14
+ def immediate_family
15
+ @immediate_family ||= Geni::Profile::ImmediateFamily.new({
16
+ :client => client,
17
+ :attrs => client.access_token.get("/api/#{id}/immediate-family")
18
+ })
19
+ end
34
20
 
35
21
  def parents
36
22
  immediate_family.parents
@@ -55,12 +41,57 @@ module Geni
55
41
  def partners
56
42
  immediate_family.partners
57
43
  end
58
-
59
- def immediate_family
60
- @immediate_family ||= Geni::Family.new({
61
- :client => client,
62
- :attrs => client.access_token.get("/api/profile-#{id}/immediate-family")
63
- })
44
+
45
+ def managers
46
+ @manager_profiles ||= @managers.collect do |profile_link|
47
+ client.get_profile(profile_link.split('-').last)
48
+ end
49
+ end
50
+
51
+ def merged_into
52
+ @merged_into_profiles ||= @merged_into.to_a.collect do |profile_link|
53
+ client.get_profile(profile_link.split('-').last)
54
+ end
55
+ end
56
+
57
+ def requested_merges
58
+ @requested_merges_profiles ||= @requested_merges.to_a.collect do |profile_link|
59
+ client.get_profile(profile_link.split('-').last)
60
+ end
61
+ end
62
+
63
+ def curator
64
+ @curator_profile ||= @curator.nil? ? nil : client.get_profile(@curator.split('/').last)
65
+ end
66
+
67
+ def photos
68
+ @photos ||= client.access_token.get("/api/#{id}/photos")['results'].to_a.collect do |photo_attrs|
69
+ Geni::Photo.new({
70
+ :client => client,
71
+ :attrs => photo_attrs,
72
+ :fetched => true
73
+ })
74
+ end
75
+ end
76
+
77
+ def videos
78
+ @videos ||= client.access_token.get("/api/#{id}/videos")['results'].to_a.collect do |video_attrs|
79
+ Geni::Photo.new({
80
+ :client => client,
81
+ :attrs => video_attrs,
82
+ :fetched => true
83
+ })
84
+ end
85
+ end
86
+
87
+ def documents
88
+ @documents ||= client.access_token.get("/api/#{id}/documents")['results'].collect do |documents_attrs|
89
+ Geni::Photo.new({
90
+ :client => client,
91
+ :attrs => documents_attrs,
92
+ :fetched => true
93
+ })
94
+ end
64
95
  end
65
96
  end
66
97
  end
@@ -0,0 +1,51 @@
1
+ module Geni
2
+ class Profile < Base
3
+ class ImmediateFamily
4
+ attr_reader :client, :focus
5
+
6
+ def initialize(params)
7
+ @client = params[:client]
8
+
9
+ params[:attrs].each_pair do |key, value|
10
+ instance_variable_set("@#{key}", value)
11
+ end
12
+ end
13
+
14
+ def parents
15
+ @parents ||= profiles(walk(focus_node, ['child', 'partner']))
16
+ end
17
+
18
+ def partners
19
+ @partners ||= profiles(walk(focus_node, ['partner', 'partner']))
20
+ end
21
+
22
+ def children
23
+ @children ||= profiles(walk(focus_node, ['partner', 'child']))
24
+ end
25
+
26
+ def siblings
27
+ @siblings ||= profiles(walk(focus_node, ['child', 'child']))
28
+ end
29
+
30
+ protected
31
+
32
+ def focus_node
33
+ @nodes[@focus['id']]
34
+ end
35
+
36
+ def walk(node, rels)
37
+ return node if rels.empty?
38
+
39
+ node['edges'].collect do |edge_id, edge|
40
+ if edge['rel'] == rels.first && edge_id != @focus['id']
41
+ walk(@nodes[edge_id], rels.tail)
42
+ end
43
+ end.compact.flatten
44
+ end
45
+
46
+ def profiles(nodes)
47
+ client.get_profiles(nodes.collect { |node| node['id'] })
48
+ end
49
+ end
50
+ end
51
+ end
@@ -0,0 +1,19 @@
1
+ module Geni
2
+ class Project < Base
3
+ has_fetchable_attributes %w[name description url]
4
+
5
+ ['collaborators', 'profiles', 'followers'].each do |relation_name|
6
+ define_method relation_name do
7
+ if instance_variable_get("@#{relation_name}").nil?
8
+ profile_ids = client.access_token.get("/api/#{id}/#{relation_name}")['results'].collect do |profile|
9
+ profile['id'].split('-').last
10
+ end
11
+
12
+ instance_variable_set("@#{relation_name}", client.get_profiles(profile_ids))
13
+ else
14
+ instance_variable_get("@#{relation_name}")
15
+ end
16
+ end
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,27 @@
1
+ module Geni
2
+ module Taggable
3
+ def tags
4
+ return @tags if @tags
5
+
6
+ response_hash = client.access_token.get("/api/#{id}/tags")
7
+
8
+ if response_hash.has_key?('results')
9
+ profile_ids = response_hash['results'].collect do |profile|
10
+ profile['id']
11
+ end
12
+
13
+ @tags = client.get_profiles(profile_ids)
14
+ else
15
+ @tags = []
16
+ end
17
+ end
18
+
19
+ def tag
20
+ raise NotImplementedError
21
+ end
22
+
23
+ def untag
24
+ raise NotImplementedError
25
+ end
26
+ end
27
+ end