action_blocks 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.
Files changed (69) hide show
  1. checksums.yaml +7 -0
  2. data/LICENSE +21 -0
  3. data/README.md +121 -0
  4. data/Rakefile +33 -0
  5. data/app/assets/config/action_blocks.js +2 -0
  6. data/app/assets/javascripts/action_blocks/application.js +15 -0
  7. data/app/assets/stylesheets/action_blocks/application.css +15 -0
  8. data/app/controllers/action_blocks/attachments_controller.rb +22 -0
  9. data/app/controllers/action_blocks/barchart_blocks_controller.rb +14 -0
  10. data/app/controllers/action_blocks/base_controller.rb +22 -0
  11. data/app/controllers/action_blocks/blocks_controller.rb +16 -0
  12. data/app/controllers/action_blocks/command_blocks_controller.rb +6 -0
  13. data/app/controllers/action_blocks/form_blocks_controller.rb +13 -0
  14. data/app/controllers/action_blocks/model_blocks_controller.rb +13 -0
  15. data/app/controllers/action_blocks/table_blocks_controller.rb +13 -0
  16. data/app/controllers/action_blocks/workspace_blocks_controller.rb +6 -0
  17. data/app/helpers/action_blocks/application_helper.rb +4 -0
  18. data/app/jobs/action_blocks/application_job.rb +4 -0
  19. data/app/mailers/action_blocks/application_mailer.rb +6 -0
  20. data/app/models/action_blocks/application_record.rb +5 -0
  21. data/app/views/layouts/action_blocks/application.html.erb +16 -0
  22. data/config/initializers/action_blocks.rb +9 -0
  23. data/config/routes.rb +10 -0
  24. data/lib/action_block_loader.rb +120 -0
  25. data/lib/action_blocks.rb +76 -0
  26. data/lib/action_blocks/builders/authorization_builder.rb +21 -0
  27. data/lib/action_blocks/builders/barchart_builder.rb +48 -0
  28. data/lib/action_blocks/builders/base_builder.rb +221 -0
  29. data/lib/action_blocks/builders/block_type.rb +11 -0
  30. data/lib/action_blocks/builders/command_builder.rb +6 -0
  31. data/lib/action_blocks/builders/form_builder.rb +117 -0
  32. data/lib/action_blocks/builders/layout_builder.rb +15 -0
  33. data/lib/action_blocks/builders/model_builder.rb +566 -0
  34. data/lib/action_blocks/builders/summary_field_aggregation_functions.rb +41 -0
  35. data/lib/action_blocks/builders/table_builder.rb +259 -0
  36. data/lib/action_blocks/builders/workspace_builder.rb +282 -0
  37. data/lib/action_blocks/data_engine/authorization_adapter.rb +127 -0
  38. data/lib/action_blocks/data_engine/data_engine.rb +116 -0
  39. data/lib/action_blocks/data_engine/database_functions.rb +39 -0
  40. data/lib/action_blocks/data_engine/fields_engine.rb +103 -0
  41. data/lib/action_blocks/data_engine/filter_adapter.rb +105 -0
  42. data/lib/action_blocks/data_engine/filter_engine.rb +88 -0
  43. data/lib/action_blocks/data_engine/selections_via_where_engine.rb +134 -0
  44. data/lib/action_blocks/data_engine/summary_engine.rb +72 -0
  45. data/lib/action_blocks/engine.rb +5 -0
  46. data/lib/action_blocks/error.rb +62 -0
  47. data/lib/action_blocks/generator_helper.rb +134 -0
  48. data/lib/action_blocks/generators/action_blocks/model_block/USAGE +8 -0
  49. data/lib/action_blocks/generators/action_blocks/model_block/model_block_generator.rb +17 -0
  50. data/lib/action_blocks/generators/action_blocks/model_block/templates/model_block.rb +13 -0
  51. data/lib/action_blocks/generators/action_blocks/type/USAGE +8 -0
  52. data/lib/action_blocks/generators/action_blocks/type/templates/controller.rb +3 -0
  53. data/lib/action_blocks/generators/action_blocks/type/templates/dsl.rb +38 -0
  54. data/lib/action_blocks/generators/action_blocks/type/templates/type.css +3 -0
  55. data/lib/action_blocks/generators/action_blocks/type/templates/type.js +22 -0
  56. data/lib/action_blocks/generators/action_blocks/type/type_generator.rb +33 -0
  57. data/lib/action_blocks/store.rb +151 -0
  58. data/lib/action_blocks/version.rb +3 -0
  59. data/lib/generators/active_blocks/model_block/USAGE +8 -0
  60. data/lib/generators/active_blocks/model_block/model_block_generator.rb +17 -0
  61. data/lib/generators/active_blocks/model_block/templates/model_block.rb +13 -0
  62. data/lib/generators/active_blocks/type/USAGE +8 -0
  63. data/lib/generators/active_blocks/type/templates/controller.rb +3 -0
  64. data/lib/generators/active_blocks/type/templates/dsl.rb +38 -0
  65. data/lib/generators/active_blocks/type/templates/type.css +3 -0
  66. data/lib/generators/active_blocks/type/templates/type.js +22 -0
  67. data/lib/generators/active_blocks/type/type_generator.rb +33 -0
  68. data/lib/tasks/active_blocks_tasks.rake +4 -0
  69. metadata +128 -0
@@ -0,0 +1,76 @@
1
+ require "action_blocks/engine"
2
+ require "action_blocks/version"
3
+ require 'action_block_loader'
4
+
5
+ module ActionBlocks
6
+
7
+ autoload :AuthorizationBuilder, 'action_blocks/builders/authorization_builder'
8
+ autoload :BarchartBuilder, 'action_blocks/builders/barchart_builder'
9
+ autoload :BaseBuilder, 'action_blocks/builders/base_builder'
10
+ autoload :BlockType, 'action_blocks/builders/block_type'
11
+ autoload :FormBuilder, 'action_blocks/builders/form_builder'
12
+ autoload :LayoutBuilder, 'action_blocks/builders/layout_builder'
13
+ autoload :ModelBuilder, 'action_blocks/builders/model_builder'
14
+ autoload :SummaryFieldAggregationFunctions, 'action_blocks/builders/summary_field_aggregation_functions'
15
+ autoload :TableBuilder, 'action_blocks/builders/table_builder'
16
+ autoload :WorkspaceBuilder, 'action_blocks/builders/workspace_builder'
17
+
18
+ # autoload :AuthorizationEngine, 'action_blocks/data_engine/authorization_engine'
19
+ autoload :AuthorizationAdapter, 'action_blocks/data_engine/authorization_adapter'
20
+ autoload :FilterAdapter, 'action_blocks/data_engine/filter_adapter'
21
+
22
+ autoload :DatabaseFunctions, 'action_blocks/data_engine/database_functions'
23
+ autoload :DataEngine, 'action_blocks/data_engine/data_engine'
24
+ autoload :FieldsEngine, 'action_blocks/data_engine/fields_engine'
25
+ autoload :FilterEngine, 'action_blocks/data_engine/filter_engine'
26
+ autoload :SelectionsViaWhereEngine, 'action_blocks/data_engine/selections_via_where_engine'
27
+ autoload :SummaryEngine, 'action_blocks/data_engine/summary_engine'
28
+
29
+ # autoload :BlocksController, 'action_blocks/app/controllers/action_blocks/blocks_controller'
30
+
31
+ autoload :Store, 'action_blocks/store'
32
+
33
+ class << self
34
+ attr_accessor :block_db, :loader, :selections_engine, :config
35
+ end
36
+
37
+ @config = {
38
+ fields_engine: FieldsEngine,
39
+ selections_engine: SelectionsViaWhereEngine,
40
+ filter_engine: FilterEngine,
41
+ summary_engine: SummaryEngine,
42
+ should_authorize: true,
43
+ authorization_adapter: AuthorizationAdapter
44
+ }
45
+
46
+ def self.block_store
47
+ self.block_db ||= ActionBlocks::Store.new
48
+ return self.block_db
49
+ end
50
+
51
+ def self.initial_load
52
+ Rails.application.config.after_initialize do
53
+ self.load
54
+ end
55
+ end
56
+
57
+
58
+ def self.load
59
+ self.loader = ActionBlocks::Loader.new('app/blocks')
60
+ self.loader.load!
61
+ self.block_store.after_load
62
+ self.loader.attach_reloader
63
+ self.block_store.freeze_builders
64
+ end
65
+
66
+ def self.unload
67
+ self.block_db = nil
68
+ end
69
+
70
+ def self.method_missing(m, *args, &block)
71
+ self.block_store.send(m, *args, &block)
72
+ end
73
+
74
+ end
75
+
76
+ require 'action_blocks/error'
@@ -0,0 +1,21 @@
1
+ module ActionBlocks
2
+ class AuthorizationBuilder < ActionBlocks::BlockType
3
+ block_type :authorization
4
+ sets :active_model
5
+ builds_many :rls, :grant, 'ActionBlocks::RlsBuilder'
6
+ includes_scheme_helpers
7
+ end
8
+
9
+ class RlsBuilder < ActionBlocks::BlockType
10
+ block_type :rls
11
+ sets :role
12
+ sets :filter
13
+ sets :scheme # Lisp like data structure sp
14
+
15
+ def before_build(parent, role, scheme=nil)
16
+ @role = role
17
+ @id = "#{parent.id}-#{role}"
18
+ @scheme = scheme
19
+ end
20
+ end
21
+ end
@@ -0,0 +1,48 @@
1
+ module ActionBlocks
2
+
3
+ class BarchartBuilder < ActionBlocks::BlockType
4
+ block_type :barchart
5
+ sets :title
6
+ sets :scope
7
+ sets :calculate
8
+ builds :group, 'ActionBlocks::BarchartGroupBuilder'
9
+ builds :subgroup, 'ActionBlocks::BarchartGroupBuilder'
10
+
11
+ def before_build(parent, *args)
12
+ @id = "#{parent.id}_#{args.first}"
13
+ @title = id.to_s.titleize
14
+ @calculate = :count
15
+ end
16
+
17
+ def hashify(user)
18
+ {
19
+ title: @title,
20
+ key: key,
21
+ type: type,
22
+ group: @group.try(:hashify, user),
23
+ subgroup: @subgroup.try(:hashify, user)
24
+ }
25
+ end
26
+ end
27
+
28
+ class BarchartGroupBuilder < ActionBlocks::BaseBuilder
29
+ sets :column
30
+ sets :order_by
31
+ sets :grouping_by
32
+
33
+ def before_build(parent, *args)
34
+ @column = args[0]
35
+ @order_by = :ascending
36
+ @grouping_by = :equal_values
37
+ end
38
+
39
+ def hashify(user)
40
+ {
41
+ column: @column,
42
+ order_by: @order_by,
43
+ grouping_by: @grouping_by
44
+ }
45
+ end
46
+ end
47
+
48
+ end
@@ -0,0 +1,221 @@
1
+ module ActionBlocks
2
+ class BaseBuilder
3
+ include ActiveModel::Validations
4
+ attr_accessor :id, :dsl_delegate
5
+
6
+ def self.block_type(t)
7
+ self.define_method("type") do
8
+ return t
9
+ end
10
+ end
11
+
12
+ # Dynamically create class to delegate dsl methods to
13
+ @@delegate_classes = {}
14
+ @@array_fields = {}
15
+
16
+ def self.delegate_class()
17
+ key = self.to_s
18
+ if @@delegate_classes[key] == nil
19
+ @@delegate_classes[key] = Class.new() do
20
+ def initialize(obj)
21
+ @obj = obj
22
+ end
23
+ end
24
+ end
25
+ @@delegate_classes[key]
26
+ end
27
+
28
+ def self.array_fields()
29
+ key = self.to_s
30
+ if @@array_fields[key] == nil
31
+ @@array_fields[key] = []
32
+ end
33
+ @@array_fields[key]
34
+ end
35
+
36
+ def self.sets(field_name)
37
+ self.send(:attr_accessor, field_name)
38
+ self.delegate_class.define_method(field_name) do |value|
39
+ @obj.send("#{field_name}=", value)
40
+ end
41
+ end
42
+
43
+ def self.builds(field_name, klass)
44
+ self.send(:attr_accessor, field_name)
45
+ self.delegate_class.define_method(field_name) do |*p, &block|
46
+ dsl_class = eval(klass.to_s)
47
+ n = dsl_class.new()
48
+ n.id = p.first
49
+ n.before_build(@obj, *p)
50
+ if n.is_block?
51
+ ActionBlocks.store(n)
52
+ end
53
+ ActionBlocks.add_to_validator(n)
54
+ n.dsl_delegate.instance_eval(&block) if block!=nil
55
+ n.after_build(@obj, p.first)
56
+ @obj.send("#{field_name}=", n)
57
+ end
58
+ end
59
+
60
+ def self.sets_many(field_name, entry_method)
61
+ self.array_fields().append(field_name)
62
+ self.send(:attr_accessor, field_name)
63
+ self.delegate_class.define_method(entry_method) do |*p, &block|
64
+ @obj.send(field_name).append(p.first)
65
+ end
66
+ end
67
+
68
+ # references :name_field, -> (s, obj) {"field-#{obj.id}-#{s}"}
69
+ # self.referendes block_type, [entry_method], [keyFn(f,Obj)]
70
+ def self.references(entry_method, block_type=nil, key_proc=nil, handler: nil)
71
+ block_type = block_type || entry_method
72
+ self.send(:attr_accessor, "#{entry_method}_key")
73
+
74
+ if handler
75
+ self.delegate_class.define_method(entry_method) do |*p|
76
+ handler.call(@obj, *p)
77
+ end
78
+ else
79
+ self.delegate_class.define_method(entry_method) do |*p|
80
+ reference_key = "#{entry_method}_key"
81
+ if key_proc
82
+ k = key_proc.call(p.first, @obj)
83
+ else
84
+ k = "#{block_type}-#{p.first}"
85
+ end
86
+ @obj.send("#{entry_method}_key=", k)
87
+ end
88
+ end
89
+
90
+ self.define_method(entry_method) do
91
+ k = send("#{entry_method}_key")
92
+ if k
93
+ return ActionBlocks.find(k)
94
+ else
95
+ return nil
96
+ end
97
+ end
98
+
99
+ self.validate "#{entry_method}_reference_is_valid".to_sym
100
+ self.define_method("#{entry_method}_reference_is_valid") do
101
+ reference_key = send("#{entry_method}_key")
102
+ if reference_key
103
+ if !ActionBlocks.find(reference_key)
104
+ errors.add(entry_method.to_sym, "Reference #{reference_key} doesn't match any block in store.")
105
+ end
106
+ end
107
+ end
108
+ end
109
+
110
+ def self.includes_scheme_helpers
111
+ self.delegate_class.define_method(:_and) do |*args|
112
+ return [:and, *args]
113
+ end
114
+
115
+ self.delegate_class.define_method(:_or) do |*args|
116
+ return [:or, *args]
117
+ end
118
+
119
+ self.delegate_class.define_method(:_eq) do |left, right|
120
+ return [:eq, left, right]
121
+ end
122
+
123
+ self.delegate_class.define_method(:_user) do |field|
124
+ return [:user, field]
125
+ end
126
+
127
+ self.delegate_class.define_method(:_not_eq) do |left, right|
128
+ return [:not_eq, left, right]
129
+ end
130
+ end
131
+
132
+ def self.builds_many(field_name, entry_method, klass)
133
+ self.array_fields().append(field_name)
134
+ self.define_method("#{field_name}_hash") do
135
+ Hash[self.send(field_name).map do |x|
136
+ [x.id, x]
137
+ end]
138
+ end
139
+
140
+ self.send(:attr_accessor, field_name)
141
+ self.delegate_class.define_method(entry_method) do |*p, &block|
142
+ dsl_class = eval(klass.to_s)
143
+ n = dsl_class.new()
144
+ n.id = p.first
145
+ n.before_build(@obj, *p)
146
+ if n.is_block?
147
+ ActionBlocks.store(n)
148
+ end
149
+ ActionBlocks.add_to_validator(n)
150
+ n.dsl_delegate.instance_eval(&block) if block!=nil
151
+ n.after_build(@obj, p.first)
152
+ if @obj.send(field_name) == nil
153
+ @obj.send("#{field_name}=",[n])
154
+ else
155
+ @obj.send(field_name).append(n)
156
+ end
157
+ end
158
+ end
159
+
160
+
161
+ def initialize()
162
+ @dsl_delegate = self.class.delegate_class.new(self)
163
+ self.class.array_fields.each do |array_field|
164
+ self.send("#{array_field}=", [])
165
+ end
166
+ end
167
+
168
+ def key
169
+ if(is_block?)
170
+ "#{type}-#{@id}"
171
+ else
172
+ @id
173
+ end
174
+ end
175
+
176
+ def ui_reference()
177
+ key()
178
+ end
179
+
180
+ def evaluate(&block)
181
+ @dsl_delegate.instance_eval(&block)
182
+ end
183
+
184
+ def before_build(parent, *p)
185
+ end
186
+
187
+ def after_build(parent, *p)
188
+ end
189
+
190
+ def after_load()
191
+ end
192
+
193
+ def is_block?
194
+ false
195
+ end
196
+
197
+
198
+ # Valid the object when freeze is called so the object
199
+ def freeze
200
+ self.valid?
201
+ super
202
+ end
203
+
204
+ # Runs all the specified validations and returns true if no errors were added
205
+ # otherwise false. Context can optionally be supplied to define which callbacks
206
+ # to test against (the context is defined on the validations using :on).
207
+ def valid?(context = nil)
208
+ unless self.frozen?
209
+ current_context, self.validation_context = validation_context, context
210
+ errors.clear
211
+ @valid = run_validations!
212
+ else
213
+ @valid
214
+ end
215
+ ensure
216
+ self.validation_context = current_context unless self.frozen?
217
+ end
218
+
219
+ end
220
+
221
+ end
@@ -0,0 +1,11 @@
1
+ module ActionBlocks
2
+ class BlockType < ActionBlocks::BaseBuilder
3
+ def is_block?
4
+ true
5
+ end
6
+
7
+ def type
8
+ raise "#{self.class} should specify its block_type."
9
+ end
10
+ end
11
+ end
@@ -0,0 +1,6 @@
1
+ module ActionBlocks
2
+
3
+ class CommandBuilder < ActionBlocks::BlockType
4
+ references :model
5
+ end
6
+ end
@@ -0,0 +1,117 @@
1
+ module ActionBlocks
2
+
3
+ class FormBuilder < ActionBlocks::BlockType
4
+ attr_accessor :form_fields, :model_id, :model_fields, :form_fields_hash, :model_fields_hash
5
+ block_type :form
6
+ references :model, handler: -> (form_builder, model_id) do
7
+ form_builder.model_key = "model-#{model_id}"
8
+ form_builder.model_id = model_id
9
+ end
10
+
11
+ builds_many :sections, :section, 'ActionBlocks::FormSectionBuilder'
12
+
13
+ def before_build(parent, *args)
14
+ @form_fields = []
15
+ @form_fields_hash = {}
16
+ end
17
+
18
+ def add_form_field(ff)
19
+ name = ff.id
20
+ @form_fields << ff
21
+ @form_fields_hash[name] = ff
22
+ end
23
+
24
+ def model_fields
25
+ @form_fields.map { |ff| ff.field }
26
+ end
27
+
28
+ def record_engine(user:, record_id:)
29
+ DataEngine.new(model.active_model,
30
+ filter_reqs: filter_reqs(user: user, record_id: record_id),
31
+ select_reqs: select_reqs(user: user)
32
+ )
33
+ end
34
+
35
+ def record_to_json(user:, record_id:)
36
+ record_engine(user: user, record_id: record_id).first_to_json
37
+ end
38
+
39
+ def select_reqs(user:)
40
+ srs = model_fields.map {|mf| mf.select_requirements }.flatten
41
+ end
42
+
43
+ def filter_reqs(user:, record_id:)
44
+ model.filter_reqs(user: user, record_id: record_id)
45
+ end
46
+
47
+ def hashify(user)
48
+ {
49
+ context: @context,
50
+ sections: @sections.map {|s| s.hashify(user)},
51
+ key: key,
52
+ type: type
53
+ }
54
+ end
55
+
56
+ end
57
+
58
+ # Section
59
+
60
+ class FormSectionBuilder < ActionBlocks::BaseBuilder
61
+ attr_accessor :form
62
+ sets :width
63
+ sets :title
64
+ builds_many :fields, :field, 'ActionBlocks::FormFieldBuilder'
65
+
66
+ def before_build(parent, *args)
67
+ @form = parent
68
+ @title = args[0].to_s.titleize
69
+ @width = 4
70
+ @label = @field.to_s.titleize
71
+ end
72
+
73
+ def hashify(user)
74
+ {
75
+ title: @title,
76
+ width: @width,
77
+ fields: @fields.map {|f| f.hashify(user)},
78
+ }
79
+ end
80
+ end
81
+
82
+ # Field
83
+
84
+ class FormFieldBuilder < ActionBlocks::BaseBuilder
85
+ attr_accessor :name, :form, :section
86
+ references :field
87
+ sets :width
88
+ sets :label
89
+ sets :label_above
90
+
91
+ def before_build(parent, *args)
92
+ @section = parent
93
+ @form = @section.form
94
+ @name = args[0]
95
+ @field_key = "field-#{@form.model_id}-#{@name}"
96
+ @width = parent.width
97
+ @label = @name.to_s.titleize
98
+ @label_above = false
99
+ end
100
+
101
+ def after_build(*args)
102
+ @form.add_form_field(self)
103
+ end
104
+
105
+ def hashify(user)
106
+ {
107
+ type: 'field',
108
+ field_key: @field_key,
109
+ label_above: @label_above,
110
+ label: @label,
111
+ width: @width,
112
+ }
113
+ end
114
+ end
115
+
116
+
117
+ end