neo4j-meta_model 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/MIT-LICENSE +20 -0
- data/README.rdoc +3 -0
- data/Rakefile +37 -0
- data/app/assets/javascripts/admin/models.js.coffee +25 -0
- data/app/assets/javascripts/meta_model.js.coffee +217 -0
- data/app/assets/javascripts/router.js.coffee +5 -0
- data/app/assets/javascripts/store.js.coffee +12 -0
- data/app/assets/javascripts/templates/application.emblem +3 -0
- data/app/assets/javascripts/templates/components/model-list-item.emblem +6 -0
- data/app/assets/javascripts/templates/components/model-list.emblem +4 -0
- data/app/assets/javascripts/templates/has_associations/index.emblem +25 -0
- data/app/assets/javascripts/templates/has_associations/new.emblem +50 -0
- data/app/assets/javascripts/templates/index.emblem +6 -0
- data/app/assets/javascripts/templates/models/edit.emblem +40 -0
- data/app/assets/javascripts/templates/models/hierarchy.emblem +8 -0
- data/app/assets/stylesheets/meta_model.css.scss +113 -0
- data/app/controllers/meta_model/application_controller.rb +12 -0
- data/app/controllers/meta_model/meta/has_associations_controller.rb +44 -0
- data/app/controllers/meta_model/meta/models_controller.rb +80 -0
- data/app/controllers/meta_model/meta/properties_controller.rb +36 -0
- data/app/controllers/meta_model/meta_controller.rb +7 -0
- data/app/controllers/meta_model/models_controller.rb +69 -0
- data/app/helpers/meta_model/application_helper.rb +10 -0
- data/app/helpers/meta_model/model_helper.rb +10 -0
- data/app/models/concerns/meta_model/model_base.rb +43 -0
- data/app/models/meta_model/has_association.rb +46 -0
- data/app/models/meta_model/meta_model_base.rb +7 -0
- data/app/models/meta_model/model.rb +51 -0
- data/app/models/meta_model/property.rb +11 -0
- data/app/serializers/meta_model/has_association_serializer.rb +13 -0
- data/app/serializers/meta_model/model_serializer.rb +11 -0
- data/app/serializers/meta_model/property_serializer.rb +6 -0
- data/app/views/layouts/meta_model.html.slim +28 -0
- data/app/views/meta_model/meta/associations/index.html.slim +12 -0
- data/app/views/meta_model/meta/index.html.slim +2 -0
- data/app/views/meta_model/meta/models/edit.html.slim +39 -0
- data/app/views/meta_model/models/_form.html.slim +72 -0
- data/app/views/meta_model/models/_has_many_association.html.slim +4 -0
- data/app/views/meta_model/models/_record_details.html.slim +13 -0
- data/app/views/meta_model/models/edit.html.slim +6 -0
- data/app/views/meta_model/models/index.html.slim +14 -0
- data/app/views/meta_model/models/meta_index.html.slim +6 -0
- data/app/views/meta_model/models/new.html.slim +7 -0
- data/app/views/meta_model/models/show.html.slim +18 -0
- data/config/initializers/active_model_serializer.rb +6 -0
- data/config/routes.rb +19 -0
- data/lib/ext/hash.rb +7 -0
- data/lib/meta_model/engine.rb +23 -0
- data/lib/meta_model/version.rb +3 -0
- data/lib/meta_model.rb +4 -0
- data/lib/meta_models.rb +70 -0
- data/lib/tasks/meta_model_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 +14 -0
- data/test/dummy/app/assets/stylesheets/meta_model.css.scss +55 -0
- data/test/dummy/app/controllers/meta_model/application_controller.rb +8 -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/application.rb +29 -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 +21 -0
- data/test/dummy/config/secrets.yml +22 -0
- data/test/dummy/config.ru +4 -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/integration/navigation_test.rb +10 -0
- data/test/meta_model_test.rb +7 -0
- data/test/test_helper.rb +19 -0
- data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.eot +0 -0
- data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.svg +288 -0
- data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.ttf +0 -0
- data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.woff +0 -0
- data/vendor/assets/fonts/bootstrap/glyphicons-halflings-regular.woff2 +0 -0
- data/vendor/assets/javascripts/backbone.js +1608 -0
- data/vendor/assets/javascripts/bootstrap/affix.js +162 -0
- data/vendor/assets/javascripts/bootstrap/alert.js +94 -0
- data/vendor/assets/javascripts/bootstrap/button.js +116 -0
- data/vendor/assets/javascripts/bootstrap/carousel.js +240 -0
- data/vendor/assets/javascripts/bootstrap/collapse.js +211 -0
- data/vendor/assets/javascripts/bootstrap/dropdown.js +161 -0
- data/vendor/assets/javascripts/bootstrap/modal.js +324 -0
- data/vendor/assets/javascripts/bootstrap/popover.js +119 -0
- data/vendor/assets/javascripts/bootstrap/scrollspy.js +175 -0
- data/vendor/assets/javascripts/bootstrap/tab.js +153 -0
- data/vendor/assets/javascripts/bootstrap/tooltip.js +478 -0
- data/vendor/assets/javascripts/bootstrap/transition.js +59 -0
- data/vendor/assets/javascripts/bootstrap-sprockets.js +12 -0
- data/vendor/assets/javascripts/bootstrap.js +2304 -0
- data/vendor/assets/javascripts/lodash.js +6785 -0
- data/vendor/assets/javascripts/rivets-backbone.js +97 -0
- data/vendor/assets/javascripts/rivets.js +1273 -0
- data/vendor/assets/javascripts/sightglass.js +203 -0
- data/vendor/assets/stylesheets/_bootstrap-compass.scss +7 -0
- data/vendor/assets/stylesheets/_bootstrap-mincer.scss +17 -0
- data/vendor/assets/stylesheets/_bootstrap-sprockets.scss +7 -0
- data/vendor/assets/stylesheets/_bootstrap.scss +50 -0
- data/vendor/assets/stylesheets/bootstrap/_alerts.scss +68 -0
- data/vendor/assets/stylesheets/bootstrap/_badges.scss +63 -0
- data/vendor/assets/stylesheets/bootstrap/_breadcrumbs.scss +26 -0
- data/vendor/assets/stylesheets/bootstrap/_button-groups.scss +243 -0
- data/vendor/assets/stylesheets/bootstrap/_buttons.scss +160 -0
- data/vendor/assets/stylesheets/bootstrap/_carousel.scss +267 -0
- data/vendor/assets/stylesheets/bootstrap/_close.scss +35 -0
- data/vendor/assets/stylesheets/bootstrap/_code.scss +69 -0
- data/vendor/assets/stylesheets/bootstrap/_component-animations.scss +38 -0
- data/vendor/assets/stylesheets/bootstrap/_dropdowns.scss +213 -0
- data/vendor/assets/stylesheets/bootstrap/_forms.scss +548 -0
- data/vendor/assets/stylesheets/bootstrap/_glyphicons.scss +236 -0
- data/vendor/assets/stylesheets/bootstrap/_grid.scss +84 -0
- data/vendor/assets/stylesheets/bootstrap/_input-groups.scss +166 -0
- data/vendor/assets/stylesheets/bootstrap/_jumbotron.scss +49 -0
- data/vendor/assets/stylesheets/bootstrap/_labels.scss +66 -0
- data/vendor/assets/stylesheets/bootstrap/_list-group.scss +124 -0
- data/vendor/assets/stylesheets/bootstrap/_media.scss +47 -0
- data/vendor/assets/stylesheets/bootstrap/_mixins.scss +39 -0
- data/vendor/assets/stylesheets/bootstrap/_modals.scss +148 -0
- data/vendor/assets/stylesheets/bootstrap/_navbar.scss +662 -0
- data/vendor/assets/stylesheets/bootstrap/_navs.scss +244 -0
- data/vendor/assets/stylesheets/bootstrap/_normalize.scss +427 -0
- data/vendor/assets/stylesheets/bootstrap/_pager.scss +54 -0
- data/vendor/assets/stylesheets/bootstrap/_pagination.scss +88 -0
- data/vendor/assets/stylesheets/bootstrap/_panels.scss +261 -0
- data/vendor/assets/stylesheets/bootstrap/_popovers.scss +135 -0
- data/vendor/assets/stylesheets/bootstrap/_print.scss +107 -0
- data/vendor/assets/stylesheets/bootstrap/_progress-bars.scss +87 -0
- data/vendor/assets/stylesheets/bootstrap/_responsive-embed.scss +35 -0
- data/vendor/assets/stylesheets/bootstrap/_responsive-utilities.scss +174 -0
- data/vendor/assets/stylesheets/bootstrap/_scaffolding.scss +150 -0
- data/vendor/assets/stylesheets/bootstrap/_tables.scss +234 -0
- data/vendor/assets/stylesheets/bootstrap/_theme.scss +272 -0
- data/vendor/assets/stylesheets/bootstrap/_thumbnails.scss +38 -0
- data/vendor/assets/stylesheets/bootstrap/_tooltip.scss +103 -0
- data/vendor/assets/stylesheets/bootstrap/_type.scss +298 -0
- data/vendor/assets/stylesheets/bootstrap/_utilities.scss +56 -0
- data/vendor/assets/stylesheets/bootstrap/_variables.scss +864 -0
- data/vendor/assets/stylesheets/bootstrap/_wells.scss +29 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_alerts.scss +14 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_background-variant.scss +11 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_border-radius.scss +18 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_buttons.scss +52 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_center-block.scss +7 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_clearfix.scss +22 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_forms.scss +88 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_gradients.scss +58 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_grid-framework.scss +81 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_grid.scss +122 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_hide-text.scss +21 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_image.scss +33 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_labels.scss +12 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_list-group.scss +31 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_nav-divider.scss +10 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_nav-vertical-align.scss +9 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_opacity.scss +8 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_pagination.scss +23 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_panels.scss +24 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_progress-bar.scss +10 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_reset-filter.scss +8 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_resize.scss +6 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_responsive-visibility.scss +21 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_size.scss +10 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_tab-focus.scss +9 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_table-row.scss +28 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_text-emphasis.scss +11 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_text-overflow.scss +8 -0
- data/vendor/assets/stylesheets/bootstrap/mixins/_vendor-prefixes.scss +222 -0
- metadata +365 -0
@@ -0,0 +1,80 @@
|
|
1
|
+
module MetaModel
|
2
|
+
module Meta
|
3
|
+
class ModelsController < ApplicationController
|
4
|
+
before_action :get_model, only: [:edit, :show, :update, :destroy]
|
5
|
+
|
6
|
+
def index
|
7
|
+
respond_to do |format|
|
8
|
+
format.html { @hierarchy = Model.all.hierarchically }
|
9
|
+
format.json { render json: Model.all }
|
10
|
+
end
|
11
|
+
end
|
12
|
+
|
13
|
+
def hierarchy
|
14
|
+
respond_to do |format|
|
15
|
+
format.json { render json: Model.all.hierarchically }
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def show
|
20
|
+
respond_to do |format|
|
21
|
+
format.json do
|
22
|
+
render json: @model
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def edit
|
28
|
+
@models = Model.all.order(:name)
|
29
|
+
end
|
30
|
+
|
31
|
+
def create
|
32
|
+
model = Model.create(model_params)
|
33
|
+
|
34
|
+
create_models
|
35
|
+
|
36
|
+
render json: model
|
37
|
+
end
|
38
|
+
|
39
|
+
def update
|
40
|
+
model_params.each do |key, value|
|
41
|
+
@model.send("#{key}=", value)
|
42
|
+
end
|
43
|
+
@model.save
|
44
|
+
|
45
|
+
create_models
|
46
|
+
|
47
|
+
render json: @model
|
48
|
+
end
|
49
|
+
|
50
|
+
def destroy
|
51
|
+
@model.destroy
|
52
|
+
|
53
|
+
create_models
|
54
|
+
|
55
|
+
render json: nil
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
def get_model
|
61
|
+
@model = if model_param_class_name
|
62
|
+
Model.where(class_name: model_param_class_name).first
|
63
|
+
end || Model.find(params[:id])
|
64
|
+
end
|
65
|
+
|
66
|
+
def model_param_class_name
|
67
|
+
if params[:id]
|
68
|
+
@model_param_class_name ||= params[:id].classify
|
69
|
+
end
|
70
|
+
rescue NameError
|
71
|
+
end
|
72
|
+
|
73
|
+
def model_params
|
74
|
+
superclass_model = params[:model].delete(:superclass_model_id)
|
75
|
+
params.require(:model).permit(:class_name, :superclass_model).merge(superclass_model: superclass_model)
|
76
|
+
end
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
80
|
+
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module MetaModel
|
2
|
+
module Meta
|
3
|
+
class PropertiesController < ApplicationController
|
4
|
+
before_action :get_property, only: [:edit, :show, :update, :destroy]
|
5
|
+
|
6
|
+
def destroy
|
7
|
+
@property.destroy
|
8
|
+
|
9
|
+
render json: nil
|
10
|
+
end
|
11
|
+
|
12
|
+
def create
|
13
|
+
property = Property.create(property_params)
|
14
|
+
|
15
|
+
render json: property
|
16
|
+
end
|
17
|
+
|
18
|
+
def update
|
19
|
+
@property.update_attributes(property_params)
|
20
|
+
|
21
|
+
render json: @property
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def get_property
|
27
|
+
@property = Property.find(params[:id])
|
28
|
+
end
|
29
|
+
|
30
|
+
def property_params
|
31
|
+
model = params[:property].delete(:model_id)
|
32
|
+
params.require(:property).permit(:name, :type).merge(model: model)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
module MetaModel
|
2
|
+
class ModelsController < MetaModel::ApplicationController
|
3
|
+
before_action :get_model
|
4
|
+
before_action :get_meta_model
|
5
|
+
before_action :get_record, only: [:show, :edit, :update]
|
6
|
+
|
7
|
+
layout 'layouts/meta_model'
|
8
|
+
def meta_index
|
9
|
+
@hierarchy = Model.order(:class_name).hierarchically
|
10
|
+
end
|
11
|
+
|
12
|
+
def index
|
13
|
+
@records = @model.all.to_a
|
14
|
+
respond_to do |format|
|
15
|
+
format.html
|
16
|
+
format.json { render json: @records, root: :records }
|
17
|
+
end
|
18
|
+
end
|
19
|
+
|
20
|
+
def show
|
21
|
+
end
|
22
|
+
|
23
|
+
def edit
|
24
|
+
end
|
25
|
+
|
26
|
+
def update
|
27
|
+
@record.update_attributes(params[:data])
|
28
|
+
|
29
|
+
redirect_to action: :show
|
30
|
+
end
|
31
|
+
|
32
|
+
def new
|
33
|
+
@record = @model.new
|
34
|
+
end
|
35
|
+
|
36
|
+
def create
|
37
|
+
record = @model.create(params[:data])
|
38
|
+
|
39
|
+
redirect_to action: :show, id: record.id
|
40
|
+
end
|
41
|
+
|
42
|
+
def destroy
|
43
|
+
@record.destroy
|
44
|
+
|
45
|
+
redirect_to action: :index, model: params[:model]
|
46
|
+
end
|
47
|
+
|
48
|
+
private
|
49
|
+
|
50
|
+
def get_record
|
51
|
+
@record = @model.find(params[:id])
|
52
|
+
end
|
53
|
+
|
54
|
+
def get_meta_model
|
55
|
+
@meta_model = Model.where(class_name: model_param_class_name).first if model_param_class_name
|
56
|
+
end
|
57
|
+
|
58
|
+
def get_model
|
59
|
+
@model = "MetaModel::#{model_param_class_name}".constantize if model_param_class_name
|
60
|
+
end
|
61
|
+
|
62
|
+
def model_param_class_name
|
63
|
+
if params[:model]
|
64
|
+
@model_param_class_name ||= params[:model].classify
|
65
|
+
end
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
module MetaModel
|
2
|
+
module ApplicationHelper
|
3
|
+
def action_and_controller_javascript_include_tag
|
4
|
+
capture do
|
5
|
+
concat javascript_include_tag controller_path if Rails.root.join("app/assets/javascripts/#{controller_path}.js.coffee").exist?
|
6
|
+
concat javascript_include_tag "#{controller_path}/#{action_name}" if Rails.root.join("app/assets/javascripts/#{controller_path}/#{action_name}.js.coffee").exist?
|
7
|
+
end
|
8
|
+
end
|
9
|
+
end
|
10
|
+
end
|
@@ -0,0 +1,43 @@
|
|
1
|
+
module MetaModel
|
2
|
+
module ModelBase
|
3
|
+
extend ActiveSupport::Concern
|
4
|
+
|
5
|
+
LOADED_CLASSES = []
|
6
|
+
included do |base|
|
7
|
+
LOADED_CLASSES << self
|
8
|
+
end
|
9
|
+
|
10
|
+
module ClassMethods
|
11
|
+
def inherited(base)
|
12
|
+
LOADED_CLASSES << base
|
13
|
+
end
|
14
|
+
|
15
|
+
def meta_model_class
|
16
|
+
name.gsub(/^MetaModel::/, '')
|
17
|
+
end
|
18
|
+
|
19
|
+
def naming_column
|
20
|
+
# Probably want to allow the user to choose this
|
21
|
+
MetaModel::Model.where(class_name: meta_model_class).first.properties.detect {|p| p.type == 'String' }.name
|
22
|
+
end
|
23
|
+
end
|
24
|
+
|
25
|
+
def naming_column_value
|
26
|
+
self.read_attribute(self.class.naming_column)
|
27
|
+
end
|
28
|
+
|
29
|
+
def meta_model_class
|
30
|
+
self.class.meta_model_class
|
31
|
+
end
|
32
|
+
|
33
|
+
def association_values
|
34
|
+
self.class.associations.each_with_object({}) do |(key, _), result|
|
35
|
+
result[key] = self.send(key)
|
36
|
+
end
|
37
|
+
end
|
38
|
+
|
39
|
+
def _description
|
40
|
+
self.try(:name) || self.try(:name) || self.try(:description) || self.id
|
41
|
+
end
|
42
|
+
end
|
43
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module MetaModel
|
2
|
+
class HasAssociation
|
3
|
+
include Neo4j::ActiveRel
|
4
|
+
|
5
|
+
from_class 'MetaModel::Model'
|
6
|
+
to_class 'MetaModel::Model'
|
7
|
+
type 'has_association_to'
|
8
|
+
|
9
|
+
|
10
|
+
# one_to_many refers to from_class has_many to_classes
|
11
|
+
# many_to_one refers to from_class has_one to_class
|
12
|
+
property :join_type, type: String
|
13
|
+
validates_inclusion_of :join_type, :in => %w( many_to_one one_to_many many_to_many )
|
14
|
+
|
15
|
+
# Name of associations on each side
|
16
|
+
property :name, type: String
|
17
|
+
property :opposite_name, type: String
|
18
|
+
|
19
|
+
property :relationship_type, type: String
|
20
|
+
|
21
|
+
def from_model
|
22
|
+
from_node
|
23
|
+
end
|
24
|
+
|
25
|
+
def to_model
|
26
|
+
to_node
|
27
|
+
end
|
28
|
+
|
29
|
+
def from_model=(other)
|
30
|
+
self.from_node = other
|
31
|
+
end
|
32
|
+
|
33
|
+
def to_model=(other)
|
34
|
+
self.to_node = other
|
35
|
+
end
|
36
|
+
|
37
|
+
def from_model_id=(id)
|
38
|
+
self.from_model = Model.find(id)
|
39
|
+
end
|
40
|
+
|
41
|
+
def to_model_id=(id)
|
42
|
+
self.to_model = Model.find(id)
|
43
|
+
end
|
44
|
+
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,51 @@
|
|
1
|
+
module MetaModel
|
2
|
+
class Model < MetaModelBase
|
3
|
+
property :class_name, type: String
|
4
|
+
|
5
|
+
has_one :out, :superclass_model, type: :inherits_from, model_class: 'MetaModel::Model'
|
6
|
+
|
7
|
+
has_one :out, :id_property, type: :has_id_property, model_class: 'MetaModel::Property'
|
8
|
+
has_many :out, :properties, type: :has_property, model_class: 'MetaModel::Property'
|
9
|
+
|
10
|
+
has_many :both, :assocs, model_class: 'MetaModel::Model', rel_class: 'MetaModel::HasAssociation'
|
11
|
+
|
12
|
+
before_destroy :destroy_properties
|
13
|
+
|
14
|
+
def to_param
|
15
|
+
self.class_name.tableize
|
16
|
+
end
|
17
|
+
|
18
|
+
# def property_ids
|
19
|
+
# properties(:p).pluck(p: :uuid)
|
20
|
+
# end
|
21
|
+
|
22
|
+
def has_associations
|
23
|
+
assocs.each_rel.to_a
|
24
|
+
end
|
25
|
+
|
26
|
+
def self.hierarchically
|
27
|
+
Hash.new.tap do |result|
|
28
|
+
model_parents = Hash[*all.query_as(:model).optional_match("model-[:inherits_from]->(parent)").pluck(:model, :parent).flatten]
|
29
|
+
|
30
|
+
all.query_as(:model).where('NOT(model-[:inherits_from]->())').pluck(:model).each do |model|
|
31
|
+
result[model] = {}
|
32
|
+
end
|
33
|
+
|
34
|
+
all.query_as(:model).match('p=model-[:inherits_from*1..]->()').pluck('nodes(p)').each do |path|
|
35
|
+
path.reverse.inject(result) do |sub_result, model|
|
36
|
+
sub_result[model] ||= {}
|
37
|
+
sub_result[model]
|
38
|
+
end
|
39
|
+
end
|
40
|
+
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def destroy_properties
|
47
|
+
properties.each(&:destroy)
|
48
|
+
id_property.try(:destroy)
|
49
|
+
end
|
50
|
+
end
|
51
|
+
end
|
@@ -0,0 +1,11 @@
|
|
1
|
+
module MetaModel
|
2
|
+
class Property < MetaModelBase
|
3
|
+
property :name, type: String
|
4
|
+
property :type, type: String
|
5
|
+
|
6
|
+
validates_inclusion_of :type, :in => %w( String DateTime Boolean Integer )
|
7
|
+
|
8
|
+
has_one :in, :model, origin: :properties, model_class: 'MetaModel::Model'
|
9
|
+
|
10
|
+
end
|
11
|
+
end
|
@@ -0,0 +1,13 @@
|
|
1
|
+
module MetaModel
|
2
|
+
class HasAssociationSerializer < ActiveModel::Serializer
|
3
|
+
attributes :id, :join_type, :name, :opposite_name, :relationship_type, :from_model, :to_model
|
4
|
+
|
5
|
+
def from_model
|
6
|
+
object.from_node.id
|
7
|
+
end
|
8
|
+
|
9
|
+
def to_model
|
10
|
+
object.to_node.id
|
11
|
+
end
|
12
|
+
end
|
13
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
doctype html
|
2
|
+
html
|
3
|
+
head
|
4
|
+
title MetaModel
|
5
|
+
|
6
|
+
javascript:
|
7
|
+
var meta_model_root_path = '#{root_path}';
|
8
|
+
|
9
|
+
= stylesheet_link_tag 'meta_model', media: 'all'
|
10
|
+
= javascript_include_tag 'meta_model'
|
11
|
+
|
12
|
+
= csrf_meta_tags
|
13
|
+
|
14
|
+
body
|
15
|
+
nav.navbar.navbar-default role="navigation"
|
16
|
+
.container-fluid
|
17
|
+
ul.nav.navbar-nav
|
18
|
+
li
|
19
|
+
= link_to 'Models', root_path
|
20
|
+
|
21
|
+
li
|
22
|
+
= link_to 'Admin', meta_path
|
23
|
+
|
24
|
+
.container
|
25
|
+
= yield
|
26
|
+
|
27
|
+
= action_and_controller_javascript_include_tag
|
28
|
+
|
@@ -0,0 +1,12 @@
|
|
1
|
+
|
2
|
+
table
|
3
|
+
- @has_associations.each do |has_association|
|
4
|
+
tr
|
5
|
+
td = link_to 'Edit', action: :edit, id: has_association.id
|
6
|
+
td = has_association.from_node.class_name
|
7
|
+
td -
|
8
|
+
td = has_association.relationship_type
|
9
|
+
td = has_association.join_type
|
10
|
+
td ->
|
11
|
+
td = has_association.to_node.class_name
|
12
|
+
|
@@ -0,0 +1,39 @@
|
|
1
|
+
= form_tag({action: :update}, method: :put, class: 'form-horizontal', role: :form) do
|
2
|
+
|
3
|
+
.form-group
|
4
|
+
label
|
5
|
+
.col-sm-2.control-label Class Name
|
6
|
+
.col-sm-10 = text_field_tag 'model_data[class_name]', @model.class_name, class: 'form-control'
|
7
|
+
|
8
|
+
.form-group
|
9
|
+
label
|
10
|
+
.col-sm-2.control-label Inherits from
|
11
|
+
.col-sm-10 = select_tag 'model_data[superclass_model]', options_from_collection_for_select(([OpenStruct.new] + @models.to_a), 'class_name', 'class_name', @model.superclass_model.try(:class_name)), class: 'form-control'
|
12
|
+
|
13
|
+
.properties.row
|
14
|
+
h2
|
15
|
+
| Properties
|
16
|
+
a.add.btn.btn-default Add Property
|
17
|
+
|
18
|
+
- @model.properties.each do |property|
|
19
|
+
.well.property.col-sm-6
|
20
|
+
i.glyphicon.glyphicon-remove-circle.close.pull-right
|
21
|
+
|
22
|
+
.form-group
|
23
|
+
label
|
24
|
+
.col-sm-2.control-label Name
|
25
|
+
.col-sm-10 = text_field_tag 'model_data[properties][][name]', property.name, class: 'form-control'
|
26
|
+
|
27
|
+
.form-group
|
28
|
+
label
|
29
|
+
.col-sm-2.control-label Type
|
30
|
+
.col-sm-10 = select_tag 'model_data[properties][][type]', options_for_select(['String', 'DateTime'], property.type), class: 'form-control'
|
31
|
+
|
32
|
+
|
33
|
+
.form-group
|
34
|
+
= submit_tag 'Update', class: 'btn btn-primary'
|
35
|
+
|
36
|
+
scss:
|
37
|
+
label {
|
38
|
+
width: 100%;
|
39
|
+
}
|
@@ -0,0 +1,72 @@
|
|
1
|
+
- record.attributes.each do |key, value|
|
2
|
+
.form-group
|
3
|
+
label.control-label.col-sm-2 = key.humanize
|
4
|
+
.col-sm-10 = text_field_tag "data[#{key}]", value, class: 'form-control'
|
5
|
+
|
6
|
+
- record.class.associations.each do |key, association|
|
7
|
+
.form-group
|
8
|
+
label.control-label.col-sm-2 = key.to_s.humanize
|
9
|
+
.col-sm-10
|
10
|
+
- case association.type
|
11
|
+
- when :has_one
|
12
|
+
= select_tag "data[#{key}]", options_from_collection_for_select(association.target_class.all.to_a, :id, :naming_column_value, record.send(key).id), class: 'form-control'
|
13
|
+
- when :has_many
|
14
|
+
.has-many-association data-option-type="#{association.target_class.meta_model_class.tableize.singularize}" data-options="#{association.target_class.all.to_json(methods: :naming_column_value)}"
|
15
|
+
select.form-control rv-on-change="view.add"
|
16
|
+
option Please select
|
17
|
+
option rv-each-option="view.current_options < objects" rv-value="option.id"
|
18
|
+
| { option.naming_column_value }
|
19
|
+
|
20
|
+
.list-group
|
21
|
+
a.list-group-item rv-each-object="objects < objects" rv-data-id="object.id" rv-on-click="view.delete"
|
22
|
+
input type="hidden" name="data[#{key}][]" rv-value="object.id"
|
23
|
+
| { object.naming_column_value }
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
coffee:
|
28
|
+
|
29
|
+
class HasManyAssociationView extends Backbone.View
|
30
|
+
el: '.has-many-association'
|
31
|
+
|
32
|
+
initialize: ->
|
33
|
+
el = $(@el)
|
34
|
+
@options = _(el.data('options')).map((element) ->
|
35
|
+
element[el.data('option-type')]
|
36
|
+
).value()
|
37
|
+
|
38
|
+
@objects = [@options[0]]
|
39
|
+
|
40
|
+
render: ->
|
41
|
+
@binding = rivets.bind $(@el), {@objects, view: @}
|
42
|
+
|
43
|
+
@
|
44
|
+
|
45
|
+
remove: ->
|
46
|
+
@binding.unbind()
|
47
|
+
|
48
|
+
current_options: =>
|
49
|
+
console.log('current_options!');
|
50
|
+
_(@options).difference(@objects).value()
|
51
|
+
|
52
|
+
|
53
|
+
add: (event, object) =>
|
54
|
+
selected_id = $(event.target).val()
|
55
|
+
selected_option = _(@options).find((option) -> option.id is selected_id)
|
56
|
+
|
57
|
+
@objects.push selected_option
|
58
|
+
|
59
|
+
$(@el).find('select option').removeAttr('selected')
|
60
|
+
|
61
|
+
delete: (event, object) =>
|
62
|
+
selected_id = $(event.target).data('id')
|
63
|
+
selected_object = _(@options).find((option) -> option.id is selected_id)
|
64
|
+
|
65
|
+
index = _(@objects).indexOf(selected_object)
|
66
|
+
@objects.removeAt(index)
|
67
|
+
|
68
|
+
ready = ->
|
69
|
+
new HasManyAssociationView().render()
|
70
|
+
|
71
|
+
$('document').ready ready
|
72
|
+
$('document').on 'page:load', ready
|
@@ -0,0 +1,13 @@
|
|
1
|
+
- link ||= false
|
2
|
+
|
3
|
+
= link_to 'View', {action: :show, model: record.meta_model_class.to_s.tableize, id: record.id}, class: 'btn btn-default' if link
|
4
|
+
|
5
|
+
= link_to 'Edit', {action: :edit, model: record.meta_model_class.to_s.tableize, id: record.id}, class: 'btn btn-default'
|
6
|
+
|
7
|
+
= button_to 'Delete', {action: :destroy, model: record.meta_model_class.to_s.tableize, id: record.id}, method: :delete, class: 'btn btn-danger pull-right'
|
8
|
+
|
9
|
+
dl.dl-horizontal
|
10
|
+
- record.attributes.each do |key, value|
|
11
|
+
dt = key
|
12
|
+
dd = value
|
13
|
+
|
@@ -0,0 +1,14 @@
|
|
1
|
+
ol.breadcrumb
|
2
|
+
li = link_to 'Models', root_path
|
3
|
+
li = @meta_model.class_name.pluralize
|
4
|
+
|
5
|
+
h2 = @meta_model.class_name.pluralize
|
6
|
+
|
7
|
+
= link_to 'Add', new_model_path(model: @meta_model)
|
8
|
+
|
9
|
+
div.list-group
|
10
|
+
- @records.each do |record|
|
11
|
+
= link_to model_path(id: record), class: 'list-group-item' do
|
12
|
+
- if record.class != @model
|
13
|
+
span.badge = record.class.to_s
|
14
|
+
= record._description
|
@@ -0,0 +1,18 @@
|
|
1
|
+
ol.breadcrumb
|
2
|
+
li = link_to 'Models', root_path
|
3
|
+
li = link_to @meta_model.class_name.pluralize, models_path(model: @meta_model.class_name)
|
4
|
+
li = @record._description
|
5
|
+
|
6
|
+
= render partial: 'record_details', locals: {record: @record}
|
7
|
+
|
8
|
+
- @model.associations.each do |name, association|
|
9
|
+
- logger.warn "@record: #{@record.inspect}"
|
10
|
+
- logger.warn "name: #{name.inspect}"
|
11
|
+
- result = @record.send(name)
|
12
|
+
- result = result.respond_to?(:each) ? result.to_a : (result ? [result] : [])
|
13
|
+
- if result.present?
|
14
|
+
h2 = name.to_s.humanize
|
15
|
+
div
|
16
|
+
- result.each do |sub_record|
|
17
|
+
= render partial: 'record_details', locals: {record: sub_record, link: true}
|
18
|
+
|
data/config/routes.rb
ADDED
@@ -0,0 +1,19 @@
|
|
1
|
+
MetaModel::Engine.routes.draw do
|
2
|
+
namespace :meta do
|
3
|
+
resources :models do
|
4
|
+
collection do
|
5
|
+
get :hierarchy
|
6
|
+
end
|
7
|
+
end
|
8
|
+
resources :properties
|
9
|
+
resources :has_associations#, path: '/associations'#, param: :asso
|
10
|
+
end
|
11
|
+
|
12
|
+
get '/meta' => 'meta#index'
|
13
|
+
|
14
|
+
|
15
|
+
resources :models, path: '/:model'
|
16
|
+
|
17
|
+
root 'models#meta_index'#, as: :meta_models
|
18
|
+
end
|
19
|
+
|