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,41 @@
1
+ module ActionBlocks
2
+ module SummaryFieldAggregationFunctions
3
+ def count
4
+ # mk = @parent_reference.related_model_key.clone
5
+ # mk["model-"]=''
6
+ # field_key = "field-#{mk}-#{id}"
7
+ # field_builder = ActionBlocks.find(field_key)
8
+
9
+ return {
10
+ path: [:id],
11
+ function: ->(*args) { count(*args) }\
12
+ }
13
+ end
14
+
15
+ def concat(field, delimiter)
16
+ mk = @parent_reference.related_model_key.clone
17
+ mk["model-"]=''
18
+ field_key = "field-#{mk}-#{field}"
19
+ puts field_key
20
+ field_builder = ActionBlocks.find(field_key)
21
+
22
+ return {
23
+ path: field_builder.select_requirements[:path],
24
+ function: ->(*args) { string_agg(delimiter, *args) }
25
+ }
26
+ end
27
+
28
+ def every(field, predicate, value)
29
+ mk = @parent_reference.related_model_key.clone
30
+ mk["model-"]=''
31
+ field_key = "field-#{mk}-#{field}"
32
+ puts field_key
33
+ field_builder = ActionBlocks.find(field_key)
34
+
35
+ return {
36
+ path: field_builder.select_requirements[:path],
37
+ function: ->(*args) { every(predicate, value, *args) }
38
+ }
39
+ end
40
+ end
41
+ end
@@ -0,0 +1,259 @@
1
+ module ActionBlocks
2
+ class TableBuilder < ActionBlocks::BlockType
3
+ attr_accessor :workspace, :subspace, :dashboard
4
+ block_type :table
5
+ sets :title
6
+ sets :scope
7
+ sets :view
8
+ sets :columns
9
+ references :model
10
+ references :selection_model
11
+ references :selection, handler: -> (builder, model, selection) {
12
+ builder.selection_model_key = "model-#{model}"
13
+ builder.selection_key = "selection-#{model}-#{selection}"
14
+ }
15
+
16
+ builds_many :table_columns, :col, 'ActionBlocks::TableColumnBuilder'
17
+
18
+ validates :columns, presence: true
19
+ validates :model_key, presence: true
20
+
21
+ validate :scope, :validate_scope
22
+ def validate_scope
23
+ return unless scope
24
+ errors.add(:scope, 'requires Proc -> () {}') if scope.class != Proc
25
+ if scope && scope.class == Proc
26
+ valid_parameters = [%i[keyreq current_user]]
27
+ valid_parameters << [:keyreq, dashboard.model.id.to_sym] if dashboard.model
28
+ valid_parameters << [:keyreq, subspace.model.id.to_sym] if subspace.model
29
+ invalid_parameters = scope.parameters - valid_parameters
30
+ errors.add(:scope, "has invalid parameter: #{invalid_parameters} Allowed: #{valid_parameters}") unless invalid_parameters.empty?
31
+ end
32
+ end
33
+
34
+ validate :scope, :validate_selection_model
35
+ def validate_selection_model
36
+ if dashboard.model != selection_model && subspace.model != selection_model
37
+ errors.add(:selection_model, "selection model not in subspace or dashboard")
38
+ end
39
+ end
40
+
41
+ def before_build(parent, *args)
42
+ @dashboard = parent
43
+ @subspace = @dashboard.subspace
44
+ @workspace = @subspace.workspace
45
+ @title = id.to_s.titleize
46
+ @id = args[0]
47
+ end
48
+
49
+ # Create a field reference for each column
50
+ def after_build(_parent, *_args)
51
+ (@columns || []).each do |c|
52
+ @dsl_delegate.col(c)
53
+ end
54
+ end
55
+
56
+ def key
57
+ "table-#{workspace.id}_#{subspace.id}_#{dashboard.id}_#{@id}"
58
+ end
59
+
60
+ def allowed_columns(_user)
61
+ model_associations = model.active_model.reflect_on_all_associations(:belongs_to)
62
+ model_association_columns = model_associations.map { |ma| ma.name.to_s + '_id' }
63
+ columns = [:id] + @columns + model_association_columns
64
+ columns.uniq
65
+ end
66
+
67
+ def select_fields()
68
+ [
69
+ data_select_fields,
70
+ view_link_select_fields
71
+ ].flatten
72
+ end
73
+
74
+ def selection_match_requirements(user)
75
+ if selection
76
+ selection.match_reqs(user)
77
+ else
78
+ []
79
+ end
80
+ end
81
+
82
+ def filter_requirements(user:, record:)
83
+ filter_reqs = []
84
+ if selection && record
85
+ filter_reqs << selection.record_filter_reqs(user: user, record: record)
86
+ end
87
+ return filter_reqs.flatten
88
+ end
89
+
90
+ # Reason to move logic to model
91
+ # would be to centralize user level
92
+ # access to columns
93
+
94
+ def data_select_fields
95
+ @table_columns.map(&:field)
96
+ end
97
+
98
+ # Technical debt deep discovery
99
+ # e.g. Subspace model being case
100
+ # and this model being change order
101
+
102
+ def view_link_select_fields
103
+ # Find dashboards in modeled subspace
104
+ @workspace.subspaces.each do |ss|
105
+ next unless ss.model && ss.model.id != model.id
106
+ ss.dashboards.each do |d|
107
+ next unless d.model && d.model.id == model.id
108
+ ref_f = model.fields.find do |f|
109
+ f.field_type == 'reference' &&
110
+ f.id == model.id &&
111
+ f.model.id == ss.model.id
112
+ end || model.fields.find do |f|
113
+ f.field_type == 'reference' &&
114
+ f.model.id == ss.model.id
115
+ end
116
+ return [
117
+ model.fields_hash[:id],
118
+ model.fields_hash[ref_f.relation.join_foreign_key.to_sym]
119
+ ].flatten
120
+ end
121
+ end
122
+ [
123
+ model.fields_hash[:id]
124
+ ]
125
+ end
126
+
127
+ def hashify(_user)
128
+ {
129
+ title: @title,
130
+ key: key,
131
+ type: type,
132
+ column_keys: allowed_columns(nil),
133
+ view: @view,
134
+ model_key: model.key,
135
+ table_columns: @table_columns.map(&:hashify)
136
+ }
137
+ end
138
+
139
+ # Given params subspace_model_id and/or workspace_model_id
140
+ # Find records and create named arguments
141
+ # If subspace_model_id was 4 and this table was in a subspace belonging to Work Order
142
+ # arguments would be { work_order: WorkOrder.find(4) }
143
+ def scope_args(params:, user:)
144
+ if scope
145
+ subspace_variable_name = subspace.model.try(:id).try(:to_sym) # returns a label such as :work_order
146
+ dashboard_variable_name = dashboard.model.try(:id).try(:to_sym) # returns a label such as :work_order
147
+ args = {}
148
+ if subspace_variable_name && scope.parameters.include?([:keyreq, subspace_variable_name])
149
+ subspace_record = subspace.model.active_model.find(params[:subspace_model_id])
150
+ # Todo: check user has read access to subspace record
151
+ args[subspace_variable_name] = subspace_record
152
+ end
153
+ if dashboard_variable_name && scope.parameters.include?([:keyreq, dashboard_variable_name])
154
+ dashboard_record = dashboard.model.active_model.find(params[:dashboard_model_id])
155
+ # Todo: check user has read access to dashboard_record
156
+ args[dashboard_variable_name] = dashboard_record
157
+ end
158
+ if scope.parameters.include?([:keyreq, :current_user])
159
+ args[:current_user] = user
160
+ end
161
+ args
162
+ else
163
+ {}
164
+ end
165
+ end
166
+
167
+ # Given params subspace_model_id and/or workspace_model_id
168
+ # Get the parent selection record
169
+ def selection_record(params:, user: nil)
170
+ if selection
171
+ subspace_model_name = subspace.model.try(:id).try(:to_sym) # returns a label such as :work_order
172
+ dashboard_model_name = dashboard.model.try(:id).try(:to_sym) # returns a label such as :work_order
173
+ selection_model_name = selection.base_model.try(:id).try(:to_sym)
174
+
175
+ if !subspace_model_name.blank? && selection_model_name == subspace_model_name
176
+ record = subspace.model.active_model.find(params[:subspace_model_id])
177
+ end
178
+ if !dashboard_model_name.blank? && selection_model_name == dashboard_model_name
179
+ record = dashboard.model.active_model.find(params[:dashboard_model_id])
180
+ end
181
+ if dashboard_model_name == subspace_model_name
182
+ raise "Ambiguous model nesting. ActionBlock validation should have prevented this."
183
+ end
184
+ if dashboard_model_name != selection_model_name && subspace_model_name != selection_model_name
185
+ raise "Invalid selection model. ActionBlock validation should have prevented this."
186
+ end
187
+ record
188
+ else
189
+ nil
190
+ end
191
+ end
192
+
193
+ def to_json(params:, user:)
194
+ if scope
195
+ scope_to_json(params: params, user: user)
196
+ else
197
+ pp({
198
+ params: params,
199
+ user: user
200
+ })
201
+ builder_to_json(params: params, user: user)
202
+ end
203
+ end
204
+
205
+ # Legacy Support
206
+ def scope_to_json(params:, user:)
207
+ if scope.parameters.length > 0
208
+ s = scope.call(scope_args(params: params, user: user))
209
+ else
210
+ s = scope.call()
211
+ end
212
+ return s.to_json
213
+ end
214
+
215
+ def builder_engine(params:, user:)
216
+ klass = model.active_model
217
+ selection_match_reqs = selection_match_requirements(user)
218
+ record = selection_record(params: params, user: user)
219
+ filter_reqs = filter_requirements(user: user, record: record)
220
+
221
+ # pp({
222
+ # record: record,
223
+ # select_fields: select_fields,
224
+ # selection_match_reqs: selection_match_reqs,
225
+ # filter_reqs: filter_reqs
226
+ # })
227
+
228
+ data_engine = ActionBlocks::DataEngine.new(klass,
229
+ select_fields: select_fields,
230
+ selection_match_reqs: selection_match_reqs,
231
+ selection_filter_reqs: filter_reqs
232
+ )
233
+ data_engine
234
+ end
235
+
236
+ def builder_to_json(params:, user:)
237
+ engine = builder_engine(params: params, user: user)
238
+ return engine.to_json
239
+ end
240
+
241
+
242
+ end
243
+
244
+ class TableColumnBuilder < ActionBlocks::BaseBuilder
245
+ references :field
246
+ def before_build(parent, *args)
247
+ @id = args[0]
248
+ pm = parent.model_key.dup
249
+ pm['model-'] = ''
250
+ @field_key = "field-#{pm}-#{@id}"
251
+ end
252
+
253
+ def hashify
254
+ {
255
+ field_key: @field_key
256
+ }
257
+ end
258
+ end
259
+ end
@@ -0,0 +1,282 @@
1
+ module ActionBlocks
2
+
3
+ class WorkspaceBuilder < ActionBlocks::BlockType
4
+ block_type :workspace
5
+ sets :title
6
+ builds_many :subspaces, :subspace, 'ActionBlocks::SubspaceBuilder'
7
+ # builds_many :record_paths, :record_path, 'ActionBlocks::RecordPathBuilder'
8
+
9
+ validate :one_route_per_model
10
+ validate :one_non_model_subspace_per_category
11
+
12
+ def one_non_model_subspace_per_category
13
+ subspace_categories.each do |sc|
14
+ if @subspaces.
15
+ select {|ss| ss.category == sc && ss.model_key.nil? }.count > 1
16
+ errors.add(:subspaces, "Subspace category #{sc.to_s} has more than one non-modeled subspace")
17
+ end
18
+ end
19
+ end
20
+
21
+ def one_route_per_model
22
+ models = subspaces.map {|ss| ss.model_key}.compact
23
+ subspaces.each do |ss|
24
+ models += ss.dashboards.map {|ss| ss.model_key}.compact
25
+ end
26
+ models.uniq.each do |model|
27
+ if models.select {|m| model == m}.count > 1
28
+ errors.add(:subspaces, "More than one subspace or dashboard uses model #{model}")
29
+ end
30
+ end
31
+ end
32
+
33
+ def before_build(parent, *args)
34
+ @title = args[0].to_s.titleize
35
+ end
36
+
37
+ def subspace_categories
38
+ @subspaces.map(&:category).uniq
39
+ end
40
+
41
+ def model_paths
42
+ subspace_paths.merge(dashboard_paths)
43
+ end
44
+
45
+ def subspace_paths
46
+ paths = {}
47
+ @subspaces.each do |ss|
48
+ if ss.model_key
49
+ paths[ss.model_key] = {
50
+ path_type: :subspace,
51
+ subspace_category: ss.category,
52
+ subspace_model: ss.model_key,
53
+ subspace_key: ss.key
54
+ }
55
+ end
56
+ end
57
+ return paths
58
+ end
59
+
60
+ def dashboard_paths
61
+ paths = {}
62
+ @subspaces.each do |ss|
63
+ if ss.model_key
64
+ ss.dashboards.each do |ds|
65
+ paths[ds.model_key] = {
66
+ path_type: :dashboard,
67
+ subspace_category: ss.category,
68
+ subspace_model: ss.model_key,
69
+ subspace_key: ss.key,
70
+ dashboard_category: ds.category,
71
+ dashboard_model: ds.model_key,
72
+ dashboard_key: ds.key
73
+ }
74
+ end
75
+ end
76
+ end
77
+ return paths
78
+ end
79
+
80
+ def hashify_subspace_categories(user)
81
+ isFirst = true
82
+ results = []
83
+ subspace_categories.each do |category|
84
+ results << {
85
+ first: isFirst,
86
+ type: 'subspace_category',
87
+ category: category,
88
+ title: category.to_s.titleize,
89
+ subspaces: @subspaces.
90
+ select {|ss| ss.category == category}.
91
+ map { |ss| ss.hashify(user) },
92
+ }
93
+ isFirst = false
94
+ end
95
+ return results
96
+ end
97
+
98
+ def hashify(user)
99
+ {
100
+ # key: key,
101
+ title: @title,
102
+ id: @id,
103
+ subspaces: @subspaces.map { |ss| ss.hashify(user) },
104
+ subspace_categories: hashify_subspace_categories(user),
105
+ model_paths: model_paths
106
+ # record_paths: @record_paths.map { |rp| rp.hashify(user) }
107
+ }
108
+ end
109
+ end
110
+
111
+ # class RecordPathBuilder < ActionBlocks::BaseBuilder
112
+ # sets :model # currently used by table to find this
113
+ #
114
+ # sets :subspace # What path/url to share to control active navigation
115
+ # sets :recordspace # What recordspace to render
116
+ # sets :dashboard # What path/url of the recordspace dashboard to control active navigation
117
+ # sets :recordboard # What recordboard to render
118
+ #
119
+ # def before_build(parent, *args)
120
+ # # When Creating Links for Records of type @model
121
+ # @model = args[0]
122
+ # # Create Links with this information
123
+ # @subspace = args[1]
124
+ # @recordspace = args[2]
125
+ # @dashboard = args[3]
126
+ # @recordboard = args[4]
127
+ # end
128
+ #
129
+ # def hashify(user)
130
+ # {
131
+ # model: @model,
132
+ # subspace: @subspace,
133
+ # dashboard: @dashboard,
134
+ # recordspace: @recordspace,
135
+ # recordboard: @recordboard
136
+ # }
137
+ # end
138
+ # end
139
+
140
+ class SubspaceBuilder < ActionBlocks::BaseBuilder
141
+ attr_accessor :workspace
142
+ sets :title
143
+ sets :category
144
+ references :model
145
+ builds_many :dashboards, :dashboard, 'ActionBlocks::DashboardBuilder'
146
+ sets_many :recordspace_keys, :mounts
147
+
148
+ validates :category, presence: true
149
+
150
+ def key
151
+ "subspace-#{@id}".to_sym
152
+ end
153
+
154
+ def before_build(parent, *args)
155
+ @workspace = parent
156
+ @title = args[0].to_s.titleize
157
+ @category = args[0]
158
+ if args[1]
159
+ @model_key = "model-#{args[1]}"
160
+ end
161
+ end
162
+
163
+ def dashboard_categories
164
+ @dashboards.map(&:category).uniq
165
+ end
166
+
167
+ def hashify_dashboard_categories(user)
168
+ isFirst = true
169
+ results = []
170
+ dashboard_categories.each do |category|
171
+ results << {
172
+ first: isFirst,
173
+ type: 'dashboard_categories',
174
+ category: category,
175
+ title: category.to_s.titleize,
176
+ dashboards: @dashboards.
177
+ select {|d| d.category == category}.
178
+ map { |d| d.hashify(user) },
179
+ }
180
+ isFirst = false
181
+ end
182
+ return results
183
+ end
184
+
185
+
186
+ def hashify(user)
187
+ {
188
+ key: key,
189
+ title: @title,
190
+ category: @category,
191
+ model: @model_key,
192
+ dashboards: @dashboards.map{ |db| db.hashify(user) },
193
+ dashboard_categories: hashify_dashboard_categories(user),
194
+ recordspace_keys: @recordspace_keys
195
+ }
196
+ end
197
+ end
198
+
199
+ class DashboardBuilder < ActionBlocks::BaseBuilder
200
+ attr_accessor :workspace, :subspace
201
+ sets :title
202
+ sets :category
203
+ references :model
204
+ builds_many :dashlets, :table, 'ActionBlocks::TableBuilder'
205
+ builds_many :dashlets, :barchart, 'ActionBlocks::BarchartBuilder'
206
+ builds_many :dashlets, :mount_form, 'ActionBlocks::MountedFormBuilder'
207
+
208
+ def before_build(parent, *args)
209
+ @subspace = parent
210
+ @workspace = @subspace.workspace
211
+ @category = args[0]
212
+ @title = @category.to_s.titleize
213
+ if args[1]
214
+ @model_key = "model-#{args[1]}"
215
+ end
216
+ end
217
+
218
+ validates :category, presence: true
219
+ validate :has_unique_dashlets
220
+ def has_unique_dashlets
221
+ @dashlets.group_by(&:key).each do |k, dashlets|
222
+ if(dashlets.length > 1)
223
+ d = dashlets.first
224
+ errors.add(:dashlets, "Duplicate #{d.type.inspect} added to dashboard #{workspace.id}/#{subspace.id}/#{id} with id #{d.id.inspect}")
225
+ end
226
+ end
227
+ end
228
+
229
+ def hashify(user)
230
+ {
231
+ key: key,
232
+ title: @title,
233
+ model: @model_key,
234
+ category: @category,
235
+ dashlet_keys: @dashlets.map(&:key)
236
+ }
237
+ end
238
+ end
239
+
240
+ class MountedFormBuilder < ActionBlocks::BlockType
241
+ block_type :mounted_form
242
+ references :form
243
+
244
+ def before_build(parent, *args)
245
+ @id = args[0]
246
+ @dashboard = parent
247
+ @subspace = @dashboard.subspace
248
+ @form_key = "form-#{@id}"
249
+ end
250
+
251
+ # validate :validate_mounted_to
252
+ # def validate_mounted_to
253
+ # return unless [:dashboard, :subspace].include?(@mounted_to)
254
+ # errors.add(:mounted_to, "#{@parent.key} #{type} must be mounted to :dashboard or :subspace but #{@mounted_to.inspect} was specified.")
255
+ # end
256
+ #
257
+ # validate :validate_mount_point_matches_model
258
+ # def validate_mount_point_matches_model
259
+ # # TODO
260
+ # end
261
+
262
+ def after_load
263
+ # After load is called after all blocks are in the store
264
+ if form.model.id == @subspace.model.try(:id)
265
+ @mounted_to = :subspace
266
+ end
267
+ if form.model.id == @dashboard.model.try(:id)
268
+ @mounted_to = :dashboard
269
+ end
270
+ end
271
+
272
+ def hashify(user)
273
+ {
274
+ type: :mounted_form,
275
+ form_key: @form_key,
276
+ mounted_to: @mounted_to
277
+ }
278
+ end
279
+ end
280
+
281
+
282
+ end