ken 0.1.2

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.
@@ -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
@@ -0,0 +1,3 @@
1
+ === 0.0.1 / not released
2
+
3
+ * Birthday!
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.
@@ -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.
@@ -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.
@@ -0,0 +1,60 @@
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
59
+
60
+ Jeweler::GemcutterTasks.new