Class: GraphStarter::Asset
- Inherits:
-
Object
- Object
- GraphStarter::Asset
show all
- Includes:
- Authorizable, Neo4j::ActiveNode, Neo4j::Timestamps
- Defined in:
- app/models/graph_starter/asset.rb
Defined Under Namespace
Classes: SecretSauceRecommendation
Class Method Summary
collapse
Instance Method Summary
collapse
#set_access_levels
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method_name, *args, &block) ⇒ Object
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
|
# File 'app/models/graph_starter/asset.rb', line 171
def method_missing(method_name, *args, &block)
if [:name, :title].include?(method_name.to_sym)
self.class.send(:define_method, method_name) do
read_attribute(self.class.name_property)
end
send(method_name)
elsif method_name.to_sym == :body
self.class.send(:define_method, method_name) do
read_attribute(self.class.body_property)
end
send(method_name)
else
super
end
end
|
Class Method Details
.authorized_associations ⇒ Object
307
308
309
|
# File 'app/models/graph_starter/asset.rb', line 307
def self.authorized_associations
associations.except(*Asset.associations.keys + [:images, :image])
end
|
.authorized_for(user) ⇒ Object
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
|
# File 'app/models/graph_starter/asset.rb', line 255
def self.authorized_for(user)
require 'graph_starter/query_authorizer'
if category_association
::GraphStarter::QueryAuthorizer.new(all(:asset).send(category_association, :category, nil, optional: true))
.authorized_query([:asset, :category], user)
.with('DISTINCT asset AS asset')
.proxy_as(self, :asset)
else
::GraphStarter::QueryAuthorizer.new(all(:asset))
.authorized_query(:asset, user)
.with('DISTINCT asset AS asset')
.proxy_as(self, :asset)
end
end
|
.authorized_properties(user) ⇒ Object
271
272
273
|
# File 'app/models/graph_starter/asset.rb', line 271
def self.authorized_properties(user)
authorized_properties_query(user).pluck(:property)
end
|
.authorized_properties_and_levels(user) ⇒ Object
275
276
277
|
# File 'app/models/graph_starter/asset.rb', line 275
def self.authorized_properties_and_levels(user)
authorized_properties_query(user).pluck(:property, :level)
end
|
.authorized_properties_query(user) ⇒ Object
279
280
281
282
283
284
285
286
287
288
289
290
291
|
# File 'app/models/graph_starter/asset.rb', line 279
def self.authorized_properties_query(user)
query = property_name_and_uuid_and_ruby_type_query
.merge(model: {Model: {name: name}})
.on_create_set(model: {private: false})
.break
.merge('model-[:HAS_PROPERTY]->(property:Property {name: property_name})')
.on_create_set(property: {private: false})
.on_create_set('property.uuid = uuid, property.ruby_type = ruby_type')
.with(:property)
::GraphStarter::Property QueryAuthorizer.new(query).authorized_query(:property, user)
end
|
.body_property(property_name = nil) ⇒ Object
123
124
125
126
127
128
129
130
131
132
133
134
|
# File 'app/models/graph_starter/asset.rb', line 123
def self.body_property(property_name = nil)
if property_name.nil?
body_property(default_name_property) if @body_property.nil?
@body_property
else
fail "Cannot declare body_property twice" if @body_property.present?
name = property_name.to_sym
fail ArgumentError, "Property #{name} is not defined" if !attributes.key?(name.to_s)
@body_property = name
end
end
|
.body_property?(property_name) ⇒ Boolean
136
137
138
|
# File 'app/models/graph_starter/asset.rb', line 136
def self.body_property?(property_name)
@body_property && @body_property.to_sym == property_name.to_sym
end
|
.category_association(association_name = nil) ⇒ Object
65
66
67
68
69
70
71
72
73
74
|
# File 'app/models/graph_starter/asset.rb', line 65
def self.category_association(association_name = nil)
if association_name.nil?
@category_association
else
fail "Cannot declare category_association twice" if @category_association.present?
name = association_name.to_sym
fail ArgumentError, "Association #{name} is not defined" if associations[name].nil?
@category_association = name
end
end
|
.default_body_property ⇒ Object
140
141
142
143
144
145
146
|
# File 'app/models/graph_starter/asset.rb', line 140
def self.default_body_property
if @body_property.nil? && !attributes.key?('body')
fail "No body_property defined for #{self.name}!"
end
body_property || 'body'
end
|
.default_name_property ⇒ Object
114
115
116
117
118
119
120
|
# File 'app/models/graph_starter/asset.rb', line 114
def self.default_name_property
(%w(name title) & attributes.keys)[0].tap do |property|
if property.nil?
fail "No name_property defined for #{self.name}!"
end
end
end
|
.descendants ⇒ Object
242
243
244
245
|
# File 'app/models/graph_starter/asset.rb', line 242
def self.descendants
Rails.application.eager_load! if Rails.env == 'development'
Neo4j::ActiveNode::Labels._wrapped_classes.select { |klass| klass < self }
end
|
.display_properties(*property_names) ⇒ Object
149
150
151
152
153
154
155
|
# File 'app/models/graph_starter/asset.rb', line 149
def self.display_properties(*property_names)
if property_names.empty?
@display_properties || []
else
@display_properties = property_names.map(&:to_sym)
end
end
|
.display_property?(property_name) ⇒ Boolean
157
158
159
|
# File 'app/models/graph_starter/asset.rb', line 157
def self.display_property?(property_name)
display_properties.include?(property_name.to_sym)
end
|
.for_query(query) ⇒ Object
198
199
200
201
202
203
204
205
206
|
# File 'app/models/graph_starter/asset.rb', line 198
def self.for_query(query)
where_clause = self.search_properties.map do |property|
fail "Invalid property: #{property}" if attributes[property].nil?
"asset.#{property} =~ {query}"
end.join(' OR ')
query_string = query.strip.gsub(/\s+/, '.*')
all(:asset).where(where_clause).params(query: "(?i).*#{query_string}.*")
end
|
.has_image ⇒ Object
32
33
34
35
|
# File 'app/models/graph_starter/asset.rb', line 32
def self.has_image
@has_image = true
has_one :out, :image, type: :HAS_IMAGE, model_class: '::GraphStarter::Image'
end
|
.has_image? ⇒ Boolean
41
42
43
|
# File 'app/models/graph_starter/asset.rb', line 41
def self.has_image?
!!@has_image
end
|
.has_images ⇒ Object
27
28
29
30
|
# File 'app/models/graph_starter/asset.rb', line 27
def self.has_images
@has_images = true
has_many :out, :images, type: :HAS_IMAGE, model_class: '::GraphStarter::Image'
end
|
.has_images? ⇒ Boolean
37
38
39
|
# File 'app/models/graph_starter/asset.rb', line 37
def self.has_images?
!!@has_images
end
|
.icon_class ⇒ Object
311
312
313
|
# File 'app/models/graph_starter/asset.rb', line 311
def self.icon_class
GraphStarter.configuration.icon_classes[self.name.to_sym]
end
|
.image_association ⇒ Object
45
46
47
48
49
50
51
|
# File 'app/models/graph_starter/asset.rb', line 45
def self.image_association
if has_images?
:images
elsif has_image?
:image
end
end
|
.model_slug ⇒ Object
247
248
249
|
# File 'app/models/graph_starter/asset.rb', line 247
def self.model_slug
name.tableize
end
|
.name_property(property_name = nil) ⇒ Object
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
|
# File 'app/models/graph_starter/asset.rb', line 94
def self.name_property(property_name = nil)
if property_name.nil?
name_property(default_name_property) if @name_property.nil?
@name_property
else
fail "Cannot declare name_property twice" if @name_property.present?
name = property_name.to_sym
fail ArgumentError, "Property #{name} is not defined" if !attributes.key?(name.to_s)
@name_property = name
validates name, presence: true
index name
end
end
|
.name_property?(property_name) ⇒ Boolean
110
111
112
|
# File 'app/models/graph_starter/asset.rb', line 110
def self.name_property?(property_name)
@name_property && @name_property.to_sym == property_name.to_sym
end
|
.properties ⇒ Object
251
252
253
|
# File 'app/models/graph_starter/asset.rb', line 251
def self.properties
attributes.keys - Asset.attributes.keys
end
|
.property_name_and_uuid_and_ruby_type_query ⇒ Object
293
294
295
296
297
298
299
300
301
302
303
304
305
|
# File 'app/models/graph_starter/asset.rb', line 293
def self.property_name_and_uuid_and_ruby_type_query
properties_and_uuids_and_ruby_types = properties.map do |property|
type = self.attributes[property][:type]
type = type.name if type.is_a?(Class)
[property, SecureRandom.uuid, type]
end
Neo4j::Session.current.query
.with('{array} AS array')
.unwind('array AS row')
.params(array: properties_and_uuids_and_ruby_types)
.with('row[0] AS property_name, row[1] AS uuid, row[2] AS ruby_type')
end
|
.rated ⇒ Object
85
86
87
|
# File 'app/models/graph_starter/asset.rb', line 85
def self.rated
@rated = true
end
|
.rated? ⇒ Boolean
89
90
91
|
# File 'app/models/graph_starter/asset.rb', line 89
def self.rated?
!!@rated
end
|
.search_properties(*array) ⇒ Object
190
191
192
193
194
195
196
|
# File 'app/models/graph_starter/asset.rb', line 190
def self.search_properties(*array)
if array.empty?
@search_properties || [name_property]
else
@search_properties = array
end
end
|
Instance Method Details
#as_json(_options = {}) ⇒ Object
232
233
234
235
236
237
238
239
240
|
# File 'app/models/graph_starter/asset.rb', line 232
def as_json(_options = {})
{self.class.model_slug =>
{id: id,
title: title,
name: title,
images: images.map {|image| image.source.url },
model_slug: self.class.model_slug}
}
end
|
#categories ⇒ Object
76
77
78
79
80
81
82
|
# File 'app/models/graph_starter/asset.rb', line 76
def categories
if self.class.category_association
send(self.class.category_association)
else
[]
end
end
|
#first_image ⇒ Object
53
54
55
56
57
58
59
|
# File 'app/models/graph_starter/asset.rb', line 53
def first_image
if self.class.has_images?
images.first
elsif self.class.has_image?
image
end
end
|
#first_image_source_url ⇒ Object
61
62
63
|
# File 'app/models/graph_starter/asset.rb', line 61
def first_image_source_url
first_image && first_image.source_url
end
|
#rating_for(user) ⇒ Object
167
168
169
|
# File 'app/models/graph_starter/asset.rb', line 167
def rating_for(user)
rated_by_user(nil, :rating).where(uuid: user.uuid).pluck(:rating)[0]
end
|
#rating_level_for(user) ⇒ Object
162
163
164
165
|
# File 'app/models/graph_starter/asset.rb', line 162
def rating_level_for(user)
rating = rating_for(user)
rating && rating.level
end
|
#secret_sauce_recommendations ⇒ Object
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
|
# File 'app/models/graph_starter/asset.rb', line 208
def secret_sauce_recommendations
user_class = GraphStarter.configuration.user_class
return [] if user_class.nil?
user_class = (user_class.is_a?(Class) ? user_class : user_class.to_s.constantize)
user_label = user_class.mapped_label_name
query_as(:source)
.match('source-[:HAS_CATEGORY]->(category:Category)<-[:HAS_CATEGORY]-(asset:Asset)')
.break
.optional_match("source<-[:CREATED]-(creator:#{user_label})-[:CREATED]->asset")
.break
.optional_match("source<-[:VIEWED]-(viewer:#{user_label})-[:VIEWED]->asset")
.limit(5)
.order('score DESC')
.pluck(
:asset,
'(count(category) * 2) +
(count(creator) * 4) +
(count(viewer) * 0.1) AS score').map do |other_asset, score|
SecretSauceRecommendation.new(other_asset, score)
end
end
|