freeb 0.0.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/MIT-LICENSE +20 -0
- data/README.md +327 -0
- data/Rakefile +38 -0
- data/app/models/freebase_model_relation.rb +6 -0
- data/app/models/freebase_topic.rb +9 -0
- data/app/models/freebase_topic_relation.rb +6 -0
- data/db/migrate/20121226072811_create_freebase_topics.rb +12 -0
- data/db/migrate/20121226073507_create_freebase_topic_relations.rb +15 -0
- data/db/migrate/20121226185919_create_freebase_model_relations.rb +15 -0
- data/lib/freeb.rb +28 -0
- data/lib/freeb/api.rb +91 -0
- data/lib/freeb/config.rb +25 -0
- data/lib/freeb/converter.rb +60 -0
- data/lib/freeb/dsl.rb +25 -0
- data/lib/freeb/engine.rb +5 -0
- data/lib/freeb/exceptions.rb +3 -0
- data/lib/freeb/model_config.rb +172 -0
- data/lib/freeb/models.rb +175 -0
- data/lib/freeb/topic.rb +57 -0
- data/lib/freeb/version.rb +3 -0
- data/lib/generators/freeb/migration_generator.rb +24 -0
- data/lib/generators/freeb/templates/migration.rb +13 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/models/music_artist.rb +7 -0
- data/test/dummy/app/models/us_state.rb +6 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +37 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/freeb.rb +3 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +58 -0
- data/test/dummy/db/migrate/20121227043946_create_freebase_topics.freeb.rb +13 -0
- data/test/dummy/db/migrate/20121227043947_create_freebase_topic_relations.freeb.rb +16 -0
- data/test/dummy/db/migrate/20121227043948_create_freebase_model_relations.freeb.rb +16 -0
- data/test/dummy/db/migrate/20121227044336_create_music_artists.rb +15 -0
- data/test/dummy/db/migrate/20121227170033_create_us_states.rb +13 -0
- data/test/dummy/db/schema.rb +71 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/spec/freeb_spec.rb +32 -0
- data/test/dummy/spec/music_artist_spec.rb +58 -0
- data/test/dummy/spec/spec_helper.rb +38 -0
- data/test/dummy/spec/us_state_spec.rb +11 -0
- data/test/freeb_test.rb +7 -0
- data/test/test_helper.rb +15 -0
- metadata +217 -0
data/lib/freeb.rb
ADDED
@@ -0,0 +1,28 @@
|
|
1
|
+
module Freeb
|
2
|
+
def self.config
|
3
|
+
yield Freeb::Config
|
4
|
+
end
|
5
|
+
|
6
|
+
def self.get(freebase_id)
|
7
|
+
API.get(freebase_id)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.search(params)
|
11
|
+
API.search(params)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.topic(mql)
|
15
|
+
API.topic(mql)
|
16
|
+
end
|
17
|
+
|
18
|
+
def self.mqlread(mql)
|
19
|
+
API.mqlread(mql)
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
directory = File.dirname(File.absolute_path(__FILE__))
|
24
|
+
Dir.glob("#{directory}/freeb/*.rb") { |file| require file }
|
25
|
+
Dir.glob("#{directory}/generators/freeb/*.rb") { |file| require file }
|
26
|
+
Dir.glob("#{directory}/../app/models/*.rb") { |file| require file }
|
27
|
+
|
28
|
+
ActiveRecord::Base.extend Freeb::Models::ClassMethods
|
data/lib/freeb/api.rb
ADDED
@@ -0,0 +1,91 @@
|
|
1
|
+
require 'httparty'
|
2
|
+
require 'uri'
|
3
|
+
require 'json'
|
4
|
+
|
5
|
+
module Freeb
|
6
|
+
class API
|
7
|
+
@base_url = "https://www.googleapis.com/freebase/v1/"
|
8
|
+
|
9
|
+
def self.get(id)
|
10
|
+
mql = {
|
11
|
+
"id" => id,
|
12
|
+
"name" => nil
|
13
|
+
}
|
14
|
+
topic(mql)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.topic(mql)
|
18
|
+
result = mqlread(mql)
|
19
|
+
return nil if result.blank?
|
20
|
+
if result.is_a?(Array)
|
21
|
+
result.collect { |r| Topic.new(r) }
|
22
|
+
else
|
23
|
+
Topic.new(result)
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.search(params)
|
28
|
+
log "Search Request: #{params}"
|
29
|
+
url = "#{@base_url}search"
|
30
|
+
result = get_result(url, params)
|
31
|
+
log "Search Response: #{result}"
|
32
|
+
result["result"].collect { |r| Topic.new(r) }
|
33
|
+
end
|
34
|
+
|
35
|
+
def self.mqlread(mql)
|
36
|
+
log "MQL Request: #{mql}"
|
37
|
+
url = "#{@base_url}mqlread"
|
38
|
+
result = get_result(url, :query => mql.to_json)
|
39
|
+
log "MQL Response: #{result}"
|
40
|
+
return nil if result["result"].blank?
|
41
|
+
result["result"]
|
42
|
+
end
|
43
|
+
|
44
|
+
def self.description(id)
|
45
|
+
url = "#{@base_url}text#{id}"
|
46
|
+
result = get_result(url, nil)
|
47
|
+
result["result"]
|
48
|
+
end
|
49
|
+
|
50
|
+
def self.get_result(url, params={})
|
51
|
+
unless params.nil?
|
52
|
+
params[:key] = Config.settings[:api_key] unless Config.settings[:api_key].blank?
|
53
|
+
url = "#{url}?#{params.to_query}"
|
54
|
+
end
|
55
|
+
if Config.settings[:cache][:is_active]
|
56
|
+
cache_key = cache_key_for_url(url)
|
57
|
+
result = Rails.cache.read(cache_key)
|
58
|
+
if result
|
59
|
+
log "Read cache for #{url}"
|
60
|
+
result
|
61
|
+
else
|
62
|
+
result = get_uncached_result(url)
|
63
|
+
Rails.cache.write(cache_key, result, :expires_in => Config.settings[:cache][:expires_in])
|
64
|
+
log "Wrote cache for #{url}"
|
65
|
+
result
|
66
|
+
end
|
67
|
+
else
|
68
|
+
get_uncached_result(url)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def self.get_uncached_result(url)
|
73
|
+
response = HTTParty.get(url)
|
74
|
+
if response.code == 200
|
75
|
+
return JSON.parse(response.body)
|
76
|
+
end
|
77
|
+
raise ResponseException, "Freebase Response #{response.code}: #{JSON.parse(response.body).inspect}"
|
78
|
+
nil
|
79
|
+
end
|
80
|
+
|
81
|
+
private
|
82
|
+
|
83
|
+
def self.cache_key_for_url(url)
|
84
|
+
{:gem => "Freeb", :class => "API", :key => "get_result", :url => url}
|
85
|
+
end
|
86
|
+
|
87
|
+
def self.log(message)
|
88
|
+
Rails.logger.debug("Freeb: #{message}")
|
89
|
+
end
|
90
|
+
end
|
91
|
+
end
|
data/lib/freeb/config.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
require 'active_support/core_ext/numeric'
|
2
|
+
|
3
|
+
module Freeb
|
4
|
+
class Config
|
5
|
+
class << self
|
6
|
+
attr_reader :settings
|
7
|
+
end
|
8
|
+
|
9
|
+
@settings = {
|
10
|
+
:api_key => nil,
|
11
|
+
:cache => {
|
12
|
+
:is_active => true,
|
13
|
+
:expires_in => 1.day
|
14
|
+
}
|
15
|
+
}
|
16
|
+
|
17
|
+
def self.api_key(api_key)
|
18
|
+
@settings[:api_key] = api_key
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.cache(options)
|
22
|
+
@settings[:cache].merge!(options)
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,60 @@
|
|
1
|
+
module Freeb
|
2
|
+
class Converter
|
3
|
+
def self.freebase_id_to_topic(freebase_id, model)
|
4
|
+
config = ModelConfig.get(model)
|
5
|
+
query_properties = ModelConfig.get_query_properties(model)
|
6
|
+
mql = {
|
7
|
+
:id => freebase_id,
|
8
|
+
:type => config[:type],
|
9
|
+
:name => nil
|
10
|
+
}.merge(query_properties)
|
11
|
+
API.topic(mql)
|
12
|
+
end
|
13
|
+
|
14
|
+
def self.name_to_topic(name, model)
|
15
|
+
config = ModelConfig.get(model)
|
16
|
+
query_properties = ModelConfig.get_query_properties(model)
|
17
|
+
mql = {
|
18
|
+
:id => nil,
|
19
|
+
:type => config[:type],
|
20
|
+
:name => name
|
21
|
+
}.merge(query_properties)
|
22
|
+
API.topic(mql)
|
23
|
+
end
|
24
|
+
|
25
|
+
def self.topic_to_record_attributes(topic, model)
|
26
|
+
config = ModelConfig.get(model)
|
27
|
+
attributes = {
|
28
|
+
:freebase_id => topic.id,
|
29
|
+
:name => topic.name
|
30
|
+
}
|
31
|
+
config[:properties].each do |key, property_config|
|
32
|
+
if property_config[:method].blank?
|
33
|
+
attributes[key] = topic[property_config[:id]]
|
34
|
+
else
|
35
|
+
attributes[key] = model.send(property_config[:method], topic)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
config[:topics].each do |key, topic_config|
|
39
|
+
attributes[key] = topic[topic_config[:id]].collect { |hash| topic_hash_to_freebase_topic_record(hash) }
|
40
|
+
end
|
41
|
+
config[:has_many].each do |key, association_config|
|
42
|
+
records = topic[association_config[:id]]
|
43
|
+
model = association_config[:class_name].constantize
|
44
|
+
attributes[key] = records.collect { |hash|
|
45
|
+
topic = Topic.new(hash)
|
46
|
+
hash = topic_to_record_attributes(topic, model)
|
47
|
+
model.ffind_or_create(hash) }
|
48
|
+
end
|
49
|
+
attributes
|
50
|
+
end
|
51
|
+
|
52
|
+
def self.topic_hash_to_freebase_topic_record(topic_hash)
|
53
|
+
hash = {
|
54
|
+
:freebase_id => topic_hash["id"],
|
55
|
+
:name => topic_hash["name"]
|
56
|
+
}
|
57
|
+
record = FreebaseTopic.find_or_create_by_freebase_id(hash)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
data/lib/freeb/dsl.rb
ADDED
@@ -0,0 +1,25 @@
|
|
1
|
+
module Freeb
|
2
|
+
class DSL
|
3
|
+
attr_reader :config
|
4
|
+
|
5
|
+
def initialize
|
6
|
+
@config = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def type(value)
|
10
|
+
@config[:type] = value
|
11
|
+
end
|
12
|
+
|
13
|
+
def properties(*args)
|
14
|
+
@config[:properties] = args
|
15
|
+
end
|
16
|
+
|
17
|
+
def topics(*args)
|
18
|
+
@config[:topics] = args
|
19
|
+
end
|
20
|
+
|
21
|
+
def has_many(*args)
|
22
|
+
@config[:has_many] = args
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
data/lib/freeb/engine.rb
ADDED
@@ -0,0 +1,172 @@
|
|
1
|
+
module Freeb
|
2
|
+
class ModelConfig
|
3
|
+
@models = {}
|
4
|
+
|
5
|
+
def self.register(model, options)
|
6
|
+
key = model_to_key(model)
|
7
|
+
@models[key] = normalize_options(options)
|
8
|
+
end
|
9
|
+
|
10
|
+
def self.get(model)
|
11
|
+
key = model_to_key(model)
|
12
|
+
@models[key]
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.get_query_properties(model)
|
16
|
+
config = get(model)
|
17
|
+
query_properties = {}
|
18
|
+
raise "Empty Freeb config for #{model}" if config.blank?
|
19
|
+
query_properties.merge!(config[:properties].inject({}) { |h, (k, property)| h[property[:id]] = nil; h })
|
20
|
+
query_properties.delete("description")
|
21
|
+
query_properties.merge!(config[:topics].inject({}) { |h, (k, topic)| h[topic[:id]] = [{:id => nil, :name => nil}]; h })
|
22
|
+
query_properties.merge!(get_has_many_properties(model))
|
23
|
+
query_properties
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.get_has_many_properties(model)
|
27
|
+
config = get(model)
|
28
|
+
properties = {}
|
29
|
+
config[:has_many].each do |key, association|
|
30
|
+
association_class = association[:class_name].classify.constantize
|
31
|
+
association_class_config = get(association_class)
|
32
|
+
association_properties = {:id => nil, :name => nil}
|
33
|
+
association_properties.merge!(get_query_properties(association_class))
|
34
|
+
key = association[:id]
|
35
|
+
properties[key] = [association_properties]
|
36
|
+
end
|
37
|
+
properties
|
38
|
+
end
|
39
|
+
|
40
|
+
def self.get_migration_properties(model)
|
41
|
+
config = get(model)
|
42
|
+
schema = Freeb.mqlread({
|
43
|
+
:name => nil,
|
44
|
+
:id => config[:type],
|
45
|
+
:type => [{:id => "/type/type"}],
|
46
|
+
"!/type/property/schema" => [{"/type/property/expected_type" => nil, "id" => nil, "name" => nil}]
|
47
|
+
})
|
48
|
+
property_types = {}
|
49
|
+
schema["!/type/property/schema"].each do |property|
|
50
|
+
property_types[property["id"]] = property["/type/property/expected_type"]
|
51
|
+
end
|
52
|
+
config[:properties].collect do |key, property|
|
53
|
+
expected_type = property_types[property[:id]]
|
54
|
+
type = case expected_type
|
55
|
+
when "/type/boolean"
|
56
|
+
:boolean
|
57
|
+
when "/type/datetime"
|
58
|
+
:datetime
|
59
|
+
when "/type/float"
|
60
|
+
:float
|
61
|
+
when "/type/int"
|
62
|
+
:integer
|
63
|
+
when "/type/text"
|
64
|
+
:text
|
65
|
+
else
|
66
|
+
:string
|
67
|
+
end
|
68
|
+
if property[:id] == "description"
|
69
|
+
type = "text"
|
70
|
+
end
|
71
|
+
{ :key => key, :type => type }
|
72
|
+
end
|
73
|
+
end
|
74
|
+
|
75
|
+
def self.model_to_key(model)
|
76
|
+
model.name.underscore.to_sym
|
77
|
+
end
|
78
|
+
|
79
|
+
def self.normalize_options(options)
|
80
|
+
normalize_properties(options)
|
81
|
+
normalize_topics(options)
|
82
|
+
normalize_has_many(options)
|
83
|
+
options
|
84
|
+
end
|
85
|
+
|
86
|
+
def self.normalize_properties(options)
|
87
|
+
properties = {}
|
88
|
+
options[:properties].flatten(1).each do |property|
|
89
|
+
if property.is_a?(String)
|
90
|
+
properties[property.to_sym] = {
|
91
|
+
:key => property,
|
92
|
+
:id => key_to_id(property, options)
|
93
|
+
}
|
94
|
+
elsif property.is_a?(Hash)
|
95
|
+
property.each do |key, value|
|
96
|
+
if value.is_a?(String)
|
97
|
+
properties[key.to_sym] = {
|
98
|
+
:key => value,
|
99
|
+
:id => key_to_id(value, options)
|
100
|
+
}
|
101
|
+
elsif value.is_a?(Hash)
|
102
|
+
defaults = {
|
103
|
+
:key => key,
|
104
|
+
:id => key_to_id(key, options)
|
105
|
+
}
|
106
|
+
properties[key.to_sym] = defaults.merge(value)
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
110
|
+
end
|
111
|
+
options[:properties] = properties
|
112
|
+
end
|
113
|
+
|
114
|
+
def self.normalize_topics(options)
|
115
|
+
topics = {}
|
116
|
+
options[:topics] = [options[:topics]] if !options[:topics].is_a?(Array)
|
117
|
+
options[:topics].each do |topic|
|
118
|
+
if topic.is_a?(String) || topic.is_a?(Symbol)
|
119
|
+
topic = topic.to_s
|
120
|
+
topics[topic.to_sym] = {
|
121
|
+
:key => topic,
|
122
|
+
:id => key_to_id(topic, options)
|
123
|
+
}
|
124
|
+
elsif topic.is_a?(Hash)
|
125
|
+
topic.each do |key, value|
|
126
|
+
topics[key.to_sym] = {
|
127
|
+
:key => key,
|
128
|
+
:id => key_to_id(value, options)
|
129
|
+
}
|
130
|
+
end
|
131
|
+
end
|
132
|
+
end
|
133
|
+
options[:topics] = topics
|
134
|
+
end
|
135
|
+
|
136
|
+
def self.normalize_has_many(options)
|
137
|
+
associations = {}
|
138
|
+
options[:has_many] = [options[:has_many]] if !options[:has_many].is_a?(Array)
|
139
|
+
options[:has_many].each do |association|
|
140
|
+
if association.is_a?(String) || association.is_a?(Symbol)
|
141
|
+
association = association.to_s
|
142
|
+
associations[association.to_sym] = {
|
143
|
+
:key => association.to_sym,
|
144
|
+
:id => key_to_id(value, options),
|
145
|
+
:class_name => association.singularize.camelize
|
146
|
+
}
|
147
|
+
elsif association.is_a?(Hash)
|
148
|
+
association.each do |key, value|
|
149
|
+
key = key.to_s
|
150
|
+
associations[key.to_sym] = {
|
151
|
+
:key => key,
|
152
|
+
:id => key_to_id(value, options),
|
153
|
+
:class_name => key.singularize.camelize
|
154
|
+
}
|
155
|
+
end
|
156
|
+
end
|
157
|
+
end
|
158
|
+
options[:has_many] = associations
|
159
|
+
end
|
160
|
+
|
161
|
+
def self.key_to_id(key, options)
|
162
|
+
key = key.to_s
|
163
|
+
if key == "description"
|
164
|
+
key
|
165
|
+
elsif key[0,1] == "/"
|
166
|
+
key
|
167
|
+
else
|
168
|
+
"#{options[:type]}/#{key}"
|
169
|
+
end
|
170
|
+
end
|
171
|
+
end
|
172
|
+
end
|
data/lib/freeb/models.rb
ADDED
@@ -0,0 +1,175 @@
|
|
1
|
+
module Freeb
|
2
|
+
module Models
|
3
|
+
module ClassMethods
|
4
|
+
def freeb(&block)
|
5
|
+
include InstanceMethods
|
6
|
+
dsl = DSL.new
|
7
|
+
dsl.instance_eval(&block)
|
8
|
+
options = ModelConfig.register(self, dsl.config)
|
9
|
+
|
10
|
+
accessible_attributes = [:freebase_id, :name]
|
11
|
+
accessible_attributes += (options[:properties].merge(options[:topics]).merge(options[:has_many])).keys
|
12
|
+
|
13
|
+
attr_reader :freeb_config
|
14
|
+
attr_accessible *accessible_attributes
|
15
|
+
validates_presence_of :freebase_id, :name
|
16
|
+
|
17
|
+
initialize_topic_associations(options)
|
18
|
+
initialize_has_many_associations(options)
|
19
|
+
|
20
|
+
@freeb_config = ModelConfig.get(self)
|
21
|
+
end
|
22
|
+
|
23
|
+
def initialize_topic_associations(options)
|
24
|
+
return if options[:topics].blank?
|
25
|
+
options[:topics].each do |key, value|
|
26
|
+
join_association = :"#{key}_freebase_topic_relations"
|
27
|
+
has_many join_association, :as => :subject, :class_name => "FreebaseTopicRelation",
|
28
|
+
:conditions => {:property => value[:id]}, :before_add => :"before_add_#{join_association}"
|
29
|
+
define_method :"before_add_#{join_association}" do |record|
|
30
|
+
record.property = value[:id]
|
31
|
+
end
|
32
|
+
has_many key, :through => join_association, :source => :freebase_topic
|
33
|
+
join_association = :"freebase_topic_relations_#{key}"
|
34
|
+
FreebaseTopic.has_many join_association, :class_name => "FreebaseTopicRelation",
|
35
|
+
:conditions => {:property => value[:id]}
|
36
|
+
FreebaseTopic.has_many self.name.tableize, :through => join_association,
|
37
|
+
:source => :subject, :source_type => self.name
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
def initialize_has_many_associations(options)
|
42
|
+
return if options[:has_many].blank?
|
43
|
+
options[:has_many].each do |key, association|
|
44
|
+
# Two-sided polymorphic has_many relationships are supported by Rails, so we'll do this with a HABTM and
|
45
|
+
# custom insert SQL. Is there a better approach?
|
46
|
+
join_table = "freebase_model_relations"
|
47
|
+
has_and_belongs_to_many key, :join_table => join_table,
|
48
|
+
:foreign_key => "subject_id", :association_foreign_key => "object_id",
|
49
|
+
:conditions => {
|
50
|
+
"#{join_table}.subject_type" => self.name,
|
51
|
+
"#{join_table}.object_type" => association[:class_name],
|
52
|
+
"#{join_table}.property" => association[:id]
|
53
|
+
},
|
54
|
+
:insert_sql => proc { |object|
|
55
|
+
%{INSERT INTO `#{join_table}`
|
56
|
+
(`subject_type`, `subject_id`, `property`, `object_type`, `object_id`)
|
57
|
+
VALUES
|
58
|
+
("#{self.class.name}", "#{id}", "#{association[:id]}", "#{association[:class_name]}", "#{object.id}" )}
|
59
|
+
}
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def fnew(freebase_id)
|
64
|
+
return nil if freebase_id.nil?
|
65
|
+
return fnew_with_array(freebase_id) if freebase_id.is_a?(Array)
|
66
|
+
topic = Converter.freebase_id_to_topic(freebase_id, self)
|
67
|
+
new(Converter.topic_to_record_attributes(topic, self))
|
68
|
+
end
|
69
|
+
|
70
|
+
def fnew_by_name(name)
|
71
|
+
return nil if name.nil?
|
72
|
+
return names.collect { |name| fnew_by_name(name) } if name.is_a?(Array)
|
73
|
+
topic = Converter.name_to_topic(name, self)
|
74
|
+
new(Converter.topic_to_record_attributes(topic, self))
|
75
|
+
end
|
76
|
+
|
77
|
+
def fcreate(freebase_id)
|
78
|
+
return nil if freebase_id.nil?
|
79
|
+
return fcreate_with_array(freebase_id) if freebase_id.is_a?(Array)
|
80
|
+
existing = find_by_freebase_id(freebase_id)
|
81
|
+
return existing unless existing.blank?
|
82
|
+
begin
|
83
|
+
topic = Converter.freebase_id_to_topic(freebase_id, self)
|
84
|
+
rescue ResponseException
|
85
|
+
return nil
|
86
|
+
end
|
87
|
+
return nil if topic.blank?
|
88
|
+
create(Converter.topic_to_record_attributes(topic, self))
|
89
|
+
end
|
90
|
+
|
91
|
+
def fcreate_by_name(name)
|
92
|
+
return nil if name.nil?
|
93
|
+
if name.is_a?(Array)
|
94
|
+
names = name
|
95
|
+
return names.collect { |name| fcreate_by_name(name) }
|
96
|
+
end
|
97
|
+
existing = find_by_name(name)
|
98
|
+
return existing unless existing.blank?
|
99
|
+
begin
|
100
|
+
topic = Converter.name_to_topic(name, self)
|
101
|
+
rescue ResponseException
|
102
|
+
return nil
|
103
|
+
end
|
104
|
+
return nil if topic.blank?
|
105
|
+
create(Converter.topic_to_record_attributes(topic, self))
|
106
|
+
end
|
107
|
+
|
108
|
+
def fcreate_all
|
109
|
+
return fcreate([{}])
|
110
|
+
end
|
111
|
+
|
112
|
+
def ffind_or_create(hash)
|
113
|
+
find_or_create_by_freebase_id(hash)
|
114
|
+
end
|
115
|
+
|
116
|
+
protected
|
117
|
+
|
118
|
+
def fnew_with_array(array)
|
119
|
+
if array.first.is_a?(String)
|
120
|
+
freebase_ids = array
|
121
|
+
freebase_ids.collect { |freebase_id| fnew(freebase_id) }
|
122
|
+
elsif array.first.is_a?(Hash)
|
123
|
+
fnew_with_mql(array)
|
124
|
+
end
|
125
|
+
end
|
126
|
+
|
127
|
+
def fcreate_with_array(array)
|
128
|
+
if array.first.is_a?(String)
|
129
|
+
freebase_ids = array
|
130
|
+
freebase_ids.collect { |freebase_id| fcreate(freebase_id) }
|
131
|
+
elsif array.first.is_a?(Hash)
|
132
|
+
fcreate_with_mql(array)
|
133
|
+
end
|
134
|
+
end
|
135
|
+
|
136
|
+
def fnew_with_mql(mql)
|
137
|
+
results = mql_to_results(mql)
|
138
|
+
results.collect do |hash|
|
139
|
+
topic = Topic.new(hash)
|
140
|
+
new(Converter.topic_to_record_attributes(topic, self))
|
141
|
+
end
|
142
|
+
end
|
143
|
+
|
144
|
+
def fcreate_with_mql(mql)
|
145
|
+
results = mql_to_results(mql)
|
146
|
+
results.collect do |hash|
|
147
|
+
topic = Topic.new(hash)
|
148
|
+
ffind_or_create(Converter.topic_to_record_attributes(topic, self))
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def mql_to_results(mql)
|
153
|
+
mql[0] = mql[0].inject({}){|hash, (k,v)| hash[k.to_s] = v; hash}
|
154
|
+
mql[0]["id"] = nil if mql[0]["id"].blank?
|
155
|
+
mql[0]["name"] = nil if mql[0]["name"].blank?
|
156
|
+
mql[0]["type"] = @freeb_config[:type] if mql[0]["type"].blank?
|
157
|
+
API.mqlread(mql)
|
158
|
+
end
|
159
|
+
end
|
160
|
+
|
161
|
+
module InstanceMethods
|
162
|
+
def fupdate
|
163
|
+
topic = Converter.freebase_id_to_topic(freebase_id, self)
|
164
|
+
attributes = Converter.topic_to_record_attributes(topic, self)
|
165
|
+
update_attributes(attributes)
|
166
|
+
end
|
167
|
+
|
168
|
+
def fimage(options={})
|
169
|
+
url = "https://usercontent.googleapis.com/freebase/v1/image#{freebase_id}"
|
170
|
+
url << "?#{options.to_query}" unless options.blank?
|
171
|
+
url
|
172
|
+
end
|
173
|
+
end
|
174
|
+
end
|
175
|
+
end
|