adamsalter-ken 0.1.1
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/.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
|
+
}
|