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/.gitignore
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
test_log
|
2
|
+
pkg
|
3
|
+
pkg/*
|
4
|
+
*/pkg/*
|
5
|
+
bundle
|
6
|
+
bundle/*
|
7
|
+
doc
|
8
|
+
*.log
|
9
|
+
log
|
10
|
+
!log*.rb
|
11
|
+
*/log
|
12
|
+
log/*
|
13
|
+
*/log/*
|
14
|
+
coverage
|
15
|
+
*/coverage
|
16
|
+
lib/dm-more.rb
|
17
|
+
*.db
|
18
|
+
nbproject
|
19
|
+
.DS_Store
|
20
|
+
rspec_report.html
|
21
|
+
*.swp
|
22
|
+
_Yardoc
|
23
|
+
*/ri
|
data/History.txt
ADDED
data/LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2009 Michael Aufreiter
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.textile
ADDED
@@ -0,0 +1,264 @@
|
|
1
|
+
h1. Ken
|
2
|
+
|
3
|
+
h2. Introduction
|
4
|
+
|
5
|
+
Ken is a Data Layer for Knowledge Representation.
|
6
|
+
|
7
|
+
It's being built to access the Metaweb Services supplied by Freebase.com.
|
8
|
+
The project’s goals are the provision of a concise API for querying and writing.
|
9
|
+
Therefore it wraps the Metaweb Architecture to smart Ruby Objects.
|
10
|
+
|
11
|
+
You can navigate the Freebase Graph using a rubyish syntax.
|
12
|
+
Also you can use this library as a Data Layer (instead of or in addition to ActiveRecord/DataMapper) for your Web Framework of choice (Merb, Rails).
|
13
|
+
|
14
|
+
h2. Installation
|
15
|
+
|
16
|
+
Use GitHub RubyGems:
|
17
|
+
|
18
|
+
<pre>
|
19
|
+
<code>
|
20
|
+
$ gem sources -a http://gems.github.com (you only have to do this once)
|
21
|
+
$ sudo gem install michael-ken
|
22
|
+
</code>
|
23
|
+
</pre>
|
24
|
+
|
25
|
+
In your Ruby files add:
|
26
|
+
|
27
|
+
<pre>
|
28
|
+
<code>
|
29
|
+
require 'rubygems'
|
30
|
+
gem 'michael-ken'
|
31
|
+
require 'ken'
|
32
|
+
</code>
|
33
|
+
</pre>
|
34
|
+
|
35
|
+
|
36
|
+
h2. Getting started
|
37
|
+
|
38
|
+
The first place to get started with Freebase is of course, Freebase. Try out their Browser at
|
39
|
+
"http://www.freebase.com":http://www.freebase.com.
|
40
|
+
|
41
|
+
The Freebase Database can be thought of as a huge graph of interconnected nodes that represent
|
42
|
+
knowledge (in a much more structured way than wikipedia does).
|
43
|
+
That graph can be viewed at a higher level through an object-oriented lens which leads to easier interaction.
|
44
|
+
To understand the fundamental Metaweb Architecture please read the official
|
45
|
+
"MQL Reference guide":http://download.freebase.com/MQLReferenceGuide.pdf (with focus on Chapter 2)
|
46
|
+
provided by Freebase.
|
47
|
+
|
48
|
+
In addition, you can learn a lot by employing the Freebase "Query Editor":http://www.freebase.com/tools/queryeditor/.
|
49
|
+
|
50
|
+
h3. Fetching a Resource
|
51
|
+
|
52
|
+
Let's ask Ken what he knows about the British Band New Order.
|
53
|
+
|
54
|
+
<pre>
|
55
|
+
<code>
|
56
|
+
resource = Ken.get('/en/new_order') # => <Resource id="/en/new_order" name="New Order">
|
57
|
+
</code>
|
58
|
+
</pre>
|
59
|
+
|
60
|
+
h3. Inspecting the Types
|
61
|
+
|
62
|
+
Every Resource can have multiple types.
|
63
|
+
|
64
|
+
<pre>
|
65
|
+
<code>
|
66
|
+
resource.types
|
67
|
+
# => [ #<Type id="/film/music_contributor" name="Film music contributor">, #<Type id="/music/artist" name="Musical Artist">,
|
68
|
+
#<Type id="/common/topic" name="Topic">, #<Type id="/music/musical_group" name="Musical Group">,
|
69
|
+
#<Type id="/broadcast/artist" name="Broadcast Artist">, #<Type id="/music/group_member" name="Musical Group Member"> ]
|
70
|
+
</code>
|
71
|
+
</pre>
|
72
|
+
|
73
|
+
We can see that New Order is a member of Music Artist, Film Music Contributor, Broadcast Artist and other types.
|
74
|
+
|
75
|
+
h3. Inspecting a Type's properties
|
76
|
+
|
77
|
+
A type defines a set of properties to describe a Resource.
|
78
|
+
|
79
|
+
<pre>
|
80
|
+
<code>
|
81
|
+
resource.types.each do |type|
|
82
|
+
type.properties # => e.g. [ #<Property id="/music/musical_group/member"> ]
|
83
|
+
end
|
84
|
+
</code>
|
85
|
+
</pre>
|
86
|
+
|
87
|
+
We get sets of Properties for each Type. The Type Musical Group has just one Property @/music/musical_group/member@
|
88
|
+
named Members Of Musical Group.
|
89
|
+
|
90
|
+
h3. Listing all Attributes
|
91
|
+
|
92
|
+
After inspecting a Resource's Types and Properties we now know what we could know. But actually we don't know nothing :)
|
93
|
+
So it's time to ask for the values of properties, the so called _Attributes_.
|
94
|
+
|
95
|
+
~Note: In Ken's terminology we differ between _Properties_ and concrete Property instances, the _Attributes_, while
|
96
|
+
Freebase itself doesn't.~
|
97
|
+
|
98
|
+
<pre>
|
99
|
+
<code>
|
100
|
+
resource.attributes.each do |att|
|
101
|
+
att # => e.g. #<Attribute property="/music/artist/album">
|
102
|
+
att.property.name # => e.g. "Albums"
|
103
|
+
|
104
|
+
att.values
|
105
|
+
# e.g. => [ #<Resource id="/guid/9202a8c04000641f8000000002fa2556" name="Ceremony">,
|
106
|
+
#<Resource id="/guid/9202a8c04000641f8000000002fa24d5" name="Procession">,
|
107
|
+
#<Resource id="/guid/9202a8c04000641f8000000002fa20d3" name="Everything's Gone Green">, ... ]
|
108
|
+
# e.g. => ["1980"]
|
109
|
+
end
|
110
|
+
</code>
|
111
|
+
</pre>
|
112
|
+
|
113
|
+
Attributes are slightly more complicated to handle compared to Types and Properties.
|
114
|
+
|
115
|
+
There are four kinds of Attributes.
|
116
|
+
* Unique Value Type
|
117
|
+
* Unique Object Type
|
118
|
+
* Non-unique Value Type
|
119
|
+
* Non-unique Object
|
120
|
+
|
121
|
+
In order to be able to use unique and non-unique Attributes in the same manner we always wrap the value of an Attribute
|
122
|
+
in a Collection, no matter if there's one value or there are many.
|
123
|
+
|
124
|
+
h3. Group Attributes by their Type using Views
|
125
|
+
|
126
|
+
|
127
|
+
<pre>
|
128
|
+
<code>
|
129
|
+
resource.views.each do |view|
|
130
|
+
view # => e.g. #<View type="/music/artist">
|
131
|
+
view.type # => e.g #<Type id="/music/artist" name="Musical Artist">
|
132
|
+
view.attributes
|
133
|
+
# => [#<Attribute property="/music/artist/home_page">, #<Attribute property="/music/artist/genre">,
|
134
|
+
#<Attribute property="/music/artist/active_start">, #<Attribute property="/music/artist/similar_artist">,
|
135
|
+
#<Attribute property="/music/artist/album">, #<Attribute property="/music/artist/label">,
|
136
|
+
#<Attribute property="/music/artist/track">, #<Attribute property="/music/artist/origin">]
|
137
|
+
|
138
|
+
view.attributes.each do |att|
|
139
|
+
att.values
|
140
|
+
# e.g. => [ #<Resource id="/en/alternative_dance" name="Alternative dance">,
|
141
|
+
#<Resource id="/en/synthpop" name="Synthpop">,
|
142
|
+
#<Resource id="/en/house_music" name="House music">,
|
143
|
+
#<Resource id="/en/post-punk" name="Post-punk"> ]
|
144
|
+
# e.g. => ["1980"]
|
145
|
+
end
|
146
|
+
end
|
147
|
+
</code>
|
148
|
+
</pre>
|
149
|
+
|
150
|
+
h3. Fetching multiple Resources using a query
|
151
|
+
|
152
|
+
As of now you can ask for multiple Resources by specifying a query.
|
153
|
+
|
154
|
+
<pre>
|
155
|
+
<code>
|
156
|
+
resources = Ken.all(:name => "Apple", :type => "/music/album")
|
157
|
+
# => [#<Resource id="/guid/9202a8c04000641f80000000031dae7c" name="Apple">,
|
158
|
+
#<Resource id="/guid/9202a8c04000641f8000000007ce31ec" name="Apple">]
|
159
|
+
</code>
|
160
|
+
</pre>
|
161
|
+
|
162
|
+
Keep in mind that only the top level of the query is mapped to a Collection of Resource Objects.
|
163
|
+
So asking for values in a nested level does not make sense. Use nested statements just for
|
164
|
+
lowering the top level result.
|
165
|
+
|
166
|
+
However you can instead navigate the normal way to figure out that values.
|
167
|
+
_But won't that require another query to triggered? Certainly._
|
168
|
+
|
169
|
+
Let's look at a nested query:
|
170
|
+
|
171
|
+
<pre>
|
172
|
+
<code>
|
173
|
+
query = {
|
174
|
+
:directed_by => "George Lucas",
|
175
|
+
:starring => [
|
176
|
+
{
|
177
|
+
:actor => "Harrison Ford"
|
178
|
+
}
|
179
|
+
],
|
180
|
+
:type => "/film/film"
|
181
|
+
}
|
182
|
+
|
183
|
+
resources = Ken.all(query)
|
184
|
+
# => [#<Resource id="/en/star_wars_episode_iv_a_new_hope" name="Star Wars Episode IV: A New Hope">,
|
185
|
+
#<Resource id="/en/american_graffiti" name="American Graffiti">,
|
186
|
+
#<Resource id="/en/the_star_wars_holiday_special" name="The Star Wars Holiday Special">]
|
187
|
+
</code>
|
188
|
+
</pre>
|
189
|
+
|
190
|
+
h3. Access properties attributes directly
|
191
|
+
|
192
|
+
Ken is primarily designed for inspecting resources in a generic way, what's ideal for domain independent browsing applications.
|
193
|
+
However, there are legitimate situations where you already know what you want to access.
|
194
|
+
|
195
|
+
That's why I now added direct Property/Attribute access, but only on a Type/View level:
|
196
|
+
|
197
|
+
<pre>
|
198
|
+
<code>
|
199
|
+
resource = Ken.get('/en/new_order')
|
200
|
+
type = resource.types[1] # => #<Type id="/music/artist" name="Musical Artist">
|
201
|
+
# because we know _/music/artist_ has a _genre_ property we can access that directly
|
202
|
+
type.genre # => #<Property id="/music/artist/genre" expected_type="/music/genre" unique="false" object_type="true">
|
203
|
+
</code>
|
204
|
+
</pre>
|
205
|
+
|
206
|
+
The same works for views:
|
207
|
+
|
208
|
+
<pre>
|
209
|
+
<code>
|
210
|
+
resource = Ken.get('/en/new_order')
|
211
|
+
view = resource.views[1] # => #<View type="/music/artist">
|
212
|
+
# because we know _/music/artist_ has a _genre_ property we can access attribute directly as well
|
213
|
+
view.genre # => #<Attribute property="/music/artist/genre">
|
214
|
+
</code>
|
215
|
+
</pre>
|
216
|
+
|
217
|
+
If you rather want to query based on Types and access Properties/Attributes directly you can consider using
|
218
|
+
Chris "Eppsteins Freebase Library":http://github.com/chriseppstein/freebase/tree/master as an alternative.
|
219
|
+
|
220
|
+
|
221
|
+
h3. Low Level API
|
222
|
+
|
223
|
+
Sometimes you may want to do specific queries instead of inspecting Resources as a whole.
|
224
|
+
In such a case you would want to use Ken's low level API.
|
225
|
+
|
226
|
+
_mqlread_ works like the regular _mqlread service_, except that you are able to pass ruby hashes instead of JSON.
|
227
|
+
And you don't have to deal with HTTP, parameter encoding and parsing JSON.
|
228
|
+
|
229
|
+
<pre>
|
230
|
+
<code>
|
231
|
+
artists = Ken.session.mqlread([{
|
232
|
+
:type => "/music/artist",
|
233
|
+
:id => nil,
|
234
|
+
:"/common/topic/webpage" => [{:uri => nil}],
|
235
|
+
:home_page => [{:uri => nil}],
|
236
|
+
:limit => 2
|
237
|
+
}])
|
238
|
+
|
239
|
+
# => [
|
240
|
+
{"type"=>"/music/artist", "home_page"=>[{"uri"=>"http://www.massiveattack.co.uk/"}], "id"=>"/en/massive_attack", "/common/topic/webpage"=>[{"uri"=>"http://musicmoz.org/Bands_and_Artists/M/Massive_Attack/"}, {"uri"=>"http://www.discogs.com/artist/Massive+Attack"}, {"uri"=>"http://www.massiveattackarea.com/"}, {"uri"=>"http://www.massiveattack.co.uk/"}, {"uri"=>"http://www.massiveattack.com/"}]},
|
241
|
+
{"type"=>"/music/artist", "home_page"=>[{"uri"=>"http://www.apartment26.com/"}], "id"=>"/en/apartment_26", "/common/topic/webpage"=>[{"uri"=>"http://www.discogs.com/artist/Apartment+26"}, {"uri"=>"http://musicmoz.org/Bands_and_Artists/A/Apartment_26/"}, {"uri"=>"http://www.apartment26.com/"}]}
|
242
|
+
]
|
243
|
+
</code>
|
244
|
+
</pre>
|
245
|
+
|
246
|
+
h2. Project Status
|
247
|
+
|
248
|
+
h3. Features
|
249
|
+
|
250
|
+
* Fetching of single Resources
|
251
|
+
* Fetching of multiple Resources by specifying a query
|
252
|
+
* Accessing Properties/Attributes directly (on a type/view level)
|
253
|
+
* Type inspection
|
254
|
+
* Attribute inspection
|
255
|
+
* Low Level API (mqlread)
|
256
|
+
* Rails and Merb support
|
257
|
+
* Views on Resources to group Attributes based on the Resource's types
|
258
|
+
|
259
|
+
h3. Roadmap
|
260
|
+
|
261
|
+
# More tests
|
262
|
+
# Write-Support
|
263
|
+
|
264
|
+
Initial thoughts, obviously not up-to-date and not conforming to the current version, are available at "http://wiki.github.com/michael/ken":http://wiki.github.com/michael/ken.
|
data/README.txt
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
= Ken
|
2
|
+
|
3
|
+
* http://www.github.com/michael/ken
|
4
|
+
|
5
|
+
== DESCRIPTION:
|
6
|
+
|
7
|
+
Ken is a Data Layer for Knowledge Representation.
|
8
|
+
|
9
|
+
It's being built to access the Metaweb Services supplied by Freebase.com.
|
10
|
+
Just born, the project’s goals are the provision of a concise API for querying and writing.
|
11
|
+
Therefore it wraps the Metaweb Architecture to smart Ruby Objects (that represent the Metaweb Architecture).
|
12
|
+
|
13
|
+
You can navigate the Freebase Graph using a rubyish syntax.
|
14
|
+
|
15
|
+
You should be able to use this Library as a Data Layer (instead of or in addition to
|
16
|
+
ActiveRecord/DataMapper) for your Web Framework of choice (Merb, Rails).
|
17
|
+
|
18
|
+
|
19
|
+
== FEATURES/PROBLEMS:
|
20
|
+
|
21
|
+
Features
|
22
|
+
|
23
|
+
* Fetching of single Resources
|
24
|
+
* Type inspection
|
25
|
+
* Attributes inspection
|
26
|
+
* Views on Resources to group Attributes based on the Resource's types
|
27
|
+
* Some specs
|
28
|
+
|
29
|
+
Roadmap
|
30
|
+
|
31
|
+
1. Much more specs
|
32
|
+
2. Support for querying of multiple Resources
|
33
|
+
3. Better Type Support
|
34
|
+
4. API for Set Based Browsing (see http://mqlx.com/~david/parallax/)
|
35
|
+
5. Accessing Properties/Attributes directly (e.g. resource.genres )
|
36
|
+
6. Write-Support
|
37
|
+
|
38
|
+
== SYNOPSIS:
|
39
|
+
|
40
|
+
resource = Ken.get('/en/new_order') # => <Resource id="/en/new_order" name="New Order">
|
41
|
+
|
42
|
+
== REQUIREMENTS:
|
43
|
+
|
44
|
+
- Ruby >=1.8.x
|
45
|
+
- RubyGems >=1.2.x
|
46
|
+
- Extlib >=0.9.x
|
47
|
+
|
48
|
+
== INSTALL:
|
49
|
+
|
50
|
+
$ gem sources -a http://gems.github.com (you only have to do this once)
|
51
|
+
$ sudo gem install michael-ken
|
52
|
+
|
53
|
+
== LICENSE:
|
54
|
+
|
55
|
+
(The MIT License)
|
56
|
+
|
57
|
+
Copyright (c) 2009 Michael Aufreiter
|
58
|
+
|
59
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
60
|
+
a copy of this software and associated documentation files (the
|
61
|
+
'Software'), to deal in the Software without restriction, including
|
62
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
63
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
64
|
+
permit persons to whom the Software is furnished to do so, subject to
|
65
|
+
the following conditions:
|
66
|
+
|
67
|
+
The above copyright notice and this permission notice shall be
|
68
|
+
included in all copies or substantial portions of the Software.
|
69
|
+
|
70
|
+
THE SOFTWARE IS PROVIDED 'AS IS', WITHOUT WARRANTY OF ANY KIND,
|
71
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
72
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
73
|
+
IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
|
74
|
+
CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
|
75
|
+
TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
|
76
|
+
SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/Rakefile
ADDED
@@ -0,0 +1,58 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'rake'
|
3
|
+
|
4
|
+
begin
|
5
|
+
require 'jeweler'
|
6
|
+
Jeweler::Tasks.new do |gem|
|
7
|
+
gem.name = "ken"
|
8
|
+
gem.summary = %Q{Ruby API for Accessing the Freebase}
|
9
|
+
gem.email = "ma[at]zive[dot]at"
|
10
|
+
gem.homepage = "http://github.com/michael/ken"
|
11
|
+
gem.authors = ["michael"]
|
12
|
+
gem.add_dependency('extlib')
|
13
|
+
gem.add_dependency('json')
|
14
|
+
gem.add_dependency('addressable')
|
15
|
+
# gem.files = FileList["[A-Z]*.*"]
|
16
|
+
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
|
17
|
+
end
|
18
|
+
|
19
|
+
rescue LoadError
|
20
|
+
puts "Jeweler (or a dependency) not available. Install it with: sudo gem install jeweler"
|
21
|
+
end
|
22
|
+
|
23
|
+
require 'rake/testtask'
|
24
|
+
Rake::TestTask.new(:test) do |test|
|
25
|
+
test.libs << 'lib' << 'test'
|
26
|
+
test.pattern = 'test/**/*_test.rb'
|
27
|
+
test.verbose = true
|
28
|
+
end
|
29
|
+
|
30
|
+
begin
|
31
|
+
require 'rcov/rcovtask'
|
32
|
+
Rcov::RcovTask.new do |test|
|
33
|
+
test.libs << 'test'
|
34
|
+
test.pattern = 'test/**/*_test.rb'
|
35
|
+
test.verbose = true
|
36
|
+
end
|
37
|
+
rescue LoadError
|
38
|
+
task :rcov do
|
39
|
+
abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
task :default => :test
|
44
|
+
|
45
|
+
require 'rake/rdoctask'
|
46
|
+
Rake::RDocTask.new do |rdoc|
|
47
|
+
if File.exist?('VERSION.yml')
|
48
|
+
config = YAML.load(File.read('VERSION.yml'))
|
49
|
+
version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
|
50
|
+
else
|
51
|
+
version = ""
|
52
|
+
end
|
53
|
+
|
54
|
+
rdoc.rdoc_dir = 'rdoc'
|
55
|
+
rdoc.title = "ken #{version}"
|
56
|
+
rdoc.rdoc_files.include('README*')
|
57
|
+
rdoc.rdoc_files.include('lib/**/*.rb')
|
58
|
+
end
|
data/TODO
ADDED
File without changes
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.1.1
|
data/examples/artist.rb
ADDED
@@ -0,0 +1,21 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
EXAMPLES_ROOT = Pathname(__FILE__).dirname.expand_path
|
5
|
+
require EXAMPLES_ROOT.parent + 'lib/ken'
|
6
|
+
|
7
|
+
Ken::Logger.new(STDOUT, :info)
|
8
|
+
Ken::Session.new('http://www.freebase.com', 'ma', 'xxxxx')
|
9
|
+
|
10
|
+
resource = Ken.get('/en/the_police')
|
11
|
+
|
12
|
+
resource.views.each do |view|
|
13
|
+
puts view
|
14
|
+
puts "="*20
|
15
|
+
view.attributes.each do |a|
|
16
|
+
puts a.property
|
17
|
+
puts "-"*20
|
18
|
+
puts a
|
19
|
+
puts # newline
|
20
|
+
end
|
21
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
require 'pathname'
|
2
|
+
require 'rubygems'
|
3
|
+
|
4
|
+
# displays all links related to music/artists
|
5
|
+
# low level api through Ken.session.mqlread is used here
|
6
|
+
|
7
|
+
EXAMPLES_ROOT = Pathname(__FILE__).dirname.expand_path
|
8
|
+
require EXAMPLES_ROOT.parent + 'lib/ken'
|
9
|
+
|
10
|
+
Ken::Session.new('http://www.freebase.com', 'ma', '*****')
|
11
|
+
|
12
|
+
artists = Ken.session.mqlread([{
|
13
|
+
:type => "/music/artist",
|
14
|
+
:id => nil,
|
15
|
+
:"/common/topic/webpage" => [{:uri => nil}],
|
16
|
+
:home_page => [{:uri => nil}],
|
17
|
+
:limit => 50
|
18
|
+
}])
|
19
|
+
|
20
|
+
artists.each do |artist|
|
21
|
+
artist["/common/topic/webpage"].each do |webpage|
|
22
|
+
puts webpage["uri"]
|
23
|
+
end
|
24
|
+
|
25
|
+
artist["home_page"].each do |homepage|
|
26
|
+
puts homepage["uri"]
|
27
|
+
end
|
28
|
+
end
|
data/ken.gemspec
ADDED
@@ -0,0 +1,88 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
|
3
|
+
Gem::Specification.new do |s|
|
4
|
+
s.name = %q{ken}
|
5
|
+
s.version = "0.1.1"
|
6
|
+
|
7
|
+
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
8
|
+
s.authors = ["michael"]
|
9
|
+
s.date = %q{2009-08-12}
|
10
|
+
s.email = %q{ma[at]zive[dot]at}
|
11
|
+
s.extra_rdoc_files = [
|
12
|
+
"LICENSE",
|
13
|
+
"README.textile",
|
14
|
+
"README.txt"
|
15
|
+
]
|
16
|
+
s.files = [
|
17
|
+
".gitignore",
|
18
|
+
"History.txt",
|
19
|
+
"LICENSE",
|
20
|
+
"README.textile",
|
21
|
+
"README.txt",
|
22
|
+
"Rakefile",
|
23
|
+
"TODO",
|
24
|
+
"VERSION",
|
25
|
+
"examples/artist.rb",
|
26
|
+
"examples/artist_links.rb",
|
27
|
+
"ken.gemspec",
|
28
|
+
"lib/ken.rb",
|
29
|
+
"lib/ken/attribute.rb",
|
30
|
+
"lib/ken/collection.rb",
|
31
|
+
"lib/ken/logger.rb",
|
32
|
+
"lib/ken/property.rb",
|
33
|
+
"lib/ken/resource.rb",
|
34
|
+
"lib/ken/session.rb",
|
35
|
+
"lib/ken/type.rb",
|
36
|
+
"lib/ken/util.rb",
|
37
|
+
"lib/ken/view.rb",
|
38
|
+
"rails/init.rb",
|
39
|
+
"tasks/ken.rb",
|
40
|
+
"tasks/spec.rb",
|
41
|
+
"test/fixtures/music_artist.json",
|
42
|
+
"test/fixtures/the_police.json",
|
43
|
+
"test/integration/ken_test.rb",
|
44
|
+
"test/test_helper.rb",
|
45
|
+
"test/unit/attribute_test.rb",
|
46
|
+
"test/unit/property_test.rb",
|
47
|
+
"test/unit/resource_test.rb",
|
48
|
+
"test/unit/session_test.rb",
|
49
|
+
"test/unit/type_test.rb",
|
50
|
+
"test/unit/view_test.rb"
|
51
|
+
]
|
52
|
+
s.homepage = %q{http://github.com/michael/ken}
|
53
|
+
s.rdoc_options = ["--charset=UTF-8"]
|
54
|
+
s.require_paths = ["lib"]
|
55
|
+
s.rubygems_version = %q{1.3.4}
|
56
|
+
s.summary = %q{Ruby API for Accessing the Freebase}
|
57
|
+
s.test_files = [
|
58
|
+
"test/integration/ken_test.rb",
|
59
|
+
"test/test_helper.rb",
|
60
|
+
"test/unit/attribute_test.rb",
|
61
|
+
"test/unit/property_test.rb",
|
62
|
+
"test/unit/resource_test.rb",
|
63
|
+
"test/unit/session_test.rb",
|
64
|
+
"test/unit/type_test.rb",
|
65
|
+
"test/unit/view_test.rb",
|
66
|
+
"examples/artist.rb",
|
67
|
+
"examples/artist_links.rb"
|
68
|
+
]
|
69
|
+
|
70
|
+
if s.respond_to? :specification_version then
|
71
|
+
current_version = Gem::Specification::CURRENT_SPECIFICATION_VERSION
|
72
|
+
s.specification_version = 3
|
73
|
+
|
74
|
+
if Gem::Version.new(Gem::RubyGemsVersion) >= Gem::Version.new('1.2.0') then
|
75
|
+
s.add_runtime_dependency(%q<extlib>, [">= 0"])
|
76
|
+
s.add_runtime_dependency(%q<json>, [">= 0"])
|
77
|
+
s.add_runtime_dependency(%q<addressable>, [">= 0"])
|
78
|
+
else
|
79
|
+
s.add_dependency(%q<extlib>, [">= 0"])
|
80
|
+
s.add_dependency(%q<json>, [">= 0"])
|
81
|
+
s.add_dependency(%q<addressable>, [">= 0"])
|
82
|
+
end
|
83
|
+
else
|
84
|
+
s.add_dependency(%q<extlib>, [">= 0"])
|
85
|
+
s.add_dependency(%q<json>, [">= 0"])
|
86
|
+
s.add_dependency(%q<addressable>, [">= 0"])
|
87
|
+
end
|
88
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Ken
|
2
|
+
class Attribute
|
3
|
+
|
4
|
+
include Extlib::Assertions
|
5
|
+
attr_reader :property
|
6
|
+
|
7
|
+
# initializes a resource by json result
|
8
|
+
def initialize(data, property)
|
9
|
+
assert_kind_of 'data', data, Array
|
10
|
+
assert_kind_of 'property', property, Ken::Property
|
11
|
+
@data, @property = data, property
|
12
|
+
end
|
13
|
+
|
14
|
+
# factory method for creating an attribute instance
|
15
|
+
# @api semipublic
|
16
|
+
def self.create(data, property)
|
17
|
+
Ken::Attribute.new(data, property)
|
18
|
+
end
|
19
|
+
|
20
|
+
# @api public
|
21
|
+
def to_s
|
22
|
+
subject.to_s
|
23
|
+
end
|
24
|
+
|
25
|
+
# @api public
|
26
|
+
def inspect
|
27
|
+
result = "#<Attribute property=\"#{property.id || "nil"}\">"
|
28
|
+
end
|
29
|
+
|
30
|
+
# returns a collection of values
|
31
|
+
# in case of a unique property the array holds just one value
|
32
|
+
# @api public
|
33
|
+
def values
|
34
|
+
subject
|
35
|
+
end
|
36
|
+
|
37
|
+
# unique properties can have at least one value
|
38
|
+
# @api public
|
39
|
+
def unique?
|
40
|
+
@property.unique?
|
41
|
+
end
|
42
|
+
|
43
|
+
# object type properties always link to resources
|
44
|
+
# @api public
|
45
|
+
def object_type?
|
46
|
+
@property.object_type?
|
47
|
+
end
|
48
|
+
|
49
|
+
# returns true if the property is a value type
|
50
|
+
# value type properties refer to simple values like /type/text
|
51
|
+
# @api public
|
52
|
+
def value_type?
|
53
|
+
@property.value_type?
|
54
|
+
end
|
55
|
+
|
56
|
+
private
|
57
|
+
# initializes the subject if used for the first time
|
58
|
+
def subject
|
59
|
+
@subject ||= Ken::Collection.new(@data.map { |r| object_type? ? Ken::Resource.new(r) : r["value"] })
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|