graph_starter 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.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +38 -0
- data/app/assets/images/missing.png +0 -0
- data/app/assets/javascripts/graph_starter/application.coffee.erb +25 -0
- data/app/assets/javascripts/graph_starter/ember-template-compiler.js +22130 -0
- data/app/assets/javascripts/graph_starter/ember.js +52794 -0
- data/app/assets/javascripts/graph_starter/ember_apps/permissions_modal.coffee +146 -0
- data/app/assets/javascripts/graph_starter/ember_apps/user_list_dropdown.coffee +22 -0
- data/app/assets/javascripts/graph_starter/jquery-ui.min.js +7 -0
- data/app/assets/javascripts/graph_starter/underscore.js +1548 -0
- data/app/assets/stylesheets/graph_starter/application.scss +9 -0
- data/app/controllers/graph_starter/application_controller.rb +11 -0
- data/app/controllers/graph_starter/assets_controller.rb +76 -0
- data/app/controllers/graph_starter/authorizables_controller.rb +47 -0
- data/app/controllers/graph_starter/categories_controller.rb +79 -0
- data/app/controllers/graph_starter/groups_controller.rb +85 -0
- data/app/controllers/graph_starter/models_controller.rb +11 -0
- data/app/controllers/graph_starter/properties_controller.rb +11 -0
- data/app/helpers/graph_starter/application_helper.rb +11 -0
- data/app/models/concerns/graph_starter/authorizable.rb +30 -0
- data/app/models/graph_starter/asset.rb +161 -0
- data/app/models/graph_starter/can_access.rb +14 -0
- data/app/models/graph_starter/category.rb +24 -0
- data/app/models/graph_starter/group.rb +36 -0
- data/app/models/graph_starter/image.rb +16 -0
- data/app/models/graph_starter/model.rb +23 -0
- data/app/models/graph_starter/property.rb +19 -0
- data/app/models/graph_starter/view.rb +30 -0
- data/app/views/graph_starter/assets/TODO.md +7 -0
- data/app/views/graph_starter/assets/_cards.html.slim +34 -0
- data/app/views/graph_starter/assets/edit.html.slim +24 -0
- data/app/views/graph_starter/assets/home.html.slim +1 -0
- data/app/views/graph_starter/assets/index.html.slim +28 -0
- data/app/views/graph_starter/assets/show.html.slim +98 -0
- data/app/views/graph_starter/authorizables/show.json.jbuilder +20 -0
- data/app/views/graph_starter/authorizables/user_and_group_search.json.jbuilder +8 -0
- data/app/views/graph_starter/categories/show.html.slim +9 -0
- data/app/views/graph_starter/groups/_form.html.slim +30 -0
- data/app/views/graph_starter/groups/_list.html.slim +19 -0
- data/app/views/graph_starter/groups/edit.html.slim +8 -0
- data/app/views/graph_starter/groups/index.html.slim +18 -0
- data/app/views/graph_starter/groups/index.json.jbuilder +4 -0
- data/app/views/graph_starter/groups/new.html.slim +5 -0
- data/app/views/graph_starter/groups/show.html.slim +16 -0
- data/app/views/graph_starter/groups/show.json.jbuilder +1 -0
- data/app/views/graph_starter/models/index.html.slim +10 -0
- data/app/views/graph_starter/properties/_property.html.slim +34 -0
- data/app/views/layouts/graph_starter/_change_permissions_modal.html.slim +90 -0
- data/app/views/layouts/graph_starter/_custom_menu.html.slim +0 -0
- data/app/views/layouts/graph_starter/_menu.html.slim +7 -0
- data/app/views/layouts/graph_starter/_twitter_meta_tags.html.slim +17 -0
- data/app/views/layouts/graph_starter/application.html.slim +45 -0
- data/app/views/layouts/graph_starter/custom_menu.html.slim +0 -0
- data/config/routes.rb +24 -0
- data/lib/graph_starter.rb +4 -0
- data/lib/graph_starter/engine.rb +25 -0
- data/lib/graph_starter/query_authorizer.rb +81 -0
- data/lib/graph_starter/version.rb +3 -0
- data/lib/tasks/graph_starter_tasks.rake +4 -0
- data/test/dummy/README.rdoc +28 -0
- data/test/dummy/Rakefile +6 -0
- data/test/dummy/app/assets/javascripts/application.js +13 -0
- data/test/dummy/app/assets/stylesheets/application.css +15 -0
- data/test/dummy/app/controllers/application_controller.rb +5 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/app/views/layouts/application.html.erb +14 -0
- data/test/dummy/bin/bundle +3 -0
- data/test/dummy/bin/rails +4 -0
- data/test/dummy/bin/rake +4 -0
- data/test/dummy/bin/setup +29 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/config/application.rb +26 -0
- data/test/dummy/config/boot.rb +5 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +41 -0
- data/test/dummy/config/environments/production.rb +79 -0
- data/test/dummy/config/environments/test.rb +42 -0
- data/test/dummy/config/initializers/assets.rb +11 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/cookies_serializer.rb +3 -0
- data/test/dummy/config/initializers/filter_parameter_logging.rb +4 -0
- data/test/dummy/config/initializers/inflections.rb +16 -0
- data/test/dummy/config/initializers/mime_types.rb +4 -0
- data/test/dummy/config/initializers/session_store.rb +3 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +23 -0
- data/test/dummy/config/routes.rb +4 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/public/404.html +67 -0
- data/test/dummy/public/422.html +67 -0
- data/test/dummy/public/500.html +66 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/graph_starter_test.rb +7 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +20 -0
- metadata +262 -0
|
@@ -0,0 +1,76 @@
|
|
|
1
|
+
module GraphStarter
|
|
2
|
+
class AssetsController < ::GraphStarter::ApplicationController
|
|
3
|
+
def home
|
|
4
|
+
end
|
|
5
|
+
|
|
6
|
+
def index
|
|
7
|
+
@assets = asset_set
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def search
|
|
11
|
+
regexp = Regexp.new('.*' + params[:query].gsub(/\s+/, '.*') + '.*', 'i')
|
|
12
|
+
assets = asset_set { |scope| scope.where(title: regexp) }
|
|
13
|
+
results_data = assets.map do |asset|
|
|
14
|
+
{
|
|
15
|
+
title: asset.title,
|
|
16
|
+
url: asset_path(id: asset, model_slug: asset.class.model_slug),
|
|
17
|
+
image: images? && asset.first_image_source && asset.first_image_source.url || nil
|
|
18
|
+
}.reject {|_, v| v.nil? }
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
render json: {results: results_data}.to_json
|
|
22
|
+
end
|
|
23
|
+
|
|
24
|
+
def asset_set
|
|
25
|
+
associations = []
|
|
26
|
+
associations << :images if images?
|
|
27
|
+
associations << model_class.category_association if model_class.category_association
|
|
28
|
+
|
|
29
|
+
scope = model_class_scope
|
|
30
|
+
scope = yield scope if block_given?
|
|
31
|
+
|
|
32
|
+
scope = scope.limit(50)
|
|
33
|
+
|
|
34
|
+
if associations.present?
|
|
35
|
+
scope.query_as(:s).with(:s).proxy_as(model_class_scope.model, :s).with_associations(*associations)
|
|
36
|
+
else
|
|
37
|
+
scope
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def show
|
|
42
|
+
@asset = asset
|
|
43
|
+
|
|
44
|
+
render file: 'public/404.html', status: :not_found, layout: false if !@asset
|
|
45
|
+
end
|
|
46
|
+
|
|
47
|
+
def edit
|
|
48
|
+
@asset = asset
|
|
49
|
+
|
|
50
|
+
render file: 'public/404.html', status: :not_found, layout: false if !@asset
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def update
|
|
54
|
+
@asset = asset
|
|
55
|
+
@asset.update(params[:book])
|
|
56
|
+
|
|
57
|
+
redirect_to action: :edit
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
def asset
|
|
61
|
+
model_class_scope.find(params[:id])
|
|
62
|
+
end
|
|
63
|
+
|
|
64
|
+
def images?
|
|
65
|
+
model_class_scope.has_images?
|
|
66
|
+
end
|
|
67
|
+
|
|
68
|
+
def model_class_scope
|
|
69
|
+
@model_class_scope = if defined?(current_user)
|
|
70
|
+
model_class.authorized_for(current_user)
|
|
71
|
+
else
|
|
72
|
+
model_class.all
|
|
73
|
+
end
|
|
74
|
+
end
|
|
75
|
+
end
|
|
76
|
+
end
|
|
@@ -0,0 +1,47 @@
|
|
|
1
|
+
module GraphStarter
|
|
2
|
+
class AuthorizablesController < ApplicationController
|
|
3
|
+
before_action :require_admin
|
|
4
|
+
|
|
5
|
+
before_action :set_object, only: [:show, :update]
|
|
6
|
+
|
|
7
|
+
def show
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def update
|
|
11
|
+
@object.update_attribute(:private, params[:private])
|
|
12
|
+
|
|
13
|
+
@object.set_access_levels User,
|
|
14
|
+
access_levels_from_permissions(params[:user_permissions], :user)
|
|
15
|
+
|
|
16
|
+
@object.set_access_levels Group,
|
|
17
|
+
access_levels_from_permissions(params[:group_permissions], :group)
|
|
18
|
+
|
|
19
|
+
render :show
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def access_levels_from_permissions(permissions, type)
|
|
23
|
+
(permissions || []).each_with_object({}) do |permission, result|
|
|
24
|
+
result[permission[type][:id]] = permission[:level]
|
|
25
|
+
end
|
|
26
|
+
end
|
|
27
|
+
|
|
28
|
+
def user_and_group_search
|
|
29
|
+
@users, @groups = if params[:query].present?
|
|
30
|
+
|
|
31
|
+
[User.for_query(params[:query]), Group.for_query(params[:query])]
|
|
32
|
+
else
|
|
33
|
+
[[], []]
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def change_permissions_modal
|
|
38
|
+
render layout: false
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
private
|
|
42
|
+
|
|
43
|
+
def set_object
|
|
44
|
+
@object = model_class.find(params[:id])
|
|
45
|
+
end
|
|
46
|
+
end
|
|
47
|
+
end
|
|
@@ -0,0 +1,79 @@
|
|
|
1
|
+
module GraphStarter
|
|
2
|
+
class CategoriesController < ApplicationController
|
|
3
|
+
before_action :set_category, only: [:show, :edit, :update, :destroy]
|
|
4
|
+
|
|
5
|
+
# GET /categories
|
|
6
|
+
# GET /categories.json
|
|
7
|
+
def index
|
|
8
|
+
@categories = Category.all
|
|
9
|
+
end
|
|
10
|
+
|
|
11
|
+
# GET /categories/1
|
|
12
|
+
# GET /categories/1.json
|
|
13
|
+
def show
|
|
14
|
+
end
|
|
15
|
+
|
|
16
|
+
# GET /categories/new
|
|
17
|
+
def new
|
|
18
|
+
@category = Category.new
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
# GET /categories/1/edit
|
|
22
|
+
def edit
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
# POST /categories
|
|
26
|
+
# POST /categories.json
|
|
27
|
+
def create
|
|
28
|
+
@category = Category.new(category_params)
|
|
29
|
+
|
|
30
|
+
respond_to do |format|
|
|
31
|
+
if @category.save
|
|
32
|
+
format.html { redirect_to @category, notice: 'Category was successfully created.' }
|
|
33
|
+
format.json { render :show, status: :created, location: @category }
|
|
34
|
+
else
|
|
35
|
+
format.html { render :new }
|
|
36
|
+
format.json { render json: @category.errors, status: :unprocessable_entity }
|
|
37
|
+
end
|
|
38
|
+
end
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
# PATCH/PUT /categories/1
|
|
42
|
+
# PATCH/PUT /categories/1.json
|
|
43
|
+
def update
|
|
44
|
+
respond_to do |format|
|
|
45
|
+
if @category.update(category_params)
|
|
46
|
+
format.html { redirect_to @category, notice: 'Category was successfully updated.' }
|
|
47
|
+
format.json { render :show, status: :ok, location: @category }
|
|
48
|
+
else
|
|
49
|
+
format.html { render :edit }
|
|
50
|
+
format.json { render json: @category.errors, status: :unprocessable_entity }
|
|
51
|
+
end
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
|
|
55
|
+
# DELETE /categories/1
|
|
56
|
+
# DELETE /categories/1.json
|
|
57
|
+
def destroy
|
|
58
|
+
@category.destroy
|
|
59
|
+
respond_to do |format|
|
|
60
|
+
format.html do
|
|
61
|
+
redirect_to categories_url, notice: 'Category was successfully destroyed.'
|
|
62
|
+
end
|
|
63
|
+
format.json { head :no_content }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
private
|
|
68
|
+
|
|
69
|
+
# Use callbacks to share common setup or constraints between actions.
|
|
70
|
+
def set_category
|
|
71
|
+
@category = Category.find(params[:id])
|
|
72
|
+
end
|
|
73
|
+
|
|
74
|
+
# Never trust parameters from the scary internet, only allow the white list through.
|
|
75
|
+
def category_params
|
|
76
|
+
params[:category]
|
|
77
|
+
end
|
|
78
|
+
end
|
|
79
|
+
end
|
|
@@ -0,0 +1,85 @@
|
|
|
1
|
+
module GraphStarter
|
|
2
|
+
class GroupsController < ApplicationController
|
|
3
|
+
before_action :require_admin
|
|
4
|
+
|
|
5
|
+
before_action :set_group, only: [:show, :edit, :update, :destroy, :users_to_add]
|
|
6
|
+
|
|
7
|
+
# GET /groups
|
|
8
|
+
# GET /groups.json
|
|
9
|
+
def index
|
|
10
|
+
@groups = Group.roots
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
# GET /groups/1
|
|
14
|
+
# GET /groups/1.json
|
|
15
|
+
def show
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
# GET /groups/new
|
|
19
|
+
def new
|
|
20
|
+
@group = Group.new
|
|
21
|
+
end
|
|
22
|
+
|
|
23
|
+
# GET /groups/1/edit
|
|
24
|
+
def edit
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
# POST /groups
|
|
28
|
+
# POST /groups.json
|
|
29
|
+
def create
|
|
30
|
+
@group = Group.new(group_params)
|
|
31
|
+
|
|
32
|
+
respond_to do |format|
|
|
33
|
+
if @group.save
|
|
34
|
+
format.html { redirect_to @group, notice: 'Group was successfully created.' }
|
|
35
|
+
format.json { render :show, status: :created, location: @group }
|
|
36
|
+
else
|
|
37
|
+
format.html { render :new }
|
|
38
|
+
format.json { render json: @group.errors, status: :unprocessable_entity }
|
|
39
|
+
end
|
|
40
|
+
end
|
|
41
|
+
end
|
|
42
|
+
|
|
43
|
+
# PATCH/PUT /groups/1
|
|
44
|
+
# PATCH/PUT /groups/1.json
|
|
45
|
+
def update
|
|
46
|
+
respond_to do |format|
|
|
47
|
+
if @group.update(group_params)
|
|
48
|
+
format.html { redirect_to @group, notice: 'Group was successfully updated.' }
|
|
49
|
+
format.json { render :show, status: :ok, location: @group }
|
|
50
|
+
else
|
|
51
|
+
format.html { render :edit }
|
|
52
|
+
format.json { render json: @group.errors, status: :unprocessable_entity }
|
|
53
|
+
end
|
|
54
|
+
end
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
# DELETE /groups/1
|
|
58
|
+
# DELETE /groups/1.json
|
|
59
|
+
def destroy
|
|
60
|
+
@group.destroy
|
|
61
|
+
respond_to do |format|
|
|
62
|
+
format.html { redirect_to groups_url, notice: 'Group was successfully destroyed.' }
|
|
63
|
+
format.json { head :no_content }
|
|
64
|
+
end
|
|
65
|
+
end
|
|
66
|
+
|
|
67
|
+
def users_to_add
|
|
68
|
+
render json: @group.addable_users
|
|
69
|
+
end
|
|
70
|
+
|
|
71
|
+
private
|
|
72
|
+
|
|
73
|
+
# Use callbacks to share common setup or constraints between actions.
|
|
74
|
+
def set_group
|
|
75
|
+
@group = Group.find(params[:id])
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
# Never trust parameters from the scary internet, only allow the white list through.
|
|
79
|
+
def group_params
|
|
80
|
+
params[:group][:member_ids].reject!(&:blank?)
|
|
81
|
+
|
|
82
|
+
params[:group]
|
|
83
|
+
end
|
|
84
|
+
end
|
|
85
|
+
end
|
|
@@ -0,0 +1,11 @@
|
|
|
1
|
+
module GraphStarter
|
|
2
|
+
module ApplicationHelper
|
|
3
|
+
def asset_path(asset)
|
|
4
|
+
super(id: asset, model_slug: asset.class.model_slug)
|
|
5
|
+
end
|
|
6
|
+
|
|
7
|
+
def engine_view(&b)
|
|
8
|
+
yield eval("__FILE__.gsub(Rails.root.to_s, GraphStarter::Engine.root.to_s)",b.binding)
|
|
9
|
+
end
|
|
10
|
+
end
|
|
11
|
+
end
|
|
@@ -0,0 +1,30 @@
|
|
|
1
|
+
module GraphStarter
|
|
2
|
+
module Authorizable
|
|
3
|
+
extend ActiveSupport::Concern
|
|
4
|
+
|
|
5
|
+
included do
|
|
6
|
+
property :private, type: ActiveAttr::Typecasting::Boolean, default: false
|
|
7
|
+
validates :private, inclusion: {in: [true, false]}
|
|
8
|
+
|
|
9
|
+
has_many :in, :allowed_users, rel_class: :CanAccess, model_class: :User
|
|
10
|
+
has_many :in, :allowed_groups, rel_class: :CanAccess, model_class: :Group
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def set_access_levels(model, access_levels)
|
|
14
|
+
records_by_id = model.where(id: access_levels.keys).index_by(&:id)
|
|
15
|
+
|
|
16
|
+
model.where_not(id: records_by_id.keys)
|
|
17
|
+
.query_as(:r)
|
|
18
|
+
.match_nodes(this: self)
|
|
19
|
+
.match('r-[rel:CAN_ACCESS]->(this)')
|
|
20
|
+
.delete(:rel).exec
|
|
21
|
+
|
|
22
|
+
access_levels.each do |id, level|
|
|
23
|
+
CanAccess.create(from_node: records_by_id[id], to_node: self, level: level)
|
|
24
|
+
end
|
|
25
|
+
end
|
|
26
|
+
|
|
27
|
+
module ClassMethods
|
|
28
|
+
end
|
|
29
|
+
end
|
|
30
|
+
end
|
|
@@ -0,0 +1,161 @@
|
|
|
1
|
+
require 'graph_starter/query_authorizer'
|
|
2
|
+
|
|
3
|
+
module GraphStarter
|
|
4
|
+
class Asset
|
|
5
|
+
include Neo4j::ActiveNode
|
|
6
|
+
self.mapped_label_name = 'Asset'
|
|
7
|
+
|
|
8
|
+
include Neo4j::Timestamps
|
|
9
|
+
|
|
10
|
+
include Authorizable
|
|
11
|
+
|
|
12
|
+
property :title
|
|
13
|
+
validates :title, presence: true
|
|
14
|
+
|
|
15
|
+
property :summary
|
|
16
|
+
|
|
17
|
+
property :view_count, type: Integer
|
|
18
|
+
|
|
19
|
+
property :private, type: Boolean, default: false
|
|
20
|
+
|
|
21
|
+
#has_many :in, :creators, type: :CREATED, model_class: :User
|
|
22
|
+
|
|
23
|
+
has_many :in, :viewers, rel_class: :View, model_class: :User
|
|
24
|
+
|
|
25
|
+
SecretSauceRecommendation = Struct.new(:asset, :score)
|
|
26
|
+
|
|
27
|
+
def body
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
IMAGE_MODELS = []
|
|
31
|
+
def self.has_images
|
|
32
|
+
GraphStarter::Asset::IMAGE_MODELS << self
|
|
33
|
+
has_many :out, :images, type: :HAS_IMAGE, model_class: '::GraphStarter::Image'
|
|
34
|
+
end
|
|
35
|
+
|
|
36
|
+
def self.has_images?
|
|
37
|
+
GraphStarter::Asset::IMAGE_MODELS.include?(self)
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def first_image_source
|
|
41
|
+
images.first && images.first.source
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def self.category_association
|
|
45
|
+
@category_association
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
def self.category_association=(association_name)
|
|
49
|
+
@category_association = association_name
|
|
50
|
+
end
|
|
51
|
+
|
|
52
|
+
def categories
|
|
53
|
+
if self.class.category_association
|
|
54
|
+
send(self.class.category_association)
|
|
55
|
+
else
|
|
56
|
+
[]
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
|
|
61
|
+
def self.for_query(query)
|
|
62
|
+
all.where(title: /.*#{query}.*/i)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def secret_sauce_recommendations
|
|
66
|
+
query_as(:source)
|
|
67
|
+
.match('source-[:HAS_CATEGORY]->(category:Category)<-[:HAS_CATEGORY]-(asset:Asset)')
|
|
68
|
+
.break
|
|
69
|
+
.optional_match('source<-[:CREATED]-(creator:User)-[:CREATED]->asset')
|
|
70
|
+
.break
|
|
71
|
+
.optional_match('source<-[:VIEWED]-(viewer:User)-[:VIEWED]->asset')
|
|
72
|
+
.limit(5)
|
|
73
|
+
.order('score DESC')
|
|
74
|
+
.pluck(
|
|
75
|
+
:asset,
|
|
76
|
+
'(count(category) * 2) +
|
|
77
|
+
(count(creator) * 4) +
|
|
78
|
+
(count(viewer) * 0.1) AS score').map do |other_asset, score|
|
|
79
|
+
SecretSauceRecommendation.new(other_asset, score)
|
|
80
|
+
end
|
|
81
|
+
end
|
|
82
|
+
|
|
83
|
+
def name
|
|
84
|
+
title
|
|
85
|
+
end
|
|
86
|
+
|
|
87
|
+
def as_json(_options = {})
|
|
88
|
+
{self.class.model_slug =>
|
|
89
|
+
{id: id,
|
|
90
|
+
title: title,
|
|
91
|
+
name: title,
|
|
92
|
+
images: images.map {|image| image.source.url },
|
|
93
|
+
model_slug: self.class.model_slug}
|
|
94
|
+
}
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def self.descendants
|
|
98
|
+
Rails.application.eager_load! if Rails.env == 'development'
|
|
99
|
+
Neo4j::ActiveNode::Labels._wrapped_classes.select { |klass| klass < self }
|
|
100
|
+
end
|
|
101
|
+
|
|
102
|
+
def self.model_slug
|
|
103
|
+
name.tableize
|
|
104
|
+
end
|
|
105
|
+
|
|
106
|
+
def self.properties
|
|
107
|
+
attributes.keys - Asset.attributes.keys
|
|
108
|
+
end
|
|
109
|
+
|
|
110
|
+
def self.authorized_for(user)
|
|
111
|
+
require 'graph_starter/query_authorizer'
|
|
112
|
+
|
|
113
|
+
::GraphStarter::QueryAuthorizer.new(all(:asset).categories(:category, nil, optional: true))
|
|
114
|
+
.authorized_query([:asset, :category], user)
|
|
115
|
+
.with('DISTINCT asset AS asset')
|
|
116
|
+
.proxy_as(self, :asset)
|
|
117
|
+
end
|
|
118
|
+
|
|
119
|
+
def self.authorized_properties(user)
|
|
120
|
+
authorized_properties_query(user).pluck(:property)
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def self.authorized_properties_and_levels(user)
|
|
124
|
+
authorized_properties_query(user).pluck(:property, :level)
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
def self.authorized_properties_query(user)
|
|
128
|
+
query = property_name_and_uuid_and_ruby_type_query
|
|
129
|
+
.merge(model: {Model: {name: name}})
|
|
130
|
+
.on_create_set(model: {private: false})
|
|
131
|
+
.break
|
|
132
|
+
.merge('model-[:HAS_PROPERTY]->(property:Property {name: property_name})')
|
|
133
|
+
.on_create_set(property: {private: false})
|
|
134
|
+
.on_create_set('property.uuid = uuid, property.ruby_type = ruby_type')
|
|
135
|
+
.with(:property)
|
|
136
|
+
|
|
137
|
+
::GraphStarter::Property # rubocop:disable Lint/Void
|
|
138
|
+
QueryAuthorizer.new(query).authorized_query(:property, user)
|
|
139
|
+
end
|
|
140
|
+
|
|
141
|
+
def self.property_name_and_uuid_and_ruby_type_query
|
|
142
|
+
properties_and_uuids_and_ruby_types = properties.map do |property|
|
|
143
|
+
[property, SecureRandom.uuid, self.attributes[property][:type]]
|
|
144
|
+
end
|
|
145
|
+
|
|
146
|
+
Neo4j::Session.current.query
|
|
147
|
+
.with('{array} AS array')
|
|
148
|
+
.unwind('array AS row')
|
|
149
|
+
.params(array: properties_and_uuids_and_ruby_types)
|
|
150
|
+
.with('row[0] AS property_name, row[1] AS uuid, row[2] AS ruby_type')
|
|
151
|
+
end
|
|
152
|
+
|
|
153
|
+
def self.authorized_associations
|
|
154
|
+
associations.except(*Asset.associations.keys + [:images])
|
|
155
|
+
end
|
|
156
|
+
|
|
157
|
+
def self.icon_class
|
|
158
|
+
'bookmark'
|
|
159
|
+
end
|
|
160
|
+
end
|
|
161
|
+
end
|