flexite 0.0.4 → 0.0.5

Sign up to get free protection for your applications and to get access to all the features.
Files changed (70) hide show
  1. checksums.yaml +4 -4
  2. data/app/assets/javascripts/flexite/tree.js.erb +7 -0
  3. data/app/controllers/flexite/application_controller.rb +0 -6
  4. data/app/controllers/flexite/histories_controller.rb +14 -0
  5. data/app/forms/flexite/config/form.rb +4 -0
  6. data/app/forms/flexite/entry/array_form.rb +4 -0
  7. data/app/forms/flexite/entry/form.rb +8 -0
  8. data/app/helpers/flexite/entries_helper.rb +2 -1
  9. data/app/models/concerns/flexite/with_history.rb +49 -0
  10. data/app/models/flexite/bool_entry.rb +8 -2
  11. data/app/models/flexite/config.rb +6 -1
  12. data/app/models/flexite/entry.rb +6 -1
  13. data/app/models/flexite/history.rb +21 -0
  14. data/app/models/flexite/history_attribute.rb +6 -0
  15. data/app/models/flexite/int_entry.rb +1 -0
  16. data/app/models/flexite/sym_entry.rb +1 -0
  17. data/app/services/flexite/action_service.rb +2 -2
  18. data/app/services/flexite/entry/update_service.rb +6 -1
  19. data/app/views/flexite/configs/_form.html.haml +3 -0
  20. data/app/views/flexite/entries/_form.html.haml +3 -1
  21. data/app/views/flexite/entries/types/_bool_entry.html.haml +2 -0
  22. data/app/views/flexite/entries/types/_int_entry.html.haml +2 -0
  23. data/app/views/flexite/entries/types/_str_entry.html.haml +2 -0
  24. data/app/views/flexite/entries/types/_sym_entry.html.haml +1 -1
  25. data/app/views/flexite/histories/_history.html.haml +11 -0
  26. data/app/views/flexite/histories/index.js.haml +1 -0
  27. data/app/views/flexite/histories/restore.js.haml +4 -0
  28. data/config/routes.rb +2 -0
  29. data/db/migrate/20180618104507_create_flexite_histories.rb +12 -0
  30. data/db/migrate/20180618115057_create_flexite_history_attributes.rb +13 -0
  31. data/lib/flexite/configuration.rb +2 -1
  32. data/lib/flexite/engine.rb +1 -0
  33. data/lib/flexite/version.rb +1 -1
  34. data/test/dummy/config/application.yml +1 -598
  35. data/test/dummy/config/environments/development.rb +0 -2
  36. data/test/dummy/db/development.sqlite3 +0 -0
  37. data/test/dummy/db/schema.rb +21 -1
  38. data/test/dummy/log/development.log +140255 -0
  39. data/test/dummy/tmp/cache/assets/C67/060/sprockets%2Ffaf176441f0544dd2b51901280044b40 +0 -0
  40. data/test/dummy/tmp/cache/assets/C9D/530/sprockets%2Fdcd49c063327c12052812f41c20a8e74 +0 -0
  41. data/test/dummy/tmp/cache/assets/CA3/270/sprockets%2F502b740063f8ec15e7e12811da71c772 +0 -0
  42. data/test/dummy/tmp/cache/assets/CDC/060/sprockets%2F8ff1d307d1b36810549d0829722b7aea +0 -0
  43. data/test/dummy/tmp/cache/assets/CDE/120/sprockets%2F5fd8b3fa3724451579552aed373410ce +0 -0
  44. data/test/dummy/tmp/cache/assets/CF8/980/sprockets%2F4e5077b95460dc34d7c9d7d9880e7b47 +0 -0
  45. data/test/dummy/tmp/cache/assets/D00/4C0/sprockets%2F603c6d7b825c2f4a6422b3d4af4e6203 +0 -0
  46. data/test/dummy/tmp/cache/assets/D00/C40/sprockets%2F999847c008fb4ce26fff5607c39d8358 +0 -0
  47. data/test/dummy/tmp/cache/assets/D09/A30/sprockets%2F2a71e20a2f3544acb51956504cd8d8e9 +0 -0
  48. data/test/dummy/tmp/cache/assets/D0D/E60/sprockets%2F90ea9eaa4671ec2d76703bae31972634 +0 -0
  49. data/test/dummy/tmp/cache/assets/D2A/160/sprockets%2Fbe17d4d0be4b381500e2824bbe273d70 +0 -0
  50. data/test/dummy/tmp/cache/assets/D2E/700/sprockets%2Fb21f85e0940bbcb3a8914c9cb0b07218 +0 -0
  51. data/test/dummy/tmp/cache/assets/D39/CD0/sprockets%2F0e8f6981475e49ea9fe14698fa57e4e9 +0 -0
  52. data/test/dummy/tmp/cache/assets/D40/590/sprockets%2F181dd5673b58f1ec4c89e50028bfad60 +0 -0
  53. data/test/dummy/tmp/cache/assets/D46/870/sprockets%2Fd880bdf72c5d0009b88fda8521439dc8 +0 -0
  54. data/test/dummy/tmp/cache/assets/D48/5F0/sprockets%2Fe6a83afb2d92f4692ffb391b5285a518 +0 -0
  55. data/test/dummy/tmp/cache/assets/D4B/A20/sprockets%2Febde89014596e655c35df9c4a01ee636 +0 -0
  56. data/test/dummy/tmp/cache/assets/D54/A50/sprockets%2Ff49839d906f69fd92904ebac07a3a38e +0 -0
  57. data/test/dummy/tmp/cache/assets/D69/B50/sprockets%2F4186e2787004e19ceb0c4afed46cf04b +0 -0
  58. data/test/dummy/tmp/cache/assets/D6D/C20/sprockets%2F112e96fea93f5f1e31d2077f1cdaf283 +0 -0
  59. data/test/dummy/tmp/cache/assets/D7A/8F0/sprockets%2F8eefc5f9824d950317a5c4a2e68b3c4e +0 -0
  60. data/test/dummy/tmp/cache/assets/DB3/360/sprockets%2F24b1f98ad736884b91d6ebeb2fc68ed8 +0 -0
  61. data/test/dummy/tmp/cache/assets/DD2/E90/sprockets%2Ff01f48c96ba588d15b20dd57ed3ccb7f +0 -0
  62. data/test/dummy/tmp/cache/assets/DEE/0C0/sprockets%2Feedcd74856542eedb5ea3ab1b1502ca4 +0 -0
  63. data/test/dummy/tmp/cache/assets/DF1/210/sprockets%2Ff4fe7dba1445ba1b668aaa1bd34ca984 +0 -0
  64. data/test/dummy/tmp/cache/assets/E44/790/sprockets%2Fefb8d8ea9e97da9d675a8bfa1d5de343 +0 -0
  65. data/test/fixtures/flexite/histories.yml +11 -0
  66. data/test/fixtures/flexite/history_attributes.yml +11 -0
  67. data/test/unit/flexite/history_attribute_test.rb +9 -0
  68. data/test/unit/flexite/history_test.rb +9 -0
  69. metadata +47 -4
  70. data/test/dummy/db/test.sqlite3 +0 -0
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: a88e76842f315c82ea98a437022148f5094cf069
4
- data.tar.gz: 6c3f408e1707d11e1d0343beec283e12e3261ae1
3
+ metadata.gz: 2e56e14f785289341cecf9f123fcdff29203d6c3
4
+ data.tar.gz: df1b2dd7892a9aa29bc89fc80523eaac105db6bf
5
5
  SHA512:
6
- metadata.gz: 2f84344a75804aa160887f74a590d9873e8c819affbed1b39ff92eff7cdcd238f020b31b8b652a331e6898b203c1bd7912324e86b02851a1e16c64a3c08808fb
7
- data.tar.gz: 1b2c5596ac5f3fc0b7c0d4b438f48a6afa779a2d43ca24cbebc0252f6a7d69a943691f342c3df7a29002219ea7a727063fa3310e277dd6505a5b56137dd950f6
6
+ metadata.gz: 358346c815e81f5f9e08e23a020dba9604872b8d52b65e448a0d96c1e5d8019a597ba2471c564f28f80ee205b5f4e4c8b592f7f57629c8b1c888a71665d96e63
7
+ data.tar.gz: 2127e0c6ded192a39a38ce9ffb7b95fd7d9b981281e173cf016f3e16744b21d8ede07484e499f829992060aab63151a32f7996dae9f187dd2a608385eea96cb6
@@ -58,6 +58,7 @@ function Tree(selector) {
58
58
  },
59
59
  onNodeUnselected: function (event, node) {
60
60
  $flexite("#section-2").html("");
61
+ $flexite("#section-3").html("");
61
62
  }
62
63
  })
63
64
  })
@@ -68,6 +69,12 @@ function Tree(selector) {
68
69
  self.init();
69
70
  }
70
71
 
72
+ this.unselectAll = function () {
73
+ tree.treeview("getSelected").forEach(function (node) {
74
+ tree.treeview("unselectNode", node);
75
+ });
76
+ }
77
+
71
78
  this.addNode = function (jsonNode, parentId) {
72
79
  tree.treeview(true).addToParent(JSON.parse(jsonNode), parentId);
73
80
  }
@@ -2,12 +2,6 @@ require_dependency 'flexite/service_factory'
2
2
 
3
3
  module Flexite
4
4
  class ApplicationController < ActionController::Base
5
- append_view_path File.join(Flexite::Engine.root, "app/views/flexite/#{controller_name}")
6
-
7
- def self.inherited(subclass)
8
- subclass.append_view_path File.join(Flexite::Engine.root, "app/views/flexite/#{subclass.controller_name}")
9
- end
10
-
11
5
  private
12
6
 
13
7
  def service_response(result)
@@ -0,0 +1,14 @@
1
+ require_dependency 'flexite/application_controller'
2
+
3
+ module Flexite
4
+ class HistoriesController < ApplicationController
5
+ def index
6
+ @histories = History.includes(:history_attributes).where(entity_id: params[:entity_id], entity_type: params[:entity_type].camelize)
7
+ end
8
+
9
+ def restore
10
+ History.includes(:history_attributes).find(params[:id]).restore
11
+ flash[:success] = 'Entity was restored from history'
12
+ end
13
+ end
14
+ end
@@ -8,5 +8,9 @@ module Flexite
8
8
  def self.model_name
9
9
  Config.model_name
10
10
  end
11
+
12
+ def history_type
13
+ Config.name.underscore
14
+ end
11
15
  end
12
16
  end
@@ -6,6 +6,10 @@ module Flexite
6
6
  def entries
7
7
  @entries ||= []
8
8
  end
9
+
10
+ def with_history?
11
+ false
12
+ end
9
13
  end
10
14
  end
11
15
  end
@@ -12,5 +12,13 @@ module Flexite
12
12
  def view_type
13
13
  type.demodulize.underscore
14
14
  end
15
+
16
+ def history_type
17
+ Entry.name.underscore
18
+ end
19
+
20
+ def with_history?
21
+ persisted?
22
+ end
15
23
  end
16
24
  end
@@ -33,11 +33,12 @@ module Flexite
33
33
  concat(form.simple_fields_for(:entries, entry_form, index: index) do |fields|
34
34
  delete_link = link_to 'Delete', destroy_array_entries_path(id: entry.id, selector: "#{fields.object_name}-#{index}-#{entry.id}"),
35
35
  remote: true, method: :delete, class: 'btn btn-danger'
36
+ history_link = link_to 'History', entity_history_path(entry_form.id, entry_form.history_type), remote: true, class: 'btn btn-default'
36
37
 
37
38
  concat(content_tag(:div, id: "#{fields.object_name}-#{index}-#{entry.id}") do
38
39
  concat fields.input :id, as: :hidden
39
40
  concat fields.input :type, as: :hidden
40
- concat render "types/#{entry_form.view_type}", f: fields, delete_link: delete_link
41
+ concat render "flexite/entries/types/#{entry_form.view_type}", f: fields, delete_link: delete_link, history_link: history_link
41
42
  end)
42
43
  end)
43
44
  end
@@ -0,0 +1,49 @@
1
+ module Flexite
2
+ module WithHistory
3
+ extend ActiveSupport::Concern
4
+
5
+ included do
6
+ after_save :save_history
7
+
8
+ def self.history_attributes(*attributes)
9
+ define_method :history_attributes do
10
+ attributes
11
+ end
12
+ end
13
+ end
14
+
15
+ def restore(history)
16
+ history.history_attributes.each do |attr|
17
+ self[attr.name] = attr.value
18
+ end
19
+
20
+ self.class.skip_callback(:save, :after, :save_history)
21
+
22
+ begin
23
+ save!
24
+ ensure
25
+ self.class.set_callback(:save, :after, :save_history)
26
+ end
27
+ end
28
+
29
+ private
30
+
31
+ def save_history
32
+ return unless changed?
33
+
34
+ history = histories.build
35
+
36
+ History.transaction do
37
+ history_attributes.each do |attr|
38
+ history.history_attributes.build(name: attr, value: self[attr])
39
+ end
40
+
41
+ history.save
42
+ end
43
+
44
+ if history.invalid?
45
+ errors.set(:history, history.full_messages)
46
+ end
47
+ end
48
+ end
49
+ end
@@ -1,7 +1,7 @@
1
1
  module Flexite
2
2
  class BoolEntry < Entry
3
3
  def value
4
- self[:value].to_i == 1 ? true : false
4
+ self[:value].to_i == 1 ? true : false
5
5
  end
6
6
 
7
7
  def form
@@ -11,8 +11,14 @@ module Flexite
11
11
  private
12
12
 
13
13
  def check_value
14
+ unless self[:value].respond_to?(:to_i)
15
+ errors.add(:value, 'should respond to #to_i')
16
+ return false
17
+ end
18
+
14
19
  unless [1, 0].include?(self[:value].to_i)
15
- errors.add(:value, 'not a boolean')
20
+ errors.add(:value, 'not a valid boolean')
21
+ false
16
22
  end
17
23
  end
18
24
  end
@@ -1,13 +1,18 @@
1
1
  module Flexite
2
2
  class Config < ActiveRecord::Base
3
+ include WithHistory
3
4
  attr_accessible :name
5
+ history_attributes :name, :config_id
6
+ delegate :value, to: :entry, allow_nil: true
7
+
4
8
  belongs_to :config, touch: true
5
9
  belongs_to :owner, foreign_key: :created_by
6
10
  has_one :entry, as: :parent, dependent: :destroy
7
11
  has_many :configs, dependent: :destroy
12
+ has_many :histories, as: :entity, dependent: :destroy
8
13
 
9
14
  scope :not_selectable, -> { select([:id, :name]).where(selectable: false) }
10
- delegate :value, to: :entry, allow_nil: true
15
+
11
16
  validates :name, uniqueness: { scope: :config_id }
12
17
 
13
18
  def to_tree_node
@@ -1,7 +1,12 @@
1
1
  module Flexite
2
2
  class Entry < ActiveRecord::Base
3
- belongs_to :parent, polymorphic: true, touch: true
3
+ include WithHistory
4
4
  attr_accessible :value
5
+ history_attributes :value
6
+
7
+ belongs_to :parent, polymorphic: true, touch: true
8
+ has_many :histories, as: :entity, dependent: :destroy
9
+
5
10
  before_save :check_value, :cast_value
6
11
 
7
12
  def view_value
@@ -0,0 +1,21 @@
1
+ module Flexite
2
+ class History < ActiveRecord::Base
3
+ belongs_to :entity, polymorphic: true
4
+ has_many :history_attributes, dependent: :destroy
5
+
6
+ after_save :check_limit
7
+
8
+ validates_presence_of :entity
9
+
10
+ def restore
11
+ entity.restore(self)
12
+ end
13
+
14
+ private
15
+
16
+ def check_limit
17
+ return if entity.histories.count <= Flexite.config.history_limit
18
+ entity.histories.order(:id).first.destroy
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,6 @@
1
+ module Flexite
2
+ class HistoryAttribute < ActiveRecord::Base
3
+ attr_accessible :name, :value
4
+ belongs_to :history
5
+ end
6
+ end
@@ -9,5 +9,6 @@ class Flexite::IntEntry < Flexite::Entry
9
9
  self[:value].to_i
10
10
  rescue
11
11
  errors.add(:value, 'not an Integer')
12
+ false
12
13
  end
13
14
  end
@@ -13,5 +13,6 @@ class Flexite::SymEntry < Flexite::Entry
13
13
  self[:value].to_sym
14
14
  rescue
15
15
  errors(:value, 'cannot be casted to Symbol')
16
+ false
16
17
  end
17
18
  end
@@ -1,6 +1,4 @@
1
1
  class Flexite::ActionService
2
- extend ActiveSupport::Autoload
3
- autoload :Result
4
2
 
5
3
  def initialize(form, params = {})
6
4
  @form = form
@@ -33,3 +31,5 @@ class Flexite::ActionService
33
31
  end
34
32
  end
35
33
  end
34
+
35
+ require_dependency 'flexite/action_service/result'
@@ -6,8 +6,13 @@ module Flexite
6
6
  if @form.invalid?
7
7
  return failure
8
8
  end
9
+ record = @form.type.constantize.find(@form.id)
10
+ record.value = @form.value
11
+
12
+ if record.changed?
13
+ record.save
14
+ end
9
15
 
10
- @form.type.constantize.update(@form.id, value: @form.value)
11
16
  success
12
17
  end
13
18
 
@@ -5,3 +5,6 @@
5
5
  input_html: { class: 'form-control', placeholder: 'Parent' }, label: false, prompt: 'Select parent'
6
6
  = f.input :selectable, as: :boolean, label: false, wrapper_html: { class: 'checkbox' }
7
7
  = f.button :submit, class: 'btn btn-success'
8
+
9
+ - if @config_form.persisted?
10
+ = link_to 'History', entity_history_path(@config_form.id, @config_form.history_type), remote: true, class: 'btn btn-default'
@@ -1,6 +1,6 @@
1
1
  = simple_form_for @entry_form, remote: true do |f|
2
2
  - if @entry_form.type.present?
3
- = render "types/#{@entry_form.view_type}", f: f
3
+ = render "flexite/entries/types/#{@entry_form.view_type}", f: f
4
4
  = f.input :id, as: :hidden
5
5
  = f.input :type, as: :hidden
6
6
  = f.input :parent_id, as: :hidden
@@ -9,3 +9,5 @@
9
9
 
10
10
  - if @entry_form.persisted?
11
11
  = link_to 'Delete', entry_path(f.object, type: @entry_form.type), method: :delete, remote: true, class: 'btn btn-danger'
12
+ - if @entry_form.with_history?
13
+ = link_to 'History', entity_history_path(@entry_form.id, @entry_form.history_type), remote: true, class: 'btn btn-default'
@@ -2,3 +2,5 @@
2
2
  = f.input :value, collection: [[:true, 1], [:false, 0]], input_html: { class: 'form-control' }, include_blank: false, label: false
3
3
  - if local_assigns[:delete_link].present?
4
4
  = delete_link
5
+ - if local_assigns[:history_link].present?
6
+ = history_link
@@ -2,3 +2,5 @@
2
2
  = f.input :value, as: :integer, input_html: { class: 'form-control', placeholder: 'Number' }, label: false
3
3
  - if local_assigns[:delete_link].present?
4
4
  = delete_link
5
+ - if local_assigns[:history_link].present?
6
+ = history_link
@@ -2,3 +2,5 @@
2
2
  = f.input :value, as: :string, input_html: { class: 'form-control', placeholder: 'String' }, label: false
3
3
  - if local_assigns[:delete_link].present?
4
4
  = delete_link
5
+ - if local_assigns[:history_link].present?
6
+ = history_link
@@ -1 +1 @@
1
- = render 'types/str_entry', f: f, delete_link: local_assigns[:delete_link]
1
+ = render 'flexite/entries/types/str_entry', f: f, delete_link: local_assigns[:delete_link]
@@ -0,0 +1,11 @@
1
+ - history.history_attributes.each do |attr|
2
+ .history-attribute
3
+ = "#{attr.name}: "
4
+ = attr.value
5
+
6
+ .history-created-at
7
+ created at:
8
+ = history.created_at.to_s(:db)
9
+
10
+ .history-restore
11
+ = link_to 'Restore', history_restore_path(history), remote: true, class: 'btn btn-warning'
@@ -0,0 +1 @@
1
+ $flexite("#section-3").html("#{j render @histories}");
@@ -0,0 +1,4 @@
1
+ = render 'flexite/shared/show_flash'
2
+ $flexite("#section-2").html("");
3
+ $flexite("#section-3").html("");
4
+ tree.unselectAll();
data/config/routes.rb CHANGED
@@ -13,5 +13,7 @@ Flexite::Engine.routes.draw do
13
13
  get :reload, on: :collection
14
14
  end
15
15
 
16
+ get ':entity_id/:entity_type/history', to: 'histories#index', as: :entity_history, constraints: { entity_type: /.*/ }
17
+ get ':id/restore', to: 'histories#restore', as: :history_restore
16
18
  root to: 'application#index'
17
19
  end
@@ -0,0 +1,12 @@
1
+ class CreateFlexiteHistories < ActiveRecord::Migration
2
+ def change
3
+ create_table :flexite_histories do |t|
4
+ t.references :entity, polymorphic: true
5
+
6
+ t.timestamps
7
+ end
8
+
9
+ add_index :flexite_histories, :entity_id
10
+ add_index :flexite_histories, :entity_type
11
+ end
12
+ end
@@ -0,0 +1,13 @@
1
+ class CreateFlexiteHistoryAttributes < ActiveRecord::Migration
2
+ def change
3
+ create_table :flexite_history_attributes do |t|
4
+ t.references :history
5
+ t.string :name
6
+ t.string :value
7
+
8
+ t.timestamps
9
+ end
10
+
11
+ add_index :flexite_history_attributes, :history_id
12
+ end
13
+ end
@@ -1,7 +1,7 @@
1
1
  module Flexite
2
2
  class Configuration
3
3
  attr_accessor :paths, :root_cache_key, :source_roots, :hierarchy
4
- attr_accessor :app_link, :app_name
4
+ attr_accessor :app_link, :app_name, :history_limit
5
5
  attr_reader :cache
6
6
 
7
7
  def initialize
@@ -11,6 +11,7 @@ module Flexite
11
11
  @app_link = '/'
12
12
  @source_roots = {}
13
13
  @hierarchy = {}
14
+ @history_limit = 10
14
15
  end
15
16
 
16
17
  def cache_store=(*args)
@@ -14,5 +14,6 @@ module Flexite
14
14
  end
15
15
 
16
16
  config.action_controller.include_all_helpers = false
17
+ config.paths.add 'app/models/concerns', eager_load: true
17
18
  end
18
19
  end
@@ -1,3 +1,3 @@
1
1
  module Flexite
2
- VERSION = '0.0.4'
2
+ VERSION = '0.0.5'
3
3
  end