ken 0.1.3 → 0.2.0
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/README.textile +61 -1
- data/VERSION +1 -1
- data/ken.gemspec +9 -4
- data/lib/ken/attribute.rb +6 -1
- data/lib/ken/resource.rb +16 -2
- data/lib/ken/session.rb +16 -7
- data/lib/ken/topic.rb +194 -0
- data/lib/ken/view.rb +6 -7
- data/lib/ken.rb +3 -5
- data/test/fixtures/the_police_topic.json +751 -0
- data/test/unit/session_test.rb +6 -2
- data/test/unit/topic_test.rb +92 -0
- metadata +6 -2
data/README.textile
CHANGED
@@ -107,6 +107,9 @@ Freebase itself doesn't.~
|
|
107
107
|
#<Resource id="/guid/9202a8c04000641f8000000002fa20d3" name="Everything's Gone Green">, ... ]
|
108
108
|
# e.g. => ["1980"]
|
109
109
|
end
|
110
|
+
|
111
|
+
# alternatively you can access them directly
|
112
|
+
resource.attribute('/music/artist/album') # => #<Attribute property="/music/artist/album">
|
110
113
|
</code>
|
111
114
|
</pre>
|
112
115
|
|
@@ -223,7 +226,7 @@ h3. Low Level API
|
|
223
226
|
Sometimes you may want to do specific queries instead of inspecting Resources as a whole.
|
224
227
|
In such a case you would want to use Ken's low level API.
|
225
228
|
|
226
|
-
_mqlread_ works like the regular _mqlread service_, except that you are able to pass
|
229
|
+
_mqlread_ works like the regular _mqlread service_, except that you are able to pass Ruby hashes instead of JSON.
|
227
230
|
And you don't have to deal with HTTP, parameter encoding and parsing JSON.
|
228
231
|
|
229
232
|
<pre>
|
@@ -243,6 +246,62 @@ And you don't have to deal with HTTP, parameter encoding and parsing JSON.
|
|
243
246
|
</code>
|
244
247
|
</pre>
|
245
248
|
|
249
|
+
|
250
|
+
h3. Topic API
|
251
|
+
|
252
|
+
Please first have a look at the official "Topic HTTP API documentation":http://www.freebase.com/docs/topic_api .
|
253
|
+
|
254
|
+
The API provides general meta-data such as name, description, links and images for a given topic,
|
255
|
+
as well as all properties directly related to that topic in the graph.
|
256
|
+
The API wraps a series of MQL queries that are needed to get this data, which otherwise must be performed separately.
|
257
|
+
So for gaining common interest information about a specific topic the Topic API is a way faster alternative to mqlread.
|
258
|
+
|
259
|
+
The latest update of Ken provides an easy way to access Freebase Topics using Ruby.
|
260
|
+
As usual Ken wraps the JSON result of the web service to convenient Ruby Objects.
|
261
|
+
|
262
|
+
For now Ken only returns simple properties. Support for so called mediator properties (aka 'CVT') will be added later.
|
263
|
+
To be honest, I just don't know how to wrap them appropriately using the existing Ken object model. Any API ideas are welcome, btw! ;)
|
264
|
+
However, in the meanwhile you can access CVT's by using the plain JSON result returned by the low level Ken.session.topic method.
|
265
|
+
|
266
|
+
|
267
|
+
The API for Topics is quite the same as for Resources.
|
268
|
+
|
269
|
+
<pre>
|
270
|
+
<code>
|
271
|
+
t = Ken::Topic.get("/en/new_order")
|
272
|
+
# => <Topic id="/en/new_order" name="New Order">
|
273
|
+
|
274
|
+
t.types
|
275
|
+
# => [ #<Type id="/music/artist" name="Musical Artist">, #<Type id="/music/musical_group" name="Musical Group">, ... ]
|
276
|
+
|
277
|
+
t.views
|
278
|
+
# => [ #<View type="/music/artist">, #<View type="/music/musical_group">, ... ]
|
279
|
+
|
280
|
+
t.properties
|
281
|
+
# => [ #<Property id="/music/artist/similar_artist" expected_type="/music/artist">, ... ]
|
282
|
+
|
283
|
+
t.attributes
|
284
|
+
# => [ #<Attribute property="/music/artist/similar_artist">, #<Attribute property="/music/artist/album">, ... ]
|
285
|
+
|
286
|
+
</code>
|
287
|
+
</pre>
|
288
|
+
|
289
|
+
Additionally you can access some general meta-data, most importantly the topic's description which otherwise would need an additional request to the raw service.
|
290
|
+
|
291
|
+
<pre>
|
292
|
+
<code>
|
293
|
+
|
294
|
+
t.name # => "New Order"
|
295
|
+
t.description # => "New Order were an English musical group formed in 1980 by Bernard Sumner ... "
|
296
|
+
t.aliases # => [ "NewOrder", "Englandneworder" ]
|
297
|
+
t.webpages # => [ {"url"=>"http://en.wikipedia.org/wiki/index.html?curid=22146", "text"=>"Wikipedia"}, ... ]
|
298
|
+
t.url # => "http://www.freebase.com/view/en/new_order"
|
299
|
+
t.thumbnail => "http://api.freebase.com/api/trans/image_thumb/en/new_order"
|
300
|
+
|
301
|
+
</code>
|
302
|
+
</pre>
|
303
|
+
|
304
|
+
|
246
305
|
h2. Project Status
|
247
306
|
|
248
307
|
h3. Features
|
@@ -255,6 +314,7 @@ h3. Features
|
|
255
314
|
* Low Level API (mqlread)
|
256
315
|
* Rails and Merb support
|
257
316
|
* Views on Resources to group Attributes based on the Resource's types
|
317
|
+
* Accessing Topics using the new Freebase Topic API
|
258
318
|
|
259
319
|
h3. Roadmap
|
260
320
|
|
data/VERSION
CHANGED
@@ -1 +1 @@
|
|
1
|
-
0.
|
1
|
+
0.2.0
|
data/ken.gemspec
CHANGED
@@ -1,15 +1,15 @@
|
|
1
1
|
# Generated by jeweler
|
2
|
-
# DO NOT EDIT THIS FILE
|
3
|
-
# Instead, edit Jeweler::Tasks in Rakefile, and run
|
2
|
+
# DO NOT EDIT THIS FILE DIRECTLY
|
3
|
+
# Instead, edit Jeweler::Tasks in Rakefile, and run the gemspec command
|
4
4
|
# -*- encoding: utf-8 -*-
|
5
5
|
|
6
6
|
Gem::Specification.new do |s|
|
7
7
|
s.name = %q{ken}
|
8
|
-
s.version = "0.
|
8
|
+
s.version = "0.2.0"
|
9
9
|
|
10
10
|
s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
|
11
11
|
s.authors = ["michael"]
|
12
|
-
s.date = %q{2009-
|
12
|
+
s.date = %q{2009-11-02}
|
13
13
|
s.email = %q{ma[at]zive[dot]at}
|
14
14
|
s.extra_rdoc_files = [
|
15
15
|
"LICENSE",
|
@@ -35,6 +35,7 @@ Gem::Specification.new do |s|
|
|
35
35
|
"lib/ken/property.rb",
|
36
36
|
"lib/ken/resource.rb",
|
37
37
|
"lib/ken/session.rb",
|
38
|
+
"lib/ken/topic.rb",
|
38
39
|
"lib/ken/type.rb",
|
39
40
|
"lib/ken/util.rb",
|
40
41
|
"lib/ken/view.rb",
|
@@ -43,12 +44,14 @@ Gem::Specification.new do |s|
|
|
43
44
|
"tasks/spec.rb",
|
44
45
|
"test/fixtures/music_artist.json",
|
45
46
|
"test/fixtures/the_police.json",
|
47
|
+
"test/fixtures/the_police_topic.json",
|
46
48
|
"test/integration/ken_test.rb",
|
47
49
|
"test/test_helper.rb",
|
48
50
|
"test/unit/attribute_test.rb",
|
49
51
|
"test/unit/property_test.rb",
|
50
52
|
"test/unit/resource_test.rb",
|
51
53
|
"test/unit/session_test.rb",
|
54
|
+
"test/unit/topic_test.rb",
|
52
55
|
"test/unit/type_test.rb",
|
53
56
|
"test/unit/view_test.rb"
|
54
57
|
]
|
@@ -64,6 +67,7 @@ Gem::Specification.new do |s|
|
|
64
67
|
"test/unit/property_test.rb",
|
65
68
|
"test/unit/resource_test.rb",
|
66
69
|
"test/unit/session_test.rb",
|
70
|
+
"test/unit/topic_test.rb",
|
67
71
|
"test/unit/type_test.rb",
|
68
72
|
"test/unit/view_test.rb",
|
69
73
|
"examples/artist.rb",
|
@@ -89,3 +93,4 @@ Gem::Specification.new do |s|
|
|
89
93
|
s.add_dependency(%q<addressable>, [">= 0"])
|
90
94
|
end
|
91
95
|
end
|
96
|
+
|
data/lib/ken/attribute.rb
CHANGED
@@ -1,6 +1,5 @@
|
|
1
1
|
module Ken
|
2
2
|
class Attribute
|
3
|
-
|
4
3
|
include Extlib::Assertions
|
5
4
|
attr_reader :property
|
6
5
|
|
@@ -53,6 +52,12 @@ module Ken
|
|
53
52
|
@property.value_type?
|
54
53
|
end
|
55
54
|
|
55
|
+
# type, which attribute values of that property are expected to have
|
56
|
+
# @api public
|
57
|
+
def expected_type
|
58
|
+
@property.expected_type
|
59
|
+
end
|
60
|
+
|
56
61
|
private
|
57
62
|
# initializes the subject if used for the first time
|
58
63
|
def subject
|
data/lib/ken/resource.rb
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
module Ken
|
2
2
|
class Resource
|
3
3
|
include Extlib::Assertions
|
4
|
-
|
4
|
+
extend Extlib::Assertions
|
5
5
|
attr_reader :data
|
6
6
|
|
7
7
|
# initializes a resource using a json result
|
@@ -11,6 +11,20 @@ module Ken
|
|
11
11
|
@data_fechted = data["/type/reflect/any_master"] != nil
|
12
12
|
end
|
13
13
|
|
14
|
+
# Executes an Mql Query against the Freebase API and returns the result wrapped
|
15
|
+
# in a <tt>Resource</tt> Object.
|
16
|
+
#
|
17
|
+
# == Examples
|
18
|
+
#
|
19
|
+
# Ken::Resource.get('/en/the_police') => #<Resource id="/en/the_police" name="The Police">
|
20
|
+
# @api public
|
21
|
+
def self.get(id)
|
22
|
+
assert_kind_of 'id', id, String
|
23
|
+
result = Ken.session.mqlread(FETCH_DATA_QUERY.merge!(:id => id))
|
24
|
+
raise ResourceNotFound unless result
|
25
|
+
Ken::Resource.new(result)
|
26
|
+
end
|
27
|
+
|
14
28
|
# resource id
|
15
29
|
# @api public
|
16
30
|
def id
|
@@ -123,7 +137,7 @@ module Ken
|
|
123
137
|
fetch_data unless data_fetched?
|
124
138
|
# master & value attributes
|
125
139
|
raw_attributes = Ken::Util.convert_hash(@data["/type/reflect/any_master"])
|
126
|
-
raw_attributes.merge!(Ken::Util.convert_hash(@data["/type/reflect/any_value"]))
|
140
|
+
raw_attributes.merge!(Ken::Util.convert_hash(@data["/type/reflect/any_value"]))
|
127
141
|
@attributes = {}
|
128
142
|
raw_attributes.each_pair do |a, d|
|
129
143
|
properties.select { |p| p.id == a}.each do |p|
|
data/lib/ken/session.rb
CHANGED
@@ -19,6 +19,7 @@ module Ken
|
|
19
19
|
class AttributeNotFound < StandardError ; end
|
20
20
|
class PropertyNotFound < StandardError ; end
|
21
21
|
class ResourceNotFound < StandardError ; end
|
22
|
+
class TopicNotFound < StandardError ; end
|
22
23
|
class ViewNotFound < StandardError ; end
|
23
24
|
|
24
25
|
# partially taken from chris eppstein's freebase api
|
@@ -48,7 +49,8 @@ module Ken
|
|
48
49
|
:blurb => '/api/trans/blurb',
|
49
50
|
:raw => '/api/trans/raw',
|
50
51
|
:login => '/api/account/login',
|
51
|
-
:upload => '/api/service/upload'
|
52
|
+
:upload => '/api/service/upload',
|
53
|
+
:topic => '/experimental/topic',
|
52
54
|
}
|
53
55
|
|
54
56
|
# get the service url for the specified service.
|
@@ -94,29 +96,36 @@ module Ken
|
|
94
96
|
end
|
95
97
|
|
96
98
|
def raw_content(id, options = {})
|
97
|
-
puts raw_service_url
|
98
99
|
response = http_request raw_service_url+id, options
|
99
100
|
Ken.logger.info "<<< Received Raw Content Response: #{response}"
|
100
101
|
response
|
101
102
|
end
|
102
103
|
|
103
104
|
def blurb_content(id, options = {})
|
104
|
-
puts blurb_service_url
|
105
105
|
response = http_request blurb_service_url+id, options
|
106
106
|
Ken.logger.info "<<< Received Blurb Content Response: #{response}"
|
107
107
|
response
|
108
108
|
end
|
109
|
+
|
110
|
+
def topic(id, options = {})
|
111
|
+
options.merge!({:id => id})
|
112
|
+
|
113
|
+
response = http_request topic_service_url+"/standard", options
|
114
|
+
result = JSON.parse response
|
115
|
+
inner = result[id]
|
116
|
+
handle_read_error(inner)
|
117
|
+
Ken.logger.info "<<< Received Topic Response: #{inner['result'].inspect}"
|
118
|
+
inner['result']
|
119
|
+
end
|
109
120
|
|
110
121
|
protected
|
111
122
|
# returns parsed json response from freebase mqlread service
|
112
123
|
def get_query_response(query, cursor=nil)
|
113
|
-
envelope = { :qname => {:query => query }}
|
124
|
+
envelope = { :qname => {:query => query, :escape => false }}
|
114
125
|
envelope[:qname][:cursor] = cursor if cursor
|
115
126
|
|
116
127
|
response = http_request mqlread_service_url, :queries => envelope.to_json
|
117
|
-
|
118
128
|
result = JSON.parse response
|
119
|
-
|
120
129
|
inner = result['qname']
|
121
130
|
handle_read_error(inner)
|
122
131
|
Ken.logger.info "<<< Received Response: #{inner['result'].inspect}"
|
@@ -132,7 +141,7 @@ module Ken
|
|
132
141
|
def http_request(url, parameters = {})
|
133
142
|
params = params_to_string(parameters)
|
134
143
|
url << '?'+params unless params !~ /\S/
|
135
|
-
|
144
|
+
|
136
145
|
return Net::HTTP.get_response(::URI.parse(url)).body
|
137
146
|
|
138
147
|
fname = "#{MD5.md5(params)}.mql"
|
data/lib/ken/topic.rb
ADDED
@@ -0,0 +1,194 @@
|
|
1
|
+
module Ken
|
2
|
+
class Topic
|
3
|
+
include Extlib::Assertions
|
4
|
+
extend Extlib::Assertions
|
5
|
+
|
6
|
+
attr_reader :data
|
7
|
+
|
8
|
+
# initializes a topic using a json result
|
9
|
+
def initialize(data)
|
10
|
+
assert_kind_of 'data', data, Hash
|
11
|
+
@data = data
|
12
|
+
@schema_loaded, @attributes_loaded = false, false
|
13
|
+
end
|
14
|
+
|
15
|
+
# Retrieves a topic using the Topic API by Freebase
|
16
|
+
# returns a <tt>Topic</tt> Object.
|
17
|
+
#
|
18
|
+
# == Examples
|
19
|
+
#
|
20
|
+
# Ken::Topic.get('/en/the_police') => #<Topic id="/en/the_police" name="The Police">
|
21
|
+
# @api public
|
22
|
+
def self.get(id)
|
23
|
+
assert_kind_of 'id', id, String
|
24
|
+
result = Ken.session.topic(id)
|
25
|
+
raise TopicNotFound unless result
|
26
|
+
Ken::Topic.new(result)
|
27
|
+
end
|
28
|
+
|
29
|
+
# topic id
|
30
|
+
# @api public
|
31
|
+
def id
|
32
|
+
@data["id"] || ""
|
33
|
+
end
|
34
|
+
|
35
|
+
# topic aliases
|
36
|
+
def aliases
|
37
|
+
@data["alias"]
|
38
|
+
end
|
39
|
+
|
40
|
+
# topic freebase url
|
41
|
+
def url
|
42
|
+
@data["url"]
|
43
|
+
end
|
44
|
+
|
45
|
+
# topic name
|
46
|
+
# @api public
|
47
|
+
def name
|
48
|
+
text
|
49
|
+
end
|
50
|
+
|
51
|
+
# topic description
|
52
|
+
# @api public
|
53
|
+
def description
|
54
|
+
@data["description"]
|
55
|
+
end
|
56
|
+
|
57
|
+
# topic text
|
58
|
+
# @api public
|
59
|
+
def text
|
60
|
+
@data["text"]
|
61
|
+
end
|
62
|
+
|
63
|
+
# topic thumbnail
|
64
|
+
def thumbnail
|
65
|
+
@data["thumbnail"]
|
66
|
+
end
|
67
|
+
|
68
|
+
# @api public
|
69
|
+
def to_s
|
70
|
+
name || id || ""
|
71
|
+
end
|
72
|
+
|
73
|
+
# @api public
|
74
|
+
def inspect
|
75
|
+
result = "#<Topic id=\"#{id}\" name=\"#{name || "nil"}\">"
|
76
|
+
end
|
77
|
+
|
78
|
+
# topic webpages
|
79
|
+
# currently returned as an array of hashes containing the keys "text" and "url"
|
80
|
+
# that hashes may be wrapped into a Webpage class later
|
81
|
+
# @api public
|
82
|
+
def webpages
|
83
|
+
@data["webpage"]
|
84
|
+
end
|
85
|
+
|
86
|
+
# returns all assigned types
|
87
|
+
# @api public
|
88
|
+
def types
|
89
|
+
load_schema! unless schema_loaded?
|
90
|
+
@types
|
91
|
+
end
|
92
|
+
|
93
|
+
# returns individual type based on the requested type id
|
94
|
+
# @api public
|
95
|
+
def type(type)
|
96
|
+
types.each { |t| return t if t.id =~ /^#{Regexp.escape(type)}$/}
|
97
|
+
nil
|
98
|
+
end
|
99
|
+
|
100
|
+
# returns all the properties from all assigned types
|
101
|
+
# @api public
|
102
|
+
def properties
|
103
|
+
@properties = Ken::Collection.new
|
104
|
+
types.each do |type|
|
105
|
+
@properties.concat(type.properties)
|
106
|
+
end
|
107
|
+
@properties
|
108
|
+
end
|
109
|
+
|
110
|
+
# returns all attributes for every type the topic is an instance of
|
111
|
+
# @api public
|
112
|
+
def attributes
|
113
|
+
load_attributes! unless attributes_loaded?
|
114
|
+
@attributes.values
|
115
|
+
end
|
116
|
+
|
117
|
+
# returns all available views based on the assigned types
|
118
|
+
# @api public
|
119
|
+
def views
|
120
|
+
@views ||= Ken::Collection.new(types.map { |type| Ken::View.new(self, type) })
|
121
|
+
end
|
122
|
+
|
123
|
+
# returns individual view based on the requested type id
|
124
|
+
# @api public
|
125
|
+
def view(type)
|
126
|
+
views.each { |v| return v if v.type.id =~ /^#{Regexp.escape(type)}$/}
|
127
|
+
nil
|
128
|
+
end
|
129
|
+
|
130
|
+
|
131
|
+
# search for an attribute by name and return it
|
132
|
+
# @api public
|
133
|
+
def attribute(name)
|
134
|
+
attributes.each { |a| return a if a.property.id == name }
|
135
|
+
nil
|
136
|
+
end
|
137
|
+
|
138
|
+
# returns true if type information is already loaded
|
139
|
+
# @api public
|
140
|
+
def schema_loaded?
|
141
|
+
@schema_loaded
|
142
|
+
end
|
143
|
+
|
144
|
+
# returns true if attributes are already loaded
|
145
|
+
# @api public
|
146
|
+
def attributes_loaded?
|
147
|
+
@attributes_loaded
|
148
|
+
end
|
149
|
+
|
150
|
+
private
|
151
|
+
|
152
|
+
# loads the full set of attributes using reflection
|
153
|
+
# information is extracted from master, value and reverse attributes
|
154
|
+
# @api private
|
155
|
+
def load_attributes!
|
156
|
+
load_schema! unless schema_loaded?
|
157
|
+
|
158
|
+
@attributes = {}
|
159
|
+
@data["properties"].each do |id, data|
|
160
|
+
# skip mediator properties for now
|
161
|
+
if !data["properties"]
|
162
|
+
values = []
|
163
|
+
data["values"].each do |value|
|
164
|
+
values << { "id" => value["id"], "name" => value["text"], "value" => value["text"] }
|
165
|
+
end
|
166
|
+
@attributes[id] = Ken::Attribute.create(values, properties.select { |p| p.id == id }.first)
|
167
|
+
end
|
168
|
+
end
|
169
|
+
|
170
|
+
@attributes_loaded = true
|
171
|
+
end
|
172
|
+
|
173
|
+
# loads the topic's metainfo
|
174
|
+
# @api private
|
175
|
+
def load_schema!
|
176
|
+
result = {}
|
177
|
+
|
178
|
+
@data["type"].each do |type|
|
179
|
+
result[type["id"]] = { "id" => type["id"], "name" => type["text"], "properties" => [] }
|
180
|
+
end
|
181
|
+
@data["properties"].each do |id, data|
|
182
|
+
result[id.gsub(/\/\w*$/, "")]["properties"] << {
|
183
|
+
"expected_type" => data["expected_type"]["id"],
|
184
|
+
"id" => id,
|
185
|
+
"name" => data["text"],
|
186
|
+
"unique" => true
|
187
|
+
}
|
188
|
+
end
|
189
|
+
@types = Ken::Collection.new(result.values.map { |type| Ken::Type.new(type) })
|
190
|
+
@schema_loaded = true
|
191
|
+
end
|
192
|
+
|
193
|
+
end # class Topic
|
194
|
+
end # module Ken
|
data/lib/ken/view.rb
CHANGED
@@ -1,15 +1,14 @@
|
|
1
|
-
# provides an interface to view a resource as a specific type
|
1
|
+
# provides an interface to view a subject (resource or topic) as a specific type
|
2
2
|
# provides an interface for working with attributes, properties
|
3
3
|
module Ken
|
4
4
|
class View
|
5
5
|
|
6
6
|
include Extlib::Assertions
|
7
7
|
|
8
|
-
# initializes a resource by json result
|
9
|
-
def initialize(
|
10
|
-
assert_kind_of 'resource', resource, Ken::Resource
|
8
|
+
# initializes a subject (resource or topic) by json result
|
9
|
+
def initialize(subject, type)
|
11
10
|
assert_kind_of 'type', type, Ken::Type
|
12
|
-
@
|
11
|
+
@subject, @type = subject, type
|
13
12
|
end
|
14
13
|
|
15
14
|
# @api public
|
@@ -31,7 +30,7 @@ module Ken
|
|
31
30
|
# returns attributes which are member of the view's type
|
32
31
|
# @api public
|
33
32
|
def attributes
|
34
|
-
@
|
33
|
+
@subject.attributes.select { |a| a.property.type == @type}
|
35
34
|
end
|
36
35
|
|
37
36
|
# search for an attribute by name and return it
|
@@ -44,7 +43,7 @@ module Ken
|
|
44
43
|
# returns properties which are member of the view's type
|
45
44
|
# @api public
|
46
45
|
def properties
|
47
|
-
@
|
46
|
+
@subject.properties.select { |p| p.type == @type}
|
48
47
|
end
|
49
48
|
|
50
49
|
# delegate to attribute
|
data/lib/ken.rb
CHANGED
@@ -8,13 +8,14 @@ require 'addressable/uri'
|
|
8
8
|
dir = Pathname(__FILE__).dirname.expand_path + 'ken'
|
9
9
|
|
10
10
|
require dir + 'util'
|
11
|
+
require dir + 'session'
|
11
12
|
require dir + 'resource'
|
12
13
|
require dir + 'type'
|
13
14
|
require dir + 'view'
|
14
15
|
require dir + 'property'
|
15
16
|
require dir + 'attribute'
|
16
17
|
require dir + 'collection'
|
17
|
-
require dir + '
|
18
|
+
require dir + 'topic'
|
18
19
|
require dir + 'logger'
|
19
20
|
|
20
21
|
# init logger as soon as the library is required
|
@@ -117,10 +118,7 @@ module Ken
|
|
117
118
|
# Ken.get('/en/the_police') => #<Resource id="/en/the_police" name="The Police">
|
118
119
|
# @api public
|
119
120
|
def self.get(id)
|
120
|
-
|
121
|
-
result = Ken.session.mqlread(FETCH_DATA_QUERY.merge!(:id => id))
|
122
|
-
raise ResourceNotFound unless result
|
123
|
-
Ken::Resource.new(result)
|
121
|
+
Ken::Resource.get(id)
|
124
122
|
end
|
125
123
|
|
126
124
|
end # module Ken
|