Class: ActionBlocks::TableBuilder

Inherits:
BlockType show all
Defined in:
lib/action_blocks/builders/table_builder.rb

Instance Attribute Summary collapse

Attributes inherited from BaseBuilder

#dsl_delegate, #id

Instance Method Summary collapse

Methods inherited from BlockType

#is_block?, #type

Methods inherited from BaseBuilder

#after_load, array_fields, block_type, builds, builds_many, delegate_class, #evaluate, #freeze, includes_scheme_helpers, #initialize, #is_block?, references, sets, sets_many, #ui_reference, #valid?

Constructor Details

This class inherits a constructor from ActionBlocks::BaseBuilder

Instance Attribute Details

#dashboardObject

Returns the value of attribute dashboard.



3
4
5
# File 'lib/action_blocks/builders/table_builder.rb', line 3

def dashboard
  @dashboard
end

#subspaceObject

Returns the value of attribute subspace.



3
4
5
# File 'lib/action_blocks/builders/table_builder.rb', line 3

def subspace
  @subspace
end

#workspaceObject

Returns the value of attribute workspace.



3
4
5
# File 'lib/action_blocks/builders/table_builder.rb', line 3

def workspace
  @workspace
end

Instance Method Details

#after_build(_parent, *_args) ⇒ Object

Create a field reference for each column



50
51
52
53
54
# File 'lib/action_blocks/builders/table_builder.rb', line 50

def after_build(_parent, *_args)
  (@columns || []).each do |c|
    @dsl_delegate.col(c)
  end
end

#allowed_columns(_user) ⇒ Object



60
61
62
63
64
65
# File 'lib/action_blocks/builders/table_builder.rb', line 60

def allowed_columns(_user)
  model_associations = model.active_model.reflect_on_all_associations(:belongs_to)
  model_association_columns = model_associations.map { |ma| ma.name.to_s + '_id' }
  columns = [:id] + @columns + model_association_columns
  columns.uniq
end

#before_build(parent, *args) ⇒ Object



41
42
43
44
45
46
47
# File 'lib/action_blocks/builders/table_builder.rb', line 41

def before_build(parent, *args)
  @dashboard = parent
  @subspace = @dashboard.subspace
  @workspace = @subspace.workspace
  @title = id.to_s.titleize
  @id = args[0]
end

#builder_engine(params:, user:) ⇒ Object



215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
# File 'lib/action_blocks/builders/table_builder.rb', line 215

def builder_engine(params:, user:)
  klass = model.active_model
  selection_match_reqs = selection_match_requirements(user)
  record = selection_record(params: params, user: user)
  filter_reqs = filter_requirements(user: user, record: record)

  # pp({
  #   record: record,
  #   select_fields: select_fields,
  #   selection_match_reqs: selection_match_reqs,
  #   filter_reqs: filter_reqs
  # })

  data_engine = ActionBlocks::DataEngine.new(klass,
    select_fields: select_fields,
    selection_match_reqs: selection_match_reqs,
    selection_filter_reqs: filter_reqs
  )
  data_engine
end

#builder_to_json(params:, user:) ⇒ Object



236
237
238
239
# File 'lib/action_blocks/builders/table_builder.rb', line 236

def builder_to_json(params:, user:)
  engine = builder_engine(params: params, user: user)
  return engine.to_json
end

#data_select_fieldsObject

Reason to move logic to model would be to centralize user level access to columns



94
95
96
# File 'lib/action_blocks/builders/table_builder.rb', line 94

def data_select_fields
  @table_columns.map(&:field)
end

#filter_requirements(user:, record:) ⇒ Object



82
83
84
85
86
87
88
# File 'lib/action_blocks/builders/table_builder.rb', line 82

def filter_requirements(user:, record:)
  filter_reqs = []
  if selection && record
    filter_reqs << selection.record_filter_reqs(user: user, record: record)
  end
  return filter_reqs.flatten
end

#hashify(_user) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
# File 'lib/action_blocks/builders/table_builder.rb', line 127

def hashify(_user)
  {
    title: @title,
    key: key,
    type: type,
    column_keys: allowed_columns(nil),
    view: @view,
    model_key: model.key,
    table_columns: @table_columns.map(&:hashify)
  }
end

#keyObject



56
57
58
# File 'lib/action_blocks/builders/table_builder.rb', line 56

def key
  "table-#{workspace.id}_#{subspace.id}_#{dashboard.id}_#{@id}"
end

#scope_args(params:, user:) ⇒ Object

Given params subspace_model_id and/or workspace_model_id Find records and create named arguments If subspace_model_id was 4 and this table was in a subspace belonging to Work Order arguments would be { work_order: WorkOrder.find(4) }



143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
# File 'lib/action_blocks/builders/table_builder.rb', line 143

def scope_args(params:, user:)
  if scope
    subspace_variable_name = subspace.model.try(:id).try(:to_sym) # returns a label such as :work_order
    dashboard_variable_name = dashboard.model.try(:id).try(:to_sym) # returns a label such as :work_order
    args = {}
    if subspace_variable_name && scope.parameters.include?([:keyreq, subspace_variable_name])
      subspace_record = subspace.model.active_model.find(params[:subspace_model_id])
      # Todo: check user has read access to subspace record
      args[subspace_variable_name] = subspace_record
    end
    if dashboard_variable_name && scope.parameters.include?([:keyreq, dashboard_variable_name])
      dashboard_record = dashboard.model.active_model.find(params[:dashboard_model_id])
      # Todo: check user has read access to dashboard_record
      args[dashboard_variable_name] = dashboard_record
    end
    if scope.parameters.include?([:keyreq, :current_user])
      args[:current_user] = user
    end
    args
  else
    {}
  end
end

#scope_to_json(params:, user:) ⇒ Object

Legacy Support



206
207
208
209
210
211
212
213
# File 'lib/action_blocks/builders/table_builder.rb', line 206

def scope_to_json(params:, user:)
  if scope.parameters.length > 0
    s = scope.call(scope_args(params: params, user: user))
  else
    s = scope.call()
  end
  return s.to_json
end

#select_fieldsObject



67
68
69
70
71
72
# File 'lib/action_blocks/builders/table_builder.rb', line 67

def select_fields()
  [
    data_select_fields,
    view_link_select_fields
  ].flatten
end

#selection_match_requirements(user) ⇒ Object



74
75
76
77
78
79
80
# File 'lib/action_blocks/builders/table_builder.rb', line 74

def selection_match_requirements(user)
  if selection
    selection.match_reqs(user)
  else
    []
  end
end

#selection_record(params:, user: nil) ⇒ Object

Given params subspace_model_id and/or workspace_model_id Get the parent selection record



169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
# File 'lib/action_blocks/builders/table_builder.rb', line 169

def selection_record(params:, user: nil)
  if selection
    subspace_model_name = subspace.model.try(:id).try(:to_sym) # returns a label such as :work_order
    dashboard_model_name = dashboard.model.try(:id).try(:to_sym) # returns a label such as :work_order
    selection_model_name = selection.base_model.try(:id).try(:to_sym)

    if !subspace_model_name.blank? && selection_model_name == subspace_model_name
      record = subspace.model.active_model.find(params[:subspace_model_id])
    end
    if !dashboard_model_name.blank? && selection_model_name == dashboard_model_name
      record = dashboard.model.active_model.find(params[:dashboard_model_id])
    end
    if dashboard_model_name == subspace_model_name
      raise "Ambiguous model nesting.  ActionBlock validation should have prevented this."
    end
    if dashboard_model_name != selection_model_name && subspace_model_name != selection_model_name
      raise "Invalid selection model.  ActionBlock validation should have prevented this."
    end
    record
  else
    nil
  end
end

#to_json(params:, user:) ⇒ Object



193
194
195
196
197
198
199
200
201
202
203
# File 'lib/action_blocks/builders/table_builder.rb', line 193

def to_json(params:, user:)
  if scope
    scope_to_json(params: params, user: user)
  else
    pp({
      params: params,
      user: user
    })
    builder_to_json(params: params, user: user)
  end
end

#validate_scopeObject



22
23
24
25
26
27
28
29
30
31
32
# File 'lib/action_blocks/builders/table_builder.rb', line 22

def validate_scope
  return unless scope
  errors.add(:scope, 'requires Proc -> () {}') if scope.class != Proc
  if scope && scope.class == Proc
    valid_parameters = [%i[keyreq current_user]]
    valid_parameters << [:keyreq, dashboard.model.id.to_sym] if dashboard.model
    valid_parameters << [:keyreq, subspace.model.id.to_sym] if subspace.model
    invalid_parameters = scope.parameters - valid_parameters
    errors.add(:scope, "has invalid parameter: #{invalid_parameters}  Allowed: #{valid_parameters}") unless invalid_parameters.empty?
  end
end

#validate_selection_modelObject



35
36
37
38
39
# File 'lib/action_blocks/builders/table_builder.rb', line 35

def validate_selection_model
  if dashboard.model != selection_model && subspace.model != selection_model
    errors.add(:selection_model, "selection model not in subspace or dashboard")
  end
end

Technical debt deep discovery e.g. Subspace model being case

and this model being change order


102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
# File 'lib/action_blocks/builders/table_builder.rb', line 102

def view_link_select_fields
  # Find dashboards in modeled subspace
  @workspace.subspaces.each do |ss|
    next unless ss.model && ss.model.id != model.id
    ss.dashboards.each do |d|
      next unless d.model && d.model.id == model.id
      ref_f = model.fields.find do |f|
        f.field_type == 'reference' &&
          f.id == model.id &&
          f.model.id == ss.model.id
      end || model.fields.find do |f|
        f.field_type == 'reference' &&
          f.model.id == ss.model.id
      end
      return [
        model.fields_hash[:id],
        model.fields_hash[ref_f.relation.join_foreign_key.to_sym]
      ].flatten
    end
  end
  [
    model.fields_hash[:id]
  ]
end