freeb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- 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
|