geni 0.0.5 → 0.0.6

Sign up to get free protection for your applications and to get access to all the features.
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