flexite 0.0.2
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 +12 -0
- data/Rakefile +40 -0
- data/app/assets/fonts/glyphicons-halflings-regular.eot +0 -0
- data/app/assets/fonts/glyphicons-halflings-regular.svg +288 -0
- data/app/assets/fonts/glyphicons-halflings-regular.ttf +0 -0
- data/app/assets/fonts/glyphicons-halflings-regular.woff +0 -0
- data/app/assets/fonts/glyphicons-halflings-regular.woff2 +0 -0
- data/app/assets/images/flexite/glyphicons-halflings-white.png +0 -0
- data/app/assets/images/flexite/glyphicons-halflings.png +0 -0
- data/app/assets/javascripts/flexite/application.js +18 -0
- data/app/assets/javascripts/flexite/bootstrap.min.js +7 -0
- data/app/assets/javascripts/flexite/common.js.erb +2 -0
- data/app/assets/javascripts/flexite/jquery.min.js +2 -0
- data/app/assets/javascripts/flexite/tree.js.erb +83 -0
- data/app/assets/javascripts/flexite/treeview.js +1335 -0
- data/app/assets/stylesheets/flexite/application.css +29 -0
- data/app/assets/stylesheets/flexite/bootstrap-treeview.min.css +1 -0
- data/app/assets/stylesheets/flexite/bootstrap.min.css +5 -0
- data/app/assets/stylesheets/flexite/configs.css +8 -0
- data/app/assets/stylesheets/flexite/entries.css +4 -0
- data/app/assets/stylesheets/flexite/tree.css +21 -0
- data/app/assets/stylesheets/scaffold.css +56 -0
- data/app/controllers/flexite/application_controller.rb +25 -0
- data/app/controllers/flexite/configs_controller.rb +61 -0
- data/app/controllers/flexite/entries_controller.rb +82 -0
- data/app/factories/flexite/base_factory.rb +7 -0
- data/app/factories/flexite/service_factory.rb +19 -0
- data/app/forms/flexite/base_form.rb +24 -0
- data/app/forms/flexite/config/form.rb +12 -0
- data/app/forms/flexite/entry/array_form.rb +11 -0
- data/app/forms/flexite/entry/form.rb +16 -0
- data/app/helpers/flexite/application_helper.rb +15 -0
- data/app/helpers/flexite/configs_helper.rb +4 -0
- data/app/helpers/flexite/entries_helper.rb +46 -0
- data/app/models/flexite/arr_entry.rb +35 -0
- data/app/models/flexite/bool_entry.rb +19 -0
- data/app/models/flexite/config.rb +64 -0
- data/app/models/flexite/entry.rb +30 -0
- data/app/models/flexite/int_entry.rb +13 -0
- data/app/models/flexite/str_entry.rb +2 -0
- data/app/models/flexite/sym_entry.rb +17 -0
- data/app/services/flexite/action_service/result.rb +44 -0
- data/app/services/flexite/action_service.rb +30 -0
- data/app/services/flexite/config/create_service.rb +25 -0
- data/app/services/flexite/config/update_service.rb +28 -0
- data/app/services/flexite/data/hash.rb +17 -0
- data/app/services/flexite/data/migrators/yaml.rb +62 -0
- data/app/services/flexite/data/new.rb +87 -0
- data/app/services/flexite/entry/array_create_service.rb +69 -0
- data/app/services/flexite/entry/array_update_service.rb +69 -0
- data/app/services/flexite/entry/create_service.rb +31 -0
- data/app/services/flexite/entry/destroy_array_entry_service.rb +25 -0
- data/app/services/flexite/entry/destroy_service.rb +22 -0
- data/app/services/flexite/entry/update_service.rb +26 -0
- data/app/simple_form/array_input.rb +13 -0
- data/app/views/flexite/application/index.html.haml +14 -0
- data/app/views/flexite/configs/_form.html.haml +7 -0
- data/app/views/flexite/configs/create.js.haml +3 -0
- data/app/views/flexite/configs/edit.js.haml +1 -0
- data/app/views/flexite/configs/index.json.erb +10 -0
- data/app/views/flexite/configs/new.js.haml +1 -0
- data/app/views/flexite/configs/update.js.haml +2 -0
- data/app/views/flexite/entries/_form.html.haml +11 -0
- data/app/views/flexite/entries/_new_array_entry_form.html.haml +7 -0
- data/app/views/flexite/entries/_popup.html.haml +18 -0
- data/app/views/flexite/entries/_types_dropdown.html.haml +8 -0
- data/app/views/flexite/entries/create.js.haml +4 -0
- data/app/views/flexite/entries/destroy.js.haml +4 -0
- data/app/views/flexite/entries/destroy_array_entry.js.haml +6 -0
- data/app/views/flexite/entries/edit.js.haml +1 -0
- data/app/views/flexite/entries/new.js.haml +1 -0
- data/app/views/flexite/entries/new_array_entry.js.haml +1 -0
- data/app/views/flexite/entries/select_type.js.haml +1 -0
- data/app/views/flexite/entries/types/_arr_entry.html.haml +19 -0
- data/app/views/flexite/entries/types/_bool_entry.html.haml +4 -0
- data/app/views/flexite/entries/types/_int_entry.html.haml +4 -0
- data/app/views/flexite/entries/types/_str_entry.html.haml +4 -0
- data/app/views/flexite/entries/types/_sym_entry.html.haml +1 -0
- data/app/views/flexite/entries/update.js.haml +1 -0
- data/app/views/flexite/shared/_messages.html.haml +5 -0
- data/app/views/flexite/shared/_show_flash.js.haml +5 -0
- data/app/views/layouts/flexite/application.html.haml +11 -0
- data/config/initializers/simple_form.rb +143 -0
- data/config/initializers/simple_form_bootstrap.rb +43 -0
- data/config/locales/simple_form.en.yml +26 -0
- data/config/routes.rb +17 -0
- data/db/migrate/20180503102555_create_flexite_configs.rb +14 -0
- data/db/migrate/20180503103109_create_flexite_entries.rb +14 -0
- data/lib/flexite/cached_node.rb +19 -0
- data/lib/flexite/configuration.rb +24 -0
- data/lib/flexite/engine.rb +18 -0
- data/lib/flexite/flexy.rb +13 -0
- data/lib/flexite/nodes_hash.rb +5 -0
- data/lib/flexite/version.rb +3 -0
- data/lib/flexite.rb +44 -0
- data/lib/tasks/flexite_tasks.rake +20 -0
- data/test/dummy/README.rdoc +261 -0
- data/test/dummy/Rakefile +7 -0
- data/test/dummy/app/assets/javascripts/application.js +15 -0
- data/test/dummy/app/assets/stylesheets/application.css +13 -0
- data/test/dummy/app/controllers/application_controller.rb +3 -0
- data/test/dummy/app/helpers/application_helper.rb +2 -0
- data/test/dummy/config/application.rb +59 -0
- data/test/dummy/config/application.yml +599 -0
- data/test/dummy/config/boot.rb +10 -0
- data/test/dummy/config/database.yml +25 -0
- data/test/dummy/config/environment.rb +5 -0
- data/test/dummy/config/environments/development.rb +40 -0
- data/test/dummy/config/environments/production.rb +67 -0
- data/test/dummy/config/environments/test.rb +37 -0
- data/test/dummy/config/initializers/backtrace_silencers.rb +7 -0
- data/test/dummy/config/initializers/flexite.rb +5 -0
- data/test/dummy/config/initializers/inflections.rb +15 -0
- data/test/dummy/config/initializers/mime_types.rb +5 -0
- data/test/dummy/config/initializers/secret_token.rb +7 -0
- data/test/dummy/config/initializers/session_store.rb +8 -0
- data/test/dummy/config/initializers/wrap_parameters.rb +14 -0
- data/test/dummy/config/locales/en.yml +5 -0
- data/test/dummy/config/routes.rb +3 -0
- data/test/dummy/config.ru +4 -0
- data/test/dummy/db/development.sqlite3 +0 -0
- data/test/dummy/db/schema.rb +39 -0
- data/test/dummy/db/seeds.rb +3 -0
- data/test/dummy/db/test.sqlite3 +0 -0
- data/test/dummy/log/development.log +86588 -0
- data/test/dummy/public/404.html +26 -0
- data/test/dummy/public/422.html +26 -0
- data/test/dummy/public/500.html +25 -0
- data/test/dummy/public/favicon.ico +0 -0
- data/test/dummy/script/rails +6 -0
- data/test/dummy/tmp/cache/assets/C67/060/sprockets%2Ffaf176441f0544dd2b51901280044b40 +0 -0
- data/test/dummy/tmp/cache/assets/C9D/530/sprockets%2Fdcd49c063327c12052812f41c20a8e74 +0 -0
- data/test/dummy/tmp/cache/assets/CA3/270/sprockets%2F502b740063f8ec15e7e12811da71c772 +0 -0
- data/test/dummy/tmp/cache/assets/CDC/060/sprockets%2F8ff1d307d1b36810549d0829722b7aea +0 -0
- data/test/dummy/tmp/cache/assets/CDE/120/sprockets%2F5fd8b3fa3724451579552aed373410ce +0 -0
- data/test/dummy/tmp/cache/assets/CF8/980/sprockets%2F4e5077b95460dc34d7c9d7d9880e7b47 +0 -0
- data/test/dummy/tmp/cache/assets/D00/4C0/sprockets%2F603c6d7b825c2f4a6422b3d4af4e6203 +0 -0
- data/test/dummy/tmp/cache/assets/D00/C40/sprockets%2F999847c008fb4ce26fff5607c39d8358 +0 -0
- data/test/dummy/tmp/cache/assets/D09/A30/sprockets%2F2a71e20a2f3544acb51956504cd8d8e9 +0 -0
- data/test/dummy/tmp/cache/assets/D0D/E60/sprockets%2F90ea9eaa4671ec2d76703bae31972634 +0 -0
- data/test/dummy/tmp/cache/assets/D2A/160/sprockets%2Fbe17d4d0be4b381500e2824bbe273d70 +0 -0
- data/test/dummy/tmp/cache/assets/D2E/700/sprockets%2Fb21f85e0940bbcb3a8914c9cb0b07218 +0 -0
- data/test/dummy/tmp/cache/assets/D39/CD0/sprockets%2F0e8f6981475e49ea9fe14698fa57e4e9 +0 -0
- data/test/dummy/tmp/cache/assets/D40/590/sprockets%2F181dd5673b58f1ec4c89e50028bfad60 +0 -0
- data/test/dummy/tmp/cache/assets/D46/870/sprockets%2Fd880bdf72c5d0009b88fda8521439dc8 +0 -0
- data/test/dummy/tmp/cache/assets/D48/5F0/sprockets%2Fe6a83afb2d92f4692ffb391b5285a518 +0 -0
- data/test/dummy/tmp/cache/assets/D4B/A20/sprockets%2Febde89014596e655c35df9c4a01ee636 +0 -0
- data/test/dummy/tmp/cache/assets/D54/A50/sprockets%2Ff49839d906f69fd92904ebac07a3a38e +0 -0
- data/test/dummy/tmp/cache/assets/D69/B50/sprockets%2F4186e2787004e19ceb0c4afed46cf04b +0 -0
- data/test/dummy/tmp/cache/assets/D6D/C20/sprockets%2F112e96fea93f5f1e31d2077f1cdaf283 +0 -0
- data/test/dummy/tmp/cache/assets/D7A/8F0/sprockets%2F8eefc5f9824d950317a5c4a2e68b3c4e +0 -0
- data/test/dummy/tmp/cache/assets/DB3/360/sprockets%2F24b1f98ad736884b91d6ebeb2fc68ed8 +0 -0
- data/test/dummy/tmp/cache/assets/DD2/E90/sprockets%2Ff01f48c96ba588d15b20dd57ed3ccb7f +0 -0
- data/test/dummy/tmp/cache/assets/DEE/0C0/sprockets%2Feedcd74856542eedb5ea3ab1b1502ca4 +0 -0
- data/test/dummy/tmp/cache/assets/DF1/210/sprockets%2Ff4fe7dba1445ba1b668aaa1bd34ca984 +0 -0
- data/test/dummy/tmp/cache/assets/E44/790/sprockets%2Fefb8d8ea9e97da9d675a8bfa1d5de343 +0 -0
- data/test/fixtures/flexite/configs.yml +7 -0
- data/test/fixtures/flexite/entries.yml +13 -0
- data/test/flexite_test.rb +7 -0
- data/test/functional/flexite/configs_controller_test.rb +51 -0
- data/test/functional/flexite/entries_controller_test.rb +51 -0
- data/test/integration/navigation_test.rb +10 -0
- data/test/test_helper.rb +15 -0
- data/test/unit/flexite/config_test.rb +9 -0
- data/test/unit/flexite/entry_test.rb +9 -0
- data/test/unit/helpers/flexite/configs_helper_test.rb +6 -0
- data/test/unit/helpers/flexite/entries_helper_test.rb +6 -0
- metadata +366 -0
@@ -0,0 +1,24 @@
|
|
1
|
+
class Flexite::BaseForm
|
2
|
+
include ActiveModel::Validations
|
3
|
+
include ActiveModel::Conversion
|
4
|
+
extend ActiveModel::Naming
|
5
|
+
|
6
|
+
attr_reader :attributes
|
7
|
+
|
8
|
+
def initialize(attributes = {})
|
9
|
+
@attributes = HashWithIndifferentAccess.new
|
10
|
+
|
11
|
+
attributes.each do |name, value|
|
12
|
+
send("#{name}=", value) rescue next
|
13
|
+
@attributes[name] = value
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
def persisted?
|
18
|
+
respond_to?(:id) && id.present?
|
19
|
+
end
|
20
|
+
|
21
|
+
def new_record?
|
22
|
+
!persisted?
|
23
|
+
end
|
24
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require_dependency 'flexite/base_form'
|
2
|
+
|
3
|
+
module Flexite
|
4
|
+
class Entry::Form < BaseForm
|
5
|
+
attr_accessor :id, :type, :value, :parent_id, :parent_type
|
6
|
+
validates :type, presence: true
|
7
|
+
|
8
|
+
def self.model_name
|
9
|
+
Entry.model_name
|
10
|
+
end
|
11
|
+
|
12
|
+
def view_type
|
13
|
+
type.demodulize.underscore
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,15 @@
|
|
1
|
+
module Flexite
|
2
|
+
module ApplicationHelper
|
3
|
+
def present(model)
|
4
|
+
unless model.respond_to?(:presenter)
|
5
|
+
raise "#{model.class.name} is not presentable"
|
6
|
+
end
|
7
|
+
|
8
|
+
yield(model.presenter(self))
|
9
|
+
end
|
10
|
+
|
11
|
+
def back_to_app
|
12
|
+
link_to "Back to #{Flexite.config.app_name}", Flexite.config.app_link, class: 'btn btn-default'
|
13
|
+
end
|
14
|
+
end
|
15
|
+
end
|
@@ -0,0 +1,46 @@
|
|
1
|
+
module Flexite
|
2
|
+
module EntriesHelper
|
3
|
+
ENTRY_TYPE_OPTIONS = [
|
4
|
+
['String', 'Flexite::StrEntry'],
|
5
|
+
['Symbol', 'Flexite::SymEntry'],
|
6
|
+
['Boolean', 'Flexite::BoolEntry'],
|
7
|
+
['Array', 'Flexite::ArrEntry'],
|
8
|
+
['Integer', 'Flexite::IntEntry']
|
9
|
+
].freeze
|
10
|
+
|
11
|
+
def render_entries(entries, form)
|
12
|
+
content_tag :div, id: "array-entries-#{form.options[:index]}" do
|
13
|
+
entries.each_with_index do |entry, index|
|
14
|
+
concat render_entry(entry, form, index)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
def entry_type_select(f = nil)
|
20
|
+
if f.present?
|
21
|
+
f.select :type, options_for_select(ENTRY_TYPE_OPTIONS), {}, class: 'form-control'
|
22
|
+
else
|
23
|
+
select_tag :new_entry_type, options_for_select(ENTRY_TYPE_OPTIONS), class: 'form-control'
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
private
|
28
|
+
|
29
|
+
def render_entry(entry, form, index)
|
30
|
+
cache entry do
|
31
|
+
entry_form = entry.class.form(entry.form_attributes)
|
32
|
+
|
33
|
+
concat(form.simple_fields_for(:entries, entry_form, index: index) do |fields|
|
34
|
+
delete_link = link_to 'Delete', destroy_array_entries_path(id: entry.id, selector: "#{fields.object_name}-#{index}-#{entry.id}"),
|
35
|
+
remote: true, method: :delete, class: 'btn btn-danger'
|
36
|
+
|
37
|
+
concat(content_tag(:div, id: "#{fields.object_name}-#{index}-#{entry.id}") do
|
38
|
+
concat fields.input :id, as: :hidden
|
39
|
+
concat fields.input :type, as: :hidden
|
40
|
+
concat render "types/#{entry_form.view_type}", f: fields, delete_link: delete_link
|
41
|
+
end)
|
42
|
+
end)
|
43
|
+
end
|
44
|
+
end
|
45
|
+
end
|
46
|
+
end
|
@@ -0,0 +1,35 @@
|
|
1
|
+
module Flexite
|
2
|
+
class ArrEntry < Entry
|
3
|
+
has_many :entries, as: :parent, dependent: :destroy
|
4
|
+
|
5
|
+
def value
|
6
|
+
entries.select([:id, :value, :type]).map(&:value)
|
7
|
+
end
|
8
|
+
|
9
|
+
def entry=(entry)
|
10
|
+
entries << entry
|
11
|
+
end
|
12
|
+
|
13
|
+
def form_attributes
|
14
|
+
attributes.merge(entries: form_entries)
|
15
|
+
end
|
16
|
+
|
17
|
+
def self.form(attributes = {})
|
18
|
+
Entry::ArrayForm.new(attributes)
|
19
|
+
end
|
20
|
+
|
21
|
+
def self.service(type)
|
22
|
+
"arr_entry_#{type}".to_sym
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def form_entries
|
28
|
+
entries.select([:id, :value, :type, :updated_at])
|
29
|
+
end
|
30
|
+
|
31
|
+
def cast_value
|
32
|
+
# value should be blank
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
@@ -0,0 +1,19 @@
|
|
1
|
+
module Flexite
|
2
|
+
class BoolEntry < Entry
|
3
|
+
def value
|
4
|
+
self[:value].to_i == 1 ? true : false
|
5
|
+
end
|
6
|
+
|
7
|
+
def form
|
8
|
+
Entry::Form.new(attributes.merge(value: self[:value].to_i))
|
9
|
+
end
|
10
|
+
|
11
|
+
private
|
12
|
+
|
13
|
+
def check_value
|
14
|
+
unless [1, 0].include?(self[:value].to_i)
|
15
|
+
errors.add(:value, 'not a boolean')
|
16
|
+
end
|
17
|
+
end
|
18
|
+
end
|
19
|
+
end
|
@@ -0,0 +1,64 @@
|
|
1
|
+
module Flexite
|
2
|
+
class Config < ActiveRecord::Base
|
3
|
+
attr_accessible :name
|
4
|
+
belongs_to :config, touch: true
|
5
|
+
belongs_to :owner, foreign_key: :created_by
|
6
|
+
has_one :entry, as: :parent, dependent: :destroy
|
7
|
+
has_many :configs, dependent: :destroy
|
8
|
+
|
9
|
+
scope :not_selectable, -> { select([:id, :name]).where(selectable: false) }
|
10
|
+
delegate :value, to: :entry, allow_nil: true
|
11
|
+
validates :name, uniqueness: { scope: :config_id }
|
12
|
+
|
13
|
+
def to_tree_node
|
14
|
+
{
|
15
|
+
id: id,
|
16
|
+
editHref: Engine.routes.url_helpers.edit_config_path(self),
|
17
|
+
selfHref: Engine.routes.url_helpers.config_path(self),
|
18
|
+
newHref: Engine.routes.url_helpers.new_config_config_path(self),
|
19
|
+
text: name,
|
20
|
+
dataHref: selectable ? entry_href : configs_href,
|
21
|
+
nodes: nodes,
|
22
|
+
selectable: true,
|
23
|
+
ajaxOnSelect: selectable
|
24
|
+
}
|
25
|
+
end
|
26
|
+
|
27
|
+
def self.tree_view(parent_id)
|
28
|
+
joins("LEFT JOIN #{table_name} AS configs_#{table_name} ON configs_#{table_name}.config_id = #{table_name}.id")
|
29
|
+
.joins("LEFT JOIN #{Entry.table_name} ON #{Entry.table_name}.parent_id = #{table_name}.id AND #{Entry.table_name}.parent_type = '#{model_name}'")
|
30
|
+
.select(["#{table_name}.id", "#{table_name}.selectable", "#{table_name}.name", "#{table_name}.updated_at", "COUNT(configs_#{table_name}.id) as nodes_count", "#{Entry.table_name}.id AS entry_id"])
|
31
|
+
.where(config_id: parent_id).group("#{table_name}.id")
|
32
|
+
end
|
33
|
+
|
34
|
+
def nodes_count
|
35
|
+
self[:nodes_count].to_i
|
36
|
+
end
|
37
|
+
|
38
|
+
def entry_id
|
39
|
+
self[:entry_id]
|
40
|
+
end
|
41
|
+
|
42
|
+
def nodes
|
43
|
+
if selectable
|
44
|
+
return nil
|
45
|
+
end
|
46
|
+
|
47
|
+
nodes_count > 0 ? [] : nil
|
48
|
+
end
|
49
|
+
|
50
|
+
private
|
51
|
+
|
52
|
+
def entry_href
|
53
|
+
if entry_id.present?
|
54
|
+
Engine.routes.url_helpers.edit_entry_path(entry_id, format: :js)
|
55
|
+
else
|
56
|
+
Engine.routes.url_helpers.select_type_entries_path(self, format: :js)
|
57
|
+
end
|
58
|
+
end
|
59
|
+
|
60
|
+
def configs_href
|
61
|
+
Engine.routes.url_helpers.config_configs_path(self, format: :json)
|
62
|
+
end
|
63
|
+
end
|
64
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
module Flexite
|
2
|
+
class Entry < ActiveRecord::Base
|
3
|
+
belongs_to :parent, polymorphic: true, touch: true
|
4
|
+
attr_accessible :value
|
5
|
+
before_save :check_value, :cast_value
|
6
|
+
|
7
|
+
def view_value
|
8
|
+
value.to_s
|
9
|
+
end
|
10
|
+
|
11
|
+
def self.form(attributes = {})
|
12
|
+
Form.new(attributes)
|
13
|
+
end
|
14
|
+
|
15
|
+
def self.service(type)
|
16
|
+
"entry_#{type}".to_sym
|
17
|
+
end
|
18
|
+
|
19
|
+
alias :form_attributes :attributes
|
20
|
+
|
21
|
+
private
|
22
|
+
|
23
|
+
def cast_value
|
24
|
+
self[:value] = self[:value].to_s
|
25
|
+
end
|
26
|
+
|
27
|
+
def check_value
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Flexite::SymEntry < Flexite::Entry
|
2
|
+
def value
|
3
|
+
self[:value].to_sym
|
4
|
+
end
|
5
|
+
|
6
|
+
def view_value
|
7
|
+
":#{value}"
|
8
|
+
end
|
9
|
+
|
10
|
+
private
|
11
|
+
|
12
|
+
def check_value
|
13
|
+
self[:value].to_sym
|
14
|
+
rescue
|
15
|
+
errors(:value, 'cannot be casted to Symbol')
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,44 @@
|
|
1
|
+
class Flexite::ActionService::Result
|
2
|
+
def initialize(options = {})
|
3
|
+
@options = options
|
4
|
+
@errors = Hash.new { |h, k| h[k] = [] }
|
5
|
+
end
|
6
|
+
|
7
|
+
def succeed?
|
8
|
+
@options.fetch(:succeed, true)
|
9
|
+
end
|
10
|
+
|
11
|
+
def failed?
|
12
|
+
!succeed?
|
13
|
+
end
|
14
|
+
|
15
|
+
def render?
|
16
|
+
@options.fetch(:render, true)
|
17
|
+
end
|
18
|
+
|
19
|
+
def redirect?
|
20
|
+
!render?
|
21
|
+
end
|
22
|
+
|
23
|
+
def data
|
24
|
+
@options[:data]
|
25
|
+
end
|
26
|
+
|
27
|
+
alias :record :data
|
28
|
+
|
29
|
+
def add_error(name, value)
|
30
|
+
@errors[name] << value
|
31
|
+
end
|
32
|
+
|
33
|
+
def add_errors(name, values)
|
34
|
+
@errors[name] += values
|
35
|
+
end
|
36
|
+
|
37
|
+
def endpoint
|
38
|
+
@options.fetch(:endpoint, {})
|
39
|
+
end
|
40
|
+
|
41
|
+
def flash
|
42
|
+
@options.fetch(:flash, {})
|
43
|
+
end
|
44
|
+
end
|
@@ -0,0 +1,30 @@
|
|
1
|
+
class Flexite::ActionService
|
2
|
+
def self.inherited(child)
|
3
|
+
child.const_set(:Result, Result)
|
4
|
+
end
|
5
|
+
|
6
|
+
def initialize(form, params = {})
|
7
|
+
@form = form
|
8
|
+
@params = params
|
9
|
+
end
|
10
|
+
|
11
|
+
def call
|
12
|
+
raise NotImplementedError
|
13
|
+
end
|
14
|
+
|
15
|
+
protected
|
16
|
+
|
17
|
+
def success
|
18
|
+
raise NotImplementedError
|
19
|
+
end
|
20
|
+
|
21
|
+
def failure
|
22
|
+
raise NotImplementedError
|
23
|
+
end
|
24
|
+
|
25
|
+
def save_errors(result)
|
26
|
+
@form.errors.messages.each do |key, values|
|
27
|
+
result.add_errors(key, values)
|
28
|
+
end
|
29
|
+
end
|
30
|
+
end
|
@@ -0,0 +1,25 @@
|
|
1
|
+
require_dependency 'flexite/action_service'
|
2
|
+
|
3
|
+
module Flexite
|
4
|
+
class Config::CreateService < ActionService
|
5
|
+
def call
|
6
|
+
if @form.invalid?
|
7
|
+
return failure
|
8
|
+
end
|
9
|
+
|
10
|
+
@record = Config.create(@form.attributes, without_protection: true)
|
11
|
+
success
|
12
|
+
end
|
13
|
+
|
14
|
+
protected
|
15
|
+
|
16
|
+
def failure
|
17
|
+
Result.new(success: false, endpoint: { status: 400 })
|
18
|
+
end
|
19
|
+
|
20
|
+
def success
|
21
|
+
Result.new(flash: { type: :success, message: 'Config was created!' },
|
22
|
+
data: { record: @record })
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
@@ -0,0 +1,28 @@
|
|
1
|
+
module Flexite
|
2
|
+
class Config
|
3
|
+
class UpdateService < ActionService
|
4
|
+
def call
|
5
|
+
if @form.invalid?
|
6
|
+
return failure
|
7
|
+
end
|
8
|
+
|
9
|
+
@record = Config.find(@form.id)
|
10
|
+
@record.config_id = @form.config_id
|
11
|
+
@record.selectable = @form.selectable
|
12
|
+
@record.name = @form.name
|
13
|
+
@record.save
|
14
|
+
success
|
15
|
+
end
|
16
|
+
|
17
|
+
protected
|
18
|
+
|
19
|
+
def failure
|
20
|
+
Result.new(success: false, endpoint: { status: 400 })
|
21
|
+
end
|
22
|
+
|
23
|
+
def success
|
24
|
+
Result.new(flash: { type: :success, message: 'Config was updated!' }, data: { record: @record })
|
25
|
+
end
|
26
|
+
end
|
27
|
+
end
|
28
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
class Flexite::Data::Hash < Hashie::Mash
|
2
|
+
extend Hashie::Extensions::DeepMerge
|
3
|
+
|
4
|
+
def initialize(*)
|
5
|
+
super { |h, k| h[k] = {} }
|
6
|
+
end
|
7
|
+
|
8
|
+
def self.name
|
9
|
+
Hash.name
|
10
|
+
end
|
11
|
+
|
12
|
+
class Hashie::Array
|
13
|
+
def self.name
|
14
|
+
Array.name
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
@@ -0,0 +1,62 @@
|
|
1
|
+
module Flexite
|
2
|
+
class Data::Migrators::Yaml
|
3
|
+
def initialize
|
4
|
+
@paths = Flexite.config.paths
|
5
|
+
@roots = Flexite.config.source_roots
|
6
|
+
@hierarchy = Flexite.config.hierarchy
|
7
|
+
@data = Data::Hash.new
|
8
|
+
end
|
9
|
+
|
10
|
+
def call
|
11
|
+
@paths.each_with_object(@data) do |(name, paths), data|
|
12
|
+
paths.each do |p|
|
13
|
+
next unless File.exists?(p)
|
14
|
+
load_data(data, name, p)
|
15
|
+
end
|
16
|
+
end
|
17
|
+
end
|
18
|
+
|
19
|
+
private
|
20
|
+
|
21
|
+
def load_data(data, name, path)
|
22
|
+
with_hierarchy(path) do |configs|
|
23
|
+
with_source_roots(data[name], configs, @roots[name])
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
def with_source_roots(data, configs, roots)
|
28
|
+
data.deep_merge!(configs) and return if roots.blank?
|
29
|
+
|
30
|
+
roots.each do |root|
|
31
|
+
next if configs[root].blank?
|
32
|
+
data.deep_merge!(root => configs[root])
|
33
|
+
end
|
34
|
+
end
|
35
|
+
|
36
|
+
# hierarchy = [:a, :b, :c]
|
37
|
+
#
|
38
|
+
# {
|
39
|
+
# a: {
|
40
|
+
# b: {
|
41
|
+
# c: {}
|
42
|
+
# }
|
43
|
+
# }
|
44
|
+
# }
|
45
|
+
#
|
46
|
+
#
|
47
|
+
|
48
|
+
def with_hierarchy(path)
|
49
|
+
hierarchy = @hierarchy[path]
|
50
|
+
return yield(YAML.load_file(path)) if hierarchy.blank?
|
51
|
+
|
52
|
+
new_hash = {}
|
53
|
+
leveling = new_hash
|
54
|
+
hierarchy.each do |level|
|
55
|
+
leveling = leveling[level] = {}
|
56
|
+
end
|
57
|
+
|
58
|
+
leveling.merge!(YAML.load_file(path))
|
59
|
+
yield(new_hash)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
@@ -0,0 +1,87 @@
|
|
1
|
+
module Flexite
|
2
|
+
class Data::New
|
3
|
+
def initialize(migrator)
|
4
|
+
@migrator = migrator
|
5
|
+
@errors = Hash.new { |h, k| h[k] = [] }
|
6
|
+
@result = {}
|
7
|
+
end
|
8
|
+
|
9
|
+
def call
|
10
|
+
@migrator.call.each do |root, configs|
|
11
|
+
begin
|
12
|
+
@result[root] = save_root(root, configs)
|
13
|
+
rescue => exc
|
14
|
+
@errors[root] << [exc.message, exc.backtrace]
|
15
|
+
end
|
16
|
+
end
|
17
|
+
|
18
|
+
@result.tap do |result|
|
19
|
+
result[:errors] = @errors
|
20
|
+
end
|
21
|
+
end
|
22
|
+
|
23
|
+
private
|
24
|
+
|
25
|
+
def save_root(root, configs)
|
26
|
+
@result[root] = {}
|
27
|
+
|
28
|
+
Config.create!(name: root) do |record|
|
29
|
+
begin
|
30
|
+
save_hash_value(record, configs)
|
31
|
+
rescue => exc
|
32
|
+
@errors[record] << [exc.message, exc.backtrace]
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def save_entry(parent, entry)
|
38
|
+
send("save_#{entry.class.name.underscore}_value", parent, entry)
|
39
|
+
rescue => exc
|
40
|
+
@errors[parent] << [exc.message, exc.backtrace]
|
41
|
+
end
|
42
|
+
|
43
|
+
def save_hash_value(parent, hash)
|
44
|
+
parent.selectable = false
|
45
|
+
|
46
|
+
hash.each do |name, value|
|
47
|
+
entry = Config.new(name: name)
|
48
|
+
save_entry(entry, value)
|
49
|
+
parent.configs << entry
|
50
|
+
end
|
51
|
+
end
|
52
|
+
|
53
|
+
def save_array_value(parent, array)
|
54
|
+
entry = ArrEntry.new
|
55
|
+
|
56
|
+
array.each do |value|
|
57
|
+
save_entry(entry, value)
|
58
|
+
end
|
59
|
+
|
60
|
+
parent.entry = entry
|
61
|
+
end
|
62
|
+
|
63
|
+
def save_symbol_value(parent, symbol)
|
64
|
+
parent.entry = SymEntry.new(value: symbol)
|
65
|
+
end
|
66
|
+
|
67
|
+
def save_string_value(parent, string)
|
68
|
+
parent.entry = StrEntry.new(value: string)
|
69
|
+
end
|
70
|
+
|
71
|
+
def save_true_class_value(parent, _)
|
72
|
+
parent.entry = BoolEntry.new(value: 1)
|
73
|
+
end
|
74
|
+
|
75
|
+
def save_false_class_value(parent, _)
|
76
|
+
parent.entry = BoolEntry.new(value: 0)
|
77
|
+
end
|
78
|
+
|
79
|
+
def save_fixnum_value(parent, fixnum)
|
80
|
+
parent.entry = IntEntry.new(value: fixnum)
|
81
|
+
end
|
82
|
+
|
83
|
+
def save_nil_class_value(parent, nil_val)
|
84
|
+
parent.entry = Entry.new(value: nil_val)
|
85
|
+
end
|
86
|
+
end
|
87
|
+
end
|
@@ -0,0 +1,69 @@
|
|
1
|
+
require_dependency 'flexite/action_service'
|
2
|
+
|
3
|
+
module Flexite
|
4
|
+
class Entry
|
5
|
+
class ArrayCreateService < ActionService
|
6
|
+
def call
|
7
|
+
if @form.invalid?
|
8
|
+
return failure
|
9
|
+
end
|
10
|
+
|
11
|
+
process_entry
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def process_entry
|
17
|
+
@record = ArrEntry.create do |record|
|
18
|
+
record.parent_id = @form.parent_id
|
19
|
+
record.parent_type = @form.parent_type
|
20
|
+
end
|
21
|
+
|
22
|
+
Entry.transaction do
|
23
|
+
create_entries(@form.new_entries, @record.id)
|
24
|
+
end
|
25
|
+
|
26
|
+
success
|
27
|
+
rescue => exc
|
28
|
+
exc_failure(exc)
|
29
|
+
end
|
30
|
+
|
31
|
+
def create_entries(new_entries, parent_id)
|
32
|
+
return if new_entries.blank?
|
33
|
+
|
34
|
+
new_entries.each do |_, entry|
|
35
|
+
if respond_to?("save_#{entry[:type].demodulize.underscore}", true)
|
36
|
+
send("save_#{entry[:type].demodulize.underscore}", entry, parent_id)
|
37
|
+
else
|
38
|
+
save_entry(entry, parent_id)
|
39
|
+
end
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def save_arr_entry(entry, parent_id)
|
44
|
+
klass = entry[:type].constantize
|
45
|
+
record = klass.create({ parent_id: parent_id, parent_type: klass.base_class.sti_name }, without_protection: true)
|
46
|
+
create_entries(entry[:new_entries], record.id)
|
47
|
+
end
|
48
|
+
|
49
|
+
def save_entry(entry, parent_id)
|
50
|
+
klass = entry[:type].constantize
|
51
|
+
klass.create({ parent_id: parent_id, parent_type: klass.base_class.sti_name, value: entry[:value] }, without_protection: true)
|
52
|
+
end
|
53
|
+
|
54
|
+
protected
|
55
|
+
|
56
|
+
def failure
|
57
|
+
Result.new(success: false, endpoint: { status: 400 })
|
58
|
+
end
|
59
|
+
|
60
|
+
def exc_failure(exc)
|
61
|
+
Result.new(success: false, message: exc.message, endpoint: { status: 500 })
|
62
|
+
end
|
63
|
+
|
64
|
+
def success
|
65
|
+
Result.new(flash: { type: :success, message: 'Entry was created!' }, data: { record: @record })
|
66
|
+
end
|
67
|
+
end
|
68
|
+
end
|
69
|
+
end
|