adamsalter-ken 0.1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +23 -0
- data/History.txt +3 -0
- data/LICENSE +20 -0
- data/README.textile +264 -0
- data/README.txt +76 -0
- data/Rakefile +58 -0
- data/TODO +0 -0
- data/VERSION +1 -0
- data/examples/artist.rb +21 -0
- data/examples/artist_links.rb +28 -0
- data/ken.gemspec +88 -0
- data/lib/ken/attribute.rb +62 -0
- data/lib/ken/collection.rb +8 -0
- data/lib/ken/logger.rb +233 -0
- data/lib/ken/property.rb +91 -0
- data/lib/ken/resource.rb +144 -0
- data/lib/ken/session.rb +132 -0
- data/lib/ken/type.rb +53 -0
- data/lib/ken/util.rb +18 -0
- data/lib/ken/view.rb +56 -0
- data/lib/ken.rb +124 -0
- data/rails/init.rb +2 -0
- data/tasks/ken.rb +4 -0
- data/tasks/spec.rb +25 -0
- data/test/fixtures/music_artist.json +103 -0
- data/test/fixtures/the_police.json +937 -0
- data/test/integration/ken_test.rb +75 -0
- data/test/test_helper.rb +61 -0
- data/test/unit/attribute_test.rb +49 -0
- data/test/unit/property_test.rb +27 -0
- data/test/unit/resource_test.rb +53 -0
- data/test/unit/session_test.rb +27 -0
- data/test/unit/type_test.rb +35 -0
- data/test/unit/view_test.rb +48 -0
- metadata +127 -0
data/lib/ken/view.rb
ADDED
@@ -0,0 +1,56 @@
|
|
1
|
+
# provides an interface to view a resource as a specific type
|
2
|
+
# provides an interface for working with attributes, properties
|
3
|
+
module Ken
|
4
|
+
class View
|
5
|
+
|
6
|
+
include Extlib::Assertions
|
7
|
+
|
8
|
+
# initializes a resource by json result
|
9
|
+
def initialize(resource, type)
|
10
|
+
assert_kind_of 'resource', resource, Ken::Resource
|
11
|
+
assert_kind_of 'type', type, Ken::Type
|
12
|
+
@resource, @type = resource, type
|
13
|
+
end
|
14
|
+
|
15
|
+
# @api public
|
16
|
+
def to_s
|
17
|
+
@type.to_s
|
18
|
+
end
|
19
|
+
|
20
|
+
# return correspondent type
|
21
|
+
# @api public
|
22
|
+
def type
|
23
|
+
@type
|
24
|
+
end
|
25
|
+
|
26
|
+
# @api public
|
27
|
+
def inspect
|
28
|
+
result = "#<View type=\"#{type.id || "nil"}\">"
|
29
|
+
end
|
30
|
+
|
31
|
+
# returns attributes which are member of the view's type
|
32
|
+
# @api public
|
33
|
+
def attributes
|
34
|
+
@resource.attributes.select { |a| a.property.type == @type}
|
35
|
+
end
|
36
|
+
|
37
|
+
# search for an attribute by name and return it
|
38
|
+
# @api public
|
39
|
+
def attribute(name)
|
40
|
+
attributes.each { |a| return a if a.property.id =~ /\/#{name}$/ }
|
41
|
+
nil
|
42
|
+
end
|
43
|
+
|
44
|
+
# returns properties which are member of the view's type
|
45
|
+
# @api public
|
46
|
+
def properties
|
47
|
+
@resource.properties.select { |p| p.type == @type}
|
48
|
+
end
|
49
|
+
|
50
|
+
# delegate to attribute
|
51
|
+
def method_missing sym
|
52
|
+
attribute(sym.to_s)
|
53
|
+
end
|
54
|
+
|
55
|
+
end
|
56
|
+
end
|
data/lib/ken.rb
ADDED
@@ -0,0 +1,124 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rubygems'
|
3
|
+
require 'net/http'
|
4
|
+
require 'json'
|
5
|
+
require 'extlib/assertions'
|
6
|
+
require 'addressable/uri'
|
7
|
+
|
8
|
+
dir = Pathname(__FILE__).dirname.expand_path + 'ken'
|
9
|
+
|
10
|
+
require dir + 'util'
|
11
|
+
require dir + 'resource'
|
12
|
+
require dir + 'type'
|
13
|
+
require dir + 'view'
|
14
|
+
require dir + 'property'
|
15
|
+
require dir + 'attribute'
|
16
|
+
require dir + 'collection'
|
17
|
+
require dir + 'session'
|
18
|
+
require dir + 'logger'
|
19
|
+
|
20
|
+
# init logger as soon as the library is required
|
21
|
+
Ken::Logger.new(STDOUT, :error)
|
22
|
+
|
23
|
+
# init default session
|
24
|
+
Ken::Session.new('http://www.freebase.com', 'ma', 'xxxxx')
|
25
|
+
|
26
|
+
module Ken
|
27
|
+
extend Extlib::Assertions
|
28
|
+
|
29
|
+
# store query as a constant here.
|
30
|
+
# if the hash gets updated using
|
31
|
+
# #merge! or #update, this will mean
|
32
|
+
# that it actually stores the last
|
33
|
+
# query used. there are 2 sides to this.
|
34
|
+
# on the one hand, it isn't really a
|
35
|
+
# constant anymore (ruby doesn't complain)?
|
36
|
+
# on the other hand, there is no need to
|
37
|
+
# create a new object everytime a query is
|
38
|
+
# executed. maybe this is fine, maybe not,
|
39
|
+
# this needs to be discussed.
|
40
|
+
|
41
|
+
FETCH_DATA_QUERY = {
|
42
|
+
# :id => id, # needs to be merge!d in instance method
|
43
|
+
:guid => nil,
|
44
|
+
:name => nil,
|
45
|
+
:"ken:type" => [{
|
46
|
+
:id => nil,
|
47
|
+
:name => nil,
|
48
|
+
:properties => [{
|
49
|
+
:id => nil,
|
50
|
+
:name => nil,
|
51
|
+
:expected_type => nil,
|
52
|
+
:unique => nil,
|
53
|
+
:reverse_property => nil,
|
54
|
+
:master_property => nil,
|
55
|
+
}]
|
56
|
+
}],
|
57
|
+
:"/type/reflect/any_master" => [
|
58
|
+
{
|
59
|
+
:id => nil,
|
60
|
+
:link => nil,
|
61
|
+
:name => nil,
|
62
|
+
:optional => true
|
63
|
+
}
|
64
|
+
],
|
65
|
+
:"/type/reflect/any_reverse" => [
|
66
|
+
{
|
67
|
+
:id => nil,
|
68
|
+
:link => nil,
|
69
|
+
:name => nil,
|
70
|
+
:optional => true
|
71
|
+
}
|
72
|
+
],
|
73
|
+
:"/type/reflect/any_value" => [
|
74
|
+
{
|
75
|
+
:link => nil,
|
76
|
+
:value => nil,
|
77
|
+
:optional => true
|
78
|
+
# TODO: support multiple language
|
79
|
+
# :lang => "/lang/en",
|
80
|
+
# :type => "/type/text"
|
81
|
+
}
|
82
|
+
]
|
83
|
+
}
|
84
|
+
|
85
|
+
|
86
|
+
# Executes an Mql Query against the Freebase API and returns the result as
|
87
|
+
# a <tt>Collection</tt> of <tt>Resources</tt>.
|
88
|
+
#
|
89
|
+
# performs a cursored query unless there's a limit specified
|
90
|
+
# == Examples
|
91
|
+
#
|
92
|
+
# Ken.all(:name => "Apple", :type => "/music/album")
|
93
|
+
#
|
94
|
+
# Ken.all(
|
95
|
+
# :directed_by => "George Lucas",
|
96
|
+
# :starring => [{
|
97
|
+
# :actor => "Harrison Ford"
|
98
|
+
# }],
|
99
|
+
# :type => "/film/film"
|
100
|
+
# )
|
101
|
+
# @api public
|
102
|
+
def self.all(options = {})
|
103
|
+
assert_kind_of 'options', options, Hash
|
104
|
+
query = { :name => nil }.merge!(options).merge!(:id => nil)
|
105
|
+
result = Ken.session.mqlread([ query ], :cursor => !options[:limit])
|
106
|
+
Ken::Collection.new(result.map { |r| Ken::Resource.new(r) })
|
107
|
+
end
|
108
|
+
|
109
|
+
|
110
|
+
# Executes an Mql Query against the Freebase API and returns the result wrapped
|
111
|
+
# in a <tt>Resource</tt> Object.
|
112
|
+
#
|
113
|
+
# == Examples
|
114
|
+
#
|
115
|
+
# Ken.get('/en/the_police') => #<Resource id="/en/the_police" name="The Police">
|
116
|
+
# @api public
|
117
|
+
def self.get(id)
|
118
|
+
assert_kind_of 'id', id, String
|
119
|
+
result = Ken.session.mqlread(FETCH_DATA_QUERY.merge!(:id => id))
|
120
|
+
raise ResourceNotFound unless result
|
121
|
+
Ken::Resource.new(result)
|
122
|
+
end
|
123
|
+
|
124
|
+
end # module Ken
|
data/rails/init.rb
ADDED
data/tasks/ken.rb
ADDED
data/tasks/spec.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
begin
|
2
|
+
gem 'rspec', '~>1.1.12'
|
3
|
+
require 'spec'
|
4
|
+
require 'spec/rake/spectask'
|
5
|
+
|
6
|
+
task :default => [ :spec ]
|
7
|
+
|
8
|
+
desc 'Run specifications'
|
9
|
+
Spec::Rake::SpecTask.new(:spec) do |t|
|
10
|
+
t.spec_opts << '--options' << 'spec/spec.opts' if File.exists?('spec/spec.opts')
|
11
|
+
t.spec_files = Pathname.glob((ROOT + 'spec/**/*_spec.rb').to_s).map { |f| f.to_s }
|
12
|
+
|
13
|
+
begin
|
14
|
+
gem 'rcov', '~>0.8'
|
15
|
+
t.rcov = JRUBY ? false : (ENV.has_key?('NO_RCOV') ? ENV['NO_RCOV'] != 'true' : true)
|
16
|
+
t.rcov_opts << '--exclude' << 'spec'
|
17
|
+
t.rcov_opts << '--text-summary'
|
18
|
+
t.rcov_opts << '--sort' << 'coverage' << '--sort-reverse'
|
19
|
+
rescue LoadError
|
20
|
+
# rcov not installed
|
21
|
+
end
|
22
|
+
end
|
23
|
+
rescue LoadError
|
24
|
+
# rspec not installed
|
25
|
+
end
|
@@ -0,0 +1,103 @@
|
|
1
|
+
|
2
|
+
{
|
3
|
+
"id" : "/music/artist",
|
4
|
+
"name" : "Musical Artist",
|
5
|
+
"properties" : [
|
6
|
+
{
|
7
|
+
"expected_type" : "/location/location",
|
8
|
+
"id" : "/music/artist/origin",
|
9
|
+
"name" : "Place Musical Career Began",
|
10
|
+
"unique" :true
|
11
|
+
},
|
12
|
+
{
|
13
|
+
"expected_type" : "/type/datetime",
|
14
|
+
"id" : "/music/artist/active_start",
|
15
|
+
"name" : "Active as Musical Artist (start)",
|
16
|
+
"unique" : true
|
17
|
+
},
|
18
|
+
{
|
19
|
+
"expected_type" : "/type/datetime",
|
20
|
+
"id" : "/music/artist/active_end",
|
21
|
+
"name" : "Active as Musical Artist (end)",
|
22
|
+
"unique" : true
|
23
|
+
},
|
24
|
+
{
|
25
|
+
"expected_type" : "/music/genre",
|
26
|
+
"id" : "/music/artist/genre",
|
27
|
+
"name" : "Musical Genres",
|
28
|
+
"unique" : null
|
29
|
+
},
|
30
|
+
{
|
31
|
+
"expected_type" : "/music/record_label",
|
32
|
+
"id" : "/music/artist/label",
|
33
|
+
"name" : "Record Labels",
|
34
|
+
"unique" : null
|
35
|
+
},
|
36
|
+
{
|
37
|
+
"expected_type" : "/music/artist",
|
38
|
+
"id" : "/music/artist/similar_artist",
|
39
|
+
"name" : "Similar Artists",
|
40
|
+
"unique" : null
|
41
|
+
},
|
42
|
+
{
|
43
|
+
"expected_type" : "/common/webpage",
|
44
|
+
"id" : "/music/artist/home_page",
|
45
|
+
"name" : "Musical Artist Home Page",
|
46
|
+
"unique" : null
|
47
|
+
},
|
48
|
+
{
|
49
|
+
"expected_type" : "/common/webpage",
|
50
|
+
"id" : "/music/artist/acquire_webpage",
|
51
|
+
"name" : "Web Page for Music",
|
52
|
+
"unique" : null
|
53
|
+
},
|
54
|
+
{
|
55
|
+
"expected_type" : "/music/album",
|
56
|
+
"id" : "/music/artist/album",
|
57
|
+
"name" : "Albums",
|
58
|
+
"unique" : null
|
59
|
+
},
|
60
|
+
{
|
61
|
+
"expected_type" : "/music/recording_contribution",
|
62
|
+
"id" : "/music/artist/contribution",
|
63
|
+
"name" : "Album Contributions",
|
64
|
+
"unique" : null
|
65
|
+
},
|
66
|
+
{
|
67
|
+
"expected_type" : "/music/track",
|
68
|
+
"id" : "/music/artist/track",
|
69
|
+
"name" : "Tracks Recorded",
|
70
|
+
"unique" : null
|
71
|
+
},
|
72
|
+
{
|
73
|
+
"expected_type" : "/music/artist",
|
74
|
+
"id" : "/music/artist/artist_similar",
|
75
|
+
"name" : "Similar Musical Artists",
|
76
|
+
"unique" : null
|
77
|
+
},
|
78
|
+
{
|
79
|
+
"expected_type" : "/music/track_contribution",
|
80
|
+
"id" : "/music/artist/track_contributions",
|
81
|
+
"name" : "Track Contributions",
|
82
|
+
"unique" : null
|
83
|
+
},
|
84
|
+
{
|
85
|
+
"expected_type" : "/music/instrument",
|
86
|
+
"id" : "/music/artist/instruments_played",
|
87
|
+
"name" : "Instruments Played",
|
88
|
+
"unique" : null
|
89
|
+
},
|
90
|
+
{
|
91
|
+
"expected_type" : "/music/voice",
|
92
|
+
"id" : "/music/artist/vocal_range",
|
93
|
+
"name" : "Vocal Range",
|
94
|
+
"unique" : null
|
95
|
+
},
|
96
|
+
{
|
97
|
+
"expected_type" : "/music/concert_tour",
|
98
|
+
"id" : "/music/artist/concert_tours",
|
99
|
+
"name" : "Concert Tours",
|
100
|
+
"unique" : false
|
101
|
+
}
|
102
|
+
]
|
103
|
+
}
|