vimo 0.1.0
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.md +133 -0
- data/Rakefile +38 -0
- data/app/assets/config/vimo_manifest.js +2 -0
- data/app/assets/javascripts/vimo/application.js +13 -0
- data/app/assets/javascripts/vimo/entities.js +2 -0
- data/app/assets/javascripts/vimo/items.js +2 -0
- data/app/assets/stylesheets/vimo/application.css +15 -0
- data/app/assets/stylesheets/vimo/entities.css +4 -0
- data/app/assets/stylesheets/vimo/items.css +4 -0
- data/app/controllers/vimo/application_controller.rb +60 -0
- data/app/controllers/vimo/entities_controller.rb +46 -0
- data/app/controllers/vimo/items_controller.rb +62 -0
- data/app/helpers/vimo/application_helper.rb +6 -0
- data/app/helpers/vimo/entities_helper.rb +6 -0
- data/app/helpers/vimo/items_helper.rb +6 -0
- data/app/jobs/vimo/application_job.rb +6 -0
- data/app/mailers/vimo/application_mailer.rb +8 -0
- data/app/models/vimo/application_record.rb +7 -0
- data/app/models/vimo/entity.rb +23 -0
- data/app/models/vimo/field.rb +11 -0
- data/app/models/vimo/item.rb +76 -0
- data/app/models/vimo/system_name.rb +55 -0
- data/app/views/layouts/vimo/application.html.erb +14 -0
- data/config/locales/responders.en.yml +12 -0
- data/config/routes.rb +12 -0
- data/config/spring.rb +3 -0
- data/db/migrate/20180208181633_create_vimo_entities.rb +14 -0
- data/db/migrate/20180208182202_create_vimo_fields.rb +16 -0
- data/db/migrate/20180210104430_create_vimo_items.rb +11 -0
- data/lib/application_responder.rb +10 -0
- data/lib/string_ext.rb +9 -0
- data/lib/tasks/vimo_tasks.rake +5 -0
- data/lib/vimo/configuration.rb +15 -0
- data/lib/vimo/engine.rb +16 -0
- data/lib/vimo/version.rb +5 -0
- data/lib/vimo.rb +22 -0
- metadata +193 -0
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: 9beb8222f16151d7206ffc95d411d4fc938b0400ce600c4459f859c5033d9c11
|
4
|
+
data.tar.gz: d71f8f015000aba75e62898fc0427eafbe8755365f1f5ba0c0ab50f670b402cb
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 843107fe2c31cd2e395143a7b3213e849a1101506f7b3fb3bed8f4d1a21370a1192334631b3ca7f2bb169dc8af69a2541d858ac4ec44d59b04efa1f9ddef2379
|
7
|
+
data.tar.gz: 05f071ac5dd731b500d9d66c3a863d8491e3b00d23637b2b02caf43642eb3fbc01300ed385d179670d0f08ac4c59868ef23a8216ca92d3151e1f82ac8ae62f54
|
data/MIT-LICENSE
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright 2018 Jose Galisteo
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.md
ADDED
@@ -0,0 +1,133 @@
|
|
1
|
+
# Vimo
|
2
|
+
|
3
|
+
Rails engine that allow to your users create and customize their own virtual models.
|
4
|
+
|
5
|
+
## Warning
|
6
|
+
|
7
|
+
This engine is in a very early stage and the DSL and APIs could change, if you
|
8
|
+
are interesed on use it you can emailme: `ceritium@gmail.com`.
|
9
|
+
|
10
|
+
## Installation
|
11
|
+
|
12
|
+
Add this line to your application's Gemfile:
|
13
|
+
|
14
|
+
```ruby
|
15
|
+
gem 'vimo'
|
16
|
+
```
|
17
|
+
|
18
|
+
And then execute:
|
19
|
+
```bash
|
20
|
+
$ bundle
|
21
|
+
```
|
22
|
+
|
23
|
+
Or install it yourself as:
|
24
|
+
```bash
|
25
|
+
$ gem install vimo
|
26
|
+
```
|
27
|
+
|
28
|
+
## Usage
|
29
|
+
|
30
|
+
### Expose the manage API
|
31
|
+
|
32
|
+
Add `mount Vimo::Engine => "/vimo"` in `config/routers.rb` to expose an restfull
|
33
|
+
API to manage the virtual models and their contents.
|
34
|
+
|
35
|
+
CRUD of entities, where `:entity` is the `id` or `system_name` of the entity.
|
36
|
+
```
|
37
|
+
GET /vimo/entities
|
38
|
+
POST /vimo/entities
|
39
|
+
GET /vimo/entities/:entity
|
40
|
+
PATCH /vimo/entities/:entity
|
41
|
+
PUT /vimo/entities/:entity
|
42
|
+
DELETE /vimo/entities/:entity
|
43
|
+
```
|
44
|
+
|
45
|
+
Entity attributes:
|
46
|
+
```
|
47
|
+
{
|
48
|
+
"name": "posts", # required
|
49
|
+
"system_name": "posts", # unique per owner
|
50
|
+
"field_attributes": {
|
51
|
+
"id": 42, # just for update
|
52
|
+
"name": "title", # required
|
53
|
+
"kind": "string", # required, options: string, integer, float, boolean, date or datetime
|
54
|
+
"required": true, # options: true or false
|
55
|
+
"_destroy": false, # just for update, mark to destroy the field, options: true or false
|
56
|
+
}
|
57
|
+
}
|
58
|
+
|
59
|
+
```
|
60
|
+
|
61
|
+
Create an entity curl example:
|
62
|
+
```
|
63
|
+
curl localhost:3000/vimo/entities -X POST -H 'Content-Type: application/json' -d '{"entity": {"name": "comments", "fields_attributes": [{"name": "title", "kind": "string", "required": true}]}}'
|
64
|
+
```
|
65
|
+
|
66
|
+
CRUD for your virtual models:
|
67
|
+
```
|
68
|
+
GET /vimo/entities/:entity/items
|
69
|
+
POST /vimo/entities/:entity/items
|
70
|
+
GET /vimo/entities/:entity/items/:id
|
71
|
+
PATCH /vimo/entities/:entity/items/:id
|
72
|
+
PUT /vimo/entities/:entity/items/:id
|
73
|
+
DELETE /vimo/entities/:entity/items/:id
|
74
|
+
```
|
75
|
+
|
76
|
+
Create an item curl example:
|
77
|
+
```
|
78
|
+
curl localhost:3000/vimo/entities/comments/items -X POST -H 'Content-Type: application/json' -d '{"title": "a title"}'
|
79
|
+
```
|
80
|
+
|
81
|
+
Short path version
|
82
|
+
```
|
83
|
+
GET /vimo/resources/:entity
|
84
|
+
POST /vimo/resources/:entity
|
85
|
+
GET /vimo/resources/:entity/:id
|
86
|
+
PATCH /vimo/resources/:entity/:id
|
87
|
+
PUT /vimo/resources/:entity/:id
|
88
|
+
DELETE /vimo/resources/:entity/:id
|
89
|
+
```
|
90
|
+
|
91
|
+
### API authentication
|
92
|
+
|
93
|
+
Vimo allow you to authenticate and set ownership to your models.
|
94
|
+
|
95
|
+
```ruby
|
96
|
+
Vimo.configure do |config|
|
97
|
+
|
98
|
+
# The name of the before filter we'll call to authenticate the current user.
|
99
|
+
# Defaults to :login_required
|
100
|
+
config.authentication_method = :authenticate!
|
101
|
+
|
102
|
+
# The name of the controller method we'll call to return the owner for
|
103
|
+
# the virtual models.
|
104
|
+
config.owner_method = :current_account
|
105
|
+
end
|
106
|
+
```
|
107
|
+
|
108
|
+
Setting a `owner` scope the uniquenes constraints.
|
109
|
+
|
110
|
+
|
111
|
+
### Expand your models
|
112
|
+
|
113
|
+
Having a model like `Post` that belongs to an `Account` you can allow to your
|
114
|
+
users expand it.
|
115
|
+
|
116
|
+
```ruby
|
117
|
+
class Post < ApplicationRecord
|
118
|
+
belongs_to :account
|
119
|
+
|
120
|
+
extendable owner: :account
|
121
|
+
end
|
122
|
+
```
|
123
|
+
|
124
|
+
Now can manage the virtual attributes of the model `Post` with the identifier `_extend_posts`.
|
125
|
+
|
126
|
+
|
127
|
+
WIP
|
128
|
+
|
129
|
+
## Contributing
|
130
|
+
Contribution directions go here.
|
131
|
+
|
132
|
+
## License
|
133
|
+
The gem is available as open source under the terms of the [MIT License](http://opensource.org/licenses/MIT).
|
data/Rakefile
ADDED
@@ -0,0 +1,38 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
begin
|
4
|
+
require "bundler/setup"
|
5
|
+
rescue LoadError
|
6
|
+
puts "You must `gem install bundler` and `bundle install` to run rake tasks"
|
7
|
+
end
|
8
|
+
|
9
|
+
require "rdoc/task"
|
10
|
+
|
11
|
+
RDoc::Task.new(:rdoc) do |rdoc|
|
12
|
+
rdoc.rdoc_dir = "rdoc"
|
13
|
+
rdoc.title = "Vimo"
|
14
|
+
rdoc.options << "--line-numbers"
|
15
|
+
rdoc.rdoc_files.include("README.md")
|
16
|
+
rdoc.rdoc_files.include("lib/**/*.rb")
|
17
|
+
end
|
18
|
+
|
19
|
+
APP_RAKEFILE = File.expand_path("../test/dummy/Rakefile", __FILE__)
|
20
|
+
load "rails/tasks/engine.rake"
|
21
|
+
|
22
|
+
|
23
|
+
load "rails/tasks/statistics.rake"
|
24
|
+
|
25
|
+
|
26
|
+
|
27
|
+
require "bundler/gem_tasks"
|
28
|
+
|
29
|
+
require "rake/testtask"
|
30
|
+
|
31
|
+
Rake::TestTask.new(:test) do |t|
|
32
|
+
t.libs << "test"
|
33
|
+
t.pattern = "test/**/*_test.rb"
|
34
|
+
t.verbose = false
|
35
|
+
end
|
36
|
+
|
37
|
+
|
38
|
+
task default: :test
|
@@ -0,0 +1,13 @@
|
|
1
|
+
// This is a manifest file that'll be compiled into application.js, which will include all the files
|
2
|
+
// listed below.
|
3
|
+
//
|
4
|
+
// Any JavaScript/Coffee file within this directory, lib/assets/javascripts, vendor/assets/javascripts,
|
5
|
+
// or any plugin's vendor/assets/javascripts directory can be referenced here using a relative path.
|
6
|
+
//
|
7
|
+
// It's not advisable to add code directly here, but if you do, it'll appear at the bottom of the
|
8
|
+
// compiled file. JavaScript code in this file should be added after the last require_* statement.
|
9
|
+
//
|
10
|
+
// Read Sprockets README (https://github.com/rails/sprockets#sprockets-directives) for details
|
11
|
+
// about supported directives.
|
12
|
+
//
|
13
|
+
//= require_tree .
|
@@ -0,0 +1,15 @@
|
|
1
|
+
/*
|
2
|
+
* This is a manifest file that'll be compiled into application.css, which will include all the files
|
3
|
+
* listed below.
|
4
|
+
*
|
5
|
+
* Any CSS and SCSS file within this directory, lib/assets/stylesheets, vendor/assets/stylesheets,
|
6
|
+
* or any plugin's vendor/assets/stylesheets directory can be referenced here using a relative path.
|
7
|
+
*
|
8
|
+
* You're free to add application-wide styles to this file and they'll appear at the bottom of the
|
9
|
+
* compiled file so the styles you add here take precedence over styles defined in any other CSS/SCSS
|
10
|
+
* files in this directory. Styles in this file should be added after the last require_* statement.
|
11
|
+
* It is generally better to create a new file per style scope.
|
12
|
+
*
|
13
|
+
*= require_tree .
|
14
|
+
*= require_self
|
15
|
+
*/
|
@@ -0,0 +1,60 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "application_responder"
|
4
|
+
|
5
|
+
module Vimo
|
6
|
+
class ApplicationController < ::ApplicationController
|
7
|
+
protect_from_forgery with: :exception
|
8
|
+
responders Responders::PaginateResponder
|
9
|
+
respond_to :json
|
10
|
+
|
11
|
+
before_action :authentication_filter
|
12
|
+
|
13
|
+
def page
|
14
|
+
params[:page].to_i
|
15
|
+
end
|
16
|
+
|
17
|
+
def per_page
|
18
|
+
50
|
19
|
+
end
|
20
|
+
|
21
|
+
def max_per_page
|
22
|
+
per_page
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def entities_scope
|
28
|
+
owner ? owner.send(vimo_conf.entities_method) : Entity
|
29
|
+
end
|
30
|
+
|
31
|
+
def owner
|
32
|
+
if owner_method
|
33
|
+
send(owner_method)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def authentication_filter
|
38
|
+
meth = vimo_conf.authentication_method
|
39
|
+
if meth
|
40
|
+
send(meth)
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
def owner_method
|
45
|
+
vimo_conf.owner_method
|
46
|
+
end
|
47
|
+
|
48
|
+
# A helper method to access the BlogDashboard::configuration
|
49
|
+
# at the class level
|
50
|
+
def self.vimo_conf
|
51
|
+
Vimo::configuration
|
52
|
+
end
|
53
|
+
|
54
|
+
# A helper method to access the BlogDashboard::configuration
|
55
|
+
# at the controller instance level
|
56
|
+
def vimo_conf
|
57
|
+
self.class.vimo_conf
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency "vimo/application_controller"
|
4
|
+
|
5
|
+
module Vimo
|
6
|
+
class EntitiesController < ApplicationController
|
7
|
+
skip_before_action :verify_authenticity_token
|
8
|
+
before_action :find_entity, only: [:show, :update, :destroy]
|
9
|
+
|
10
|
+
def index
|
11
|
+
@entities = entities_scope.page(page).per(per_page)
|
12
|
+
respond_with @entities
|
13
|
+
end
|
14
|
+
|
15
|
+
def show
|
16
|
+
respond_with @entity
|
17
|
+
end
|
18
|
+
|
19
|
+
def create
|
20
|
+
@entity = entities_scope.create(entity_params)
|
21
|
+
respond_with @entity
|
22
|
+
end
|
23
|
+
|
24
|
+
def update
|
25
|
+
@entity.update(entity_params)
|
26
|
+
respond_with @entity
|
27
|
+
end
|
28
|
+
|
29
|
+
def destroy
|
30
|
+
@entity.destroy
|
31
|
+
respond_with @entity
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def find_entity
|
37
|
+
@entity = entities_scope.find(params[:id])
|
38
|
+
end
|
39
|
+
|
40
|
+
def entity_params
|
41
|
+
params.require(:entity).
|
42
|
+
permit(:name, :system_name,
|
43
|
+
fields_attributes: [:id, :name, :kind, :required, :_destroy])
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require_dependency "vimo/application_controller"
|
4
|
+
|
5
|
+
module Vimo
|
6
|
+
class ItemsController < ApplicationController
|
7
|
+
skip_before_action :verify_authenticity_token
|
8
|
+
before_action :find_entity
|
9
|
+
before_action :find_item, only: [:show, :update, :destroy]
|
10
|
+
|
11
|
+
def index
|
12
|
+
@items = @entity.items.page(page).per(per_page)
|
13
|
+
respond_with @entity, @items
|
14
|
+
end
|
15
|
+
|
16
|
+
def show
|
17
|
+
respond_with @entity, @item
|
18
|
+
end
|
19
|
+
|
20
|
+
def create
|
21
|
+
@item = items.build
|
22
|
+
save_and_respond
|
23
|
+
end
|
24
|
+
|
25
|
+
def update
|
26
|
+
save_and_respond
|
27
|
+
end
|
28
|
+
|
29
|
+
def destroy
|
30
|
+
@item.destroy
|
31
|
+
respond_with @entity, @item
|
32
|
+
end
|
33
|
+
|
34
|
+
private
|
35
|
+
|
36
|
+
def save_and_respond
|
37
|
+
@item.assign_params(params)
|
38
|
+
@item.save
|
39
|
+
|
40
|
+
respond_with @entity, @item
|
41
|
+
end
|
42
|
+
|
43
|
+
def find_entity
|
44
|
+
entity_id = params[:entity_id]
|
45
|
+
|
46
|
+
@entity = entities_scope.find_by(id: entity_id) ||
|
47
|
+
entities_scope.find_by!(system_name: entity_id)
|
48
|
+
end
|
49
|
+
|
50
|
+
def find_item
|
51
|
+
@item = items.find(params[:id])
|
52
|
+
end
|
53
|
+
|
54
|
+
def items
|
55
|
+
@entity.items
|
56
|
+
end
|
57
|
+
|
58
|
+
def not_found
|
59
|
+
render json: { error: "not_found" }, status: :not_found
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,23 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Vimo
|
4
|
+
class Entity < ApplicationRecord
|
5
|
+
include SystemName
|
6
|
+
|
7
|
+
validates :name, presence: true
|
8
|
+
|
9
|
+
has_system_name uniqueness_scope: [:owner_type, :owner_id]
|
10
|
+
|
11
|
+
has_many :fields
|
12
|
+
has_many :items
|
13
|
+
belongs_to :owner, polymorphic: true, required: false
|
14
|
+
|
15
|
+
accepts_nested_attributes_for :fields,
|
16
|
+
reject_if: :all_blank,
|
17
|
+
allow_destroy: true
|
18
|
+
|
19
|
+
def as_json(options = nil)
|
20
|
+
super(options.merge(include: :fields))
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Vimo
|
4
|
+
class Item < ApplicationRecord
|
5
|
+
serialize :data, JSON
|
6
|
+
belongs_to :entity
|
7
|
+
belongs_to :extendable, polymorphic: true, required: false
|
8
|
+
|
9
|
+
validate :entity_definition
|
10
|
+
|
11
|
+
class << self
|
12
|
+
def parse(value_o, kind)
|
13
|
+
value = value_o.to_s
|
14
|
+
begin
|
15
|
+
case kind
|
16
|
+
when :string
|
17
|
+
value.to_s
|
18
|
+
when :integer
|
19
|
+
value.to_i
|
20
|
+
when :float
|
21
|
+
value.to_f
|
22
|
+
when :boolean
|
23
|
+
value.to_bool unless value_o.nil?
|
24
|
+
when :date
|
25
|
+
Date.parse(value).to_date.to_s(:db)
|
26
|
+
when :datetime
|
27
|
+
DateTime.constantize.parse(value).to_datetime.to_s(:db)
|
28
|
+
else
|
29
|
+
value
|
30
|
+
end
|
31
|
+
rescue => e
|
32
|
+
puts e
|
33
|
+
nil
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
|
38
|
+
def data
|
39
|
+
read_attribute(:data) || {}
|
40
|
+
end
|
41
|
+
|
42
|
+
def as_json(options = nil)
|
43
|
+
({ id: id }).merge(data)
|
44
|
+
end
|
45
|
+
|
46
|
+
def assign_params(params)
|
47
|
+
self.data ||= {}
|
48
|
+
self.data = entity.fields.inject(self.data) do |memo, field|
|
49
|
+
|
50
|
+
name = field.name.to_s
|
51
|
+
kind = field.kind.to_s
|
52
|
+
|
53
|
+
att = params[name]
|
54
|
+
if params.keys.include?(name)
|
55
|
+
memo[name] = self.class.parse(att, kind)
|
56
|
+
end
|
57
|
+
|
58
|
+
memo
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
private
|
63
|
+
|
64
|
+
def entity_definition
|
65
|
+
self.data ||= {}
|
66
|
+
entity.fields.each do |field|
|
67
|
+
name = field.name.to_s
|
68
|
+
if field.required
|
69
|
+
if self.data[name].to_s.blank?
|
70
|
+
errors.add(name, "is required")
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Vimo
|
4
|
+
module SystemName
|
5
|
+
extend ActiveSupport::Concern
|
6
|
+
|
7
|
+
included do
|
8
|
+
before_validation :generate_system_name, on: :create
|
9
|
+
class_attribute :_system_human_name
|
10
|
+
end
|
11
|
+
|
12
|
+
module ClassMethods
|
13
|
+
def validates_system_name(opts = {})
|
14
|
+
validates :system_name, presence: true, format: { with: /\A\w[\w\-\/]+\z/ }
|
15
|
+
validates :name, presence: true
|
16
|
+
|
17
|
+
if opts[:uniqueness_scope]
|
18
|
+
validates :system_name, uniqueness: opts[:uniqueness_scope] == true ? true : { scope: opts[:uniqueness_scope] }
|
19
|
+
end
|
20
|
+
end
|
21
|
+
|
22
|
+
def has_system_name(opts = {})
|
23
|
+
attr_protected :system_name if opts.delete(:protected)
|
24
|
+
self._system_human_name = opts.delete(:human_name) || :name
|
25
|
+
validates_system_name(opts)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
protected
|
30
|
+
|
31
|
+
def system_human_name
|
32
|
+
send(self._system_human_name)
|
33
|
+
end
|
34
|
+
|
35
|
+
# Generates system_name from 'system_human_name'
|
36
|
+
def generate_system_name
|
37
|
+
generate_system_name! if self.system_name.blank?
|
38
|
+
end
|
39
|
+
|
40
|
+
def generate_system_name!
|
41
|
+
if self.system_human_name.present?
|
42
|
+
slug = self.system_human_name.parameterize
|
43
|
+
self.system_name = slug.blank? ? internal_system_name : slug
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# This method is used when we need to generate a system_name
|
48
|
+
# but ther is no suitable 'name' (human_name) from which
|
49
|
+
# we can guess a reasonable one.
|
50
|
+
#
|
51
|
+
def internal_system_name
|
52
|
+
"#{self.class.to_s}-#{SecureRandom.hex(6)}"
|
53
|
+
end
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,14 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<title>Vimo</title>
|
5
|
+
<%= stylesheet_link_tag "vimo/application", media: "all" %>
|
6
|
+
<%= javascript_include_tag "vimo/application" %>
|
7
|
+
<%= csrf_meta_tags %>
|
8
|
+
</head>
|
9
|
+
<body>
|
10
|
+
|
11
|
+
<%= yield %>
|
12
|
+
|
13
|
+
</body>
|
14
|
+
</html>
|
@@ -0,0 +1,12 @@
|
|
1
|
+
en:
|
2
|
+
flash:
|
3
|
+
actions:
|
4
|
+
create:
|
5
|
+
notice: '%{resource_name} was successfully created.'
|
6
|
+
# alert: '%{resource_name} could not be created.'
|
7
|
+
update:
|
8
|
+
notice: '%{resource_name} was successfully updated.'
|
9
|
+
# alert: '%{resource_name} could not be updated.'
|
10
|
+
destroy:
|
11
|
+
notice: '%{resource_name} was successfully destroyed.'
|
12
|
+
alert: '%{resource_name} could not be destroyed.'
|
data/config/routes.rb
ADDED
@@ -0,0 +1,12 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
Vimo::Engine.routes.draw do
|
4
|
+
defaults format: :json do
|
5
|
+
resources :entities, only: [:index, :show, :create, :update, :destroy] do
|
6
|
+
resources :items, only: [:index, :show, :create, :update, :destroy]
|
7
|
+
end
|
8
|
+
|
9
|
+
resources :items, path: "resources/:entity_id", as: :resource,
|
10
|
+
only: [:index, :show, :create, :update, :destroy]
|
11
|
+
end
|
12
|
+
end
|
data/config/spring.rb
ADDED
@@ -0,0 +1,14 @@
|
|
1
|
+
class CreateVimoEntities < ActiveRecord::Migration[5.0]
|
2
|
+
def change
|
3
|
+
create_table :vimo_entities do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :system_name
|
6
|
+
t.references :owner, polymorphic: true, index: true
|
7
|
+
|
8
|
+
t.timestamps
|
9
|
+
end
|
10
|
+
|
11
|
+
add_index :vimo_entities, [:owner_id, :owner_type, :system_name],
|
12
|
+
unique: true, name: :entity_unique_system_name
|
13
|
+
end
|
14
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
class CreateVimoFields < ActiveRecord::Migration[5.0]
|
2
|
+
def change
|
3
|
+
create_table :vimo_fields do |t|
|
4
|
+
t.string :name
|
5
|
+
t.string :system_name
|
6
|
+
t.integer :kind
|
7
|
+
t.boolean :required
|
8
|
+
t.references :entity, foreign_key: true
|
9
|
+
|
10
|
+
t.timestamps
|
11
|
+
end
|
12
|
+
|
13
|
+
add_index :vimo_fields, [:entity_id, :system_name],
|
14
|
+
unique: true, name: :field_unique_system_name
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,10 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class ApplicationResponder < ActionController::Responder
|
4
|
+
include Responders::FlashResponder
|
5
|
+
include Responders::HttpCacheResponder
|
6
|
+
|
7
|
+
# Redirects resources to the collection path (index action) instead
|
8
|
+
# of the resource path (show action) for POST/PUT/DELETE requests.
|
9
|
+
# include Responders::CollectionResponder
|
10
|
+
end
|
data/lib/string_ext.rb
ADDED
@@ -0,0 +1,9 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
class String
|
4
|
+
def to_bool
|
5
|
+
return true if self == true || self =~ (/(true|t|yes|y|1)$/i)
|
6
|
+
return false if self == false || self.blank? || self =~ (/(false|f|no|n|0)$/i)
|
7
|
+
raise ArgumentError.new("invalid value for Boolean: \"#{self}\"")
|
8
|
+
end
|
9
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Vimo
|
4
|
+
class Configuration
|
5
|
+
attr_accessor :authentication_method
|
6
|
+
attr_accessor :owner_method
|
7
|
+
attr_accessor :entities_method
|
8
|
+
|
9
|
+
def initialize
|
10
|
+
@authentication_method = nil
|
11
|
+
@owner_method = nil
|
12
|
+
@entities_method = :vimo_entities
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
data/lib/vimo/engine.rb
ADDED
@@ -0,0 +1,16 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
module Vimo
|
4
|
+
class Engine < ::Rails::Engine
|
5
|
+
isolate_namespace Vimo
|
6
|
+
|
7
|
+
require "kaminari"
|
8
|
+
require "responders"
|
9
|
+
require "paginate-responder"
|
10
|
+
|
11
|
+
|
12
|
+
initializer "model_core.factories", after: "factory_bot.set_factory_paths" do
|
13
|
+
FactoryBot.definition_file_paths << File.expand_path("../../../test/factories/", __FILE__) if defined?(FactoryBot)
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
data/lib/vimo/version.rb
ADDED
data/lib/vimo.rb
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
# frozen_string_literal: true
|
2
|
+
|
3
|
+
require "vimo/engine"
|
4
|
+
require "vimo/configuration"
|
5
|
+
|
6
|
+
module Vimo
|
7
|
+
# Your code goes here...
|
8
|
+
|
9
|
+
class ConfigurationError < StandardError; end
|
10
|
+
|
11
|
+
# Set global configuration options for I18nDashboard
|
12
|
+
# @see README.md
|
13
|
+
def self.configure(&block)
|
14
|
+
block.call(configuration)
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns I18nDashboard's globalconfiguration. Will initialize a new instance
|
18
|
+
# if not already set
|
19
|
+
def self.configuration
|
20
|
+
@configuration ||= Configuration.new
|
21
|
+
end
|
22
|
+
end
|
metadata
ADDED
@@ -0,0 +1,193 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: vimo
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.1.0
|
5
|
+
platform: ruby
|
6
|
+
authors:
|
7
|
+
- Jose Galisteo
|
8
|
+
autorequire:
|
9
|
+
bindir: bin
|
10
|
+
cert_chain: []
|
11
|
+
date: 2018-02-18 00:00:00.000000000 Z
|
12
|
+
dependencies:
|
13
|
+
- !ruby/object:Gem::Dependency
|
14
|
+
name: kaminari
|
15
|
+
requirement: !ruby/object:Gem::Requirement
|
16
|
+
requirements:
|
17
|
+
- - ">="
|
18
|
+
- !ruby/object:Gem::Version
|
19
|
+
version: '0'
|
20
|
+
type: :runtime
|
21
|
+
prerelease: false
|
22
|
+
version_requirements: !ruby/object:Gem::Requirement
|
23
|
+
requirements:
|
24
|
+
- - ">="
|
25
|
+
- !ruby/object:Gem::Version
|
26
|
+
version: '0'
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: responders
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: '0'
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: '0'
|
41
|
+
- !ruby/object:Gem::Dependency
|
42
|
+
name: paginate-responder
|
43
|
+
requirement: !ruby/object:Gem::Requirement
|
44
|
+
requirements:
|
45
|
+
- - ">="
|
46
|
+
- !ruby/object:Gem::Version
|
47
|
+
version: '0'
|
48
|
+
type: :runtime
|
49
|
+
prerelease: false
|
50
|
+
version_requirements: !ruby/object:Gem::Requirement
|
51
|
+
requirements:
|
52
|
+
- - ">="
|
53
|
+
- !ruby/object:Gem::Version
|
54
|
+
version: '0'
|
55
|
+
- !ruby/object:Gem::Dependency
|
56
|
+
name: rubocop-rails
|
57
|
+
requirement: !ruby/object:Gem::Requirement
|
58
|
+
requirements:
|
59
|
+
- - ">="
|
60
|
+
- !ruby/object:Gem::Version
|
61
|
+
version: '0'
|
62
|
+
type: :development
|
63
|
+
prerelease: false
|
64
|
+
version_requirements: !ruby/object:Gem::Requirement
|
65
|
+
requirements:
|
66
|
+
- - ">="
|
67
|
+
- !ruby/object:Gem::Version
|
68
|
+
version: '0'
|
69
|
+
- !ruby/object:Gem::Dependency
|
70
|
+
name: pry-byebug
|
71
|
+
requirement: !ruby/object:Gem::Requirement
|
72
|
+
requirements:
|
73
|
+
- - ">="
|
74
|
+
- !ruby/object:Gem::Version
|
75
|
+
version: '0'
|
76
|
+
type: :development
|
77
|
+
prerelease: false
|
78
|
+
version_requirements: !ruby/object:Gem::Requirement
|
79
|
+
requirements:
|
80
|
+
- - ">="
|
81
|
+
- !ruby/object:Gem::Version
|
82
|
+
version: '0'
|
83
|
+
- !ruby/object:Gem::Dependency
|
84
|
+
name: spring
|
85
|
+
requirement: !ruby/object:Gem::Requirement
|
86
|
+
requirements:
|
87
|
+
- - ">="
|
88
|
+
- !ruby/object:Gem::Version
|
89
|
+
version: '0'
|
90
|
+
type: :development
|
91
|
+
prerelease: false
|
92
|
+
version_requirements: !ruby/object:Gem::Requirement
|
93
|
+
requirements:
|
94
|
+
- - ">="
|
95
|
+
- !ruby/object:Gem::Version
|
96
|
+
version: '0'
|
97
|
+
- !ruby/object:Gem::Dependency
|
98
|
+
name: spring-commands-m
|
99
|
+
requirement: !ruby/object:Gem::Requirement
|
100
|
+
requirements:
|
101
|
+
- - ">="
|
102
|
+
- !ruby/object:Gem::Version
|
103
|
+
version: '0'
|
104
|
+
type: :development
|
105
|
+
prerelease: false
|
106
|
+
version_requirements: !ruby/object:Gem::Requirement
|
107
|
+
requirements:
|
108
|
+
- - ">="
|
109
|
+
- !ruby/object:Gem::Version
|
110
|
+
version: '0'
|
111
|
+
- !ruby/object:Gem::Dependency
|
112
|
+
name: m
|
113
|
+
requirement: !ruby/object:Gem::Requirement
|
114
|
+
requirements:
|
115
|
+
- - ">="
|
116
|
+
- !ruby/object:Gem::Version
|
117
|
+
version: '0'
|
118
|
+
type: :development
|
119
|
+
prerelease: false
|
120
|
+
version_requirements: !ruby/object:Gem::Requirement
|
121
|
+
requirements:
|
122
|
+
- - ">="
|
123
|
+
- !ruby/object:Gem::Version
|
124
|
+
version: '0'
|
125
|
+
description:
|
126
|
+
email:
|
127
|
+
- ceritium@gmail.com
|
128
|
+
executables: []
|
129
|
+
extensions: []
|
130
|
+
extra_rdoc_files: []
|
131
|
+
files:
|
132
|
+
- MIT-LICENSE
|
133
|
+
- README.md
|
134
|
+
- Rakefile
|
135
|
+
- app/assets/config/vimo_manifest.js
|
136
|
+
- app/assets/javascripts/vimo/application.js
|
137
|
+
- app/assets/javascripts/vimo/entities.js
|
138
|
+
- app/assets/javascripts/vimo/items.js
|
139
|
+
- app/assets/stylesheets/vimo/application.css
|
140
|
+
- app/assets/stylesheets/vimo/entities.css
|
141
|
+
- app/assets/stylesheets/vimo/items.css
|
142
|
+
- app/controllers/vimo/application_controller.rb
|
143
|
+
- app/controllers/vimo/entities_controller.rb
|
144
|
+
- app/controllers/vimo/items_controller.rb
|
145
|
+
- app/helpers/vimo/application_helper.rb
|
146
|
+
- app/helpers/vimo/entities_helper.rb
|
147
|
+
- app/helpers/vimo/items_helper.rb
|
148
|
+
- app/jobs/vimo/application_job.rb
|
149
|
+
- app/mailers/vimo/application_mailer.rb
|
150
|
+
- app/models/vimo/application_record.rb
|
151
|
+
- app/models/vimo/entity.rb
|
152
|
+
- app/models/vimo/field.rb
|
153
|
+
- app/models/vimo/item.rb
|
154
|
+
- app/models/vimo/system_name.rb
|
155
|
+
- app/views/layouts/vimo/application.html.erb
|
156
|
+
- config/locales/responders.en.yml
|
157
|
+
- config/routes.rb
|
158
|
+
- config/spring.rb
|
159
|
+
- db/migrate/20180208181633_create_vimo_entities.rb
|
160
|
+
- db/migrate/20180208182202_create_vimo_fields.rb
|
161
|
+
- db/migrate/20180210104430_create_vimo_items.rb
|
162
|
+
- lib/application_responder.rb
|
163
|
+
- lib/string_ext.rb
|
164
|
+
- lib/tasks/vimo_tasks.rake
|
165
|
+
- lib/vimo.rb
|
166
|
+
- lib/vimo/configuration.rb
|
167
|
+
- lib/vimo/engine.rb
|
168
|
+
- lib/vimo/version.rb
|
169
|
+
homepage: https://github.com/ceritium/vimo
|
170
|
+
licenses:
|
171
|
+
- MIT
|
172
|
+
metadata: {}
|
173
|
+
post_install_message:
|
174
|
+
rdoc_options: []
|
175
|
+
require_paths:
|
176
|
+
- lib
|
177
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
178
|
+
requirements:
|
179
|
+
- - ">="
|
180
|
+
- !ruby/object:Gem::Version
|
181
|
+
version: '0'
|
182
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
183
|
+
requirements:
|
184
|
+
- - ">="
|
185
|
+
- !ruby/object:Gem::Version
|
186
|
+
version: '0'
|
187
|
+
requirements: []
|
188
|
+
rubyforge_project:
|
189
|
+
rubygems_version: 2.7.3
|
190
|
+
signing_key:
|
191
|
+
specification_version: 4
|
192
|
+
summary: Allow to your users create and customize their own virtual models
|
193
|
+
test_files: []
|