module ViewModel::Controller

Public Instance Methods

prerender_json_view(json_view, json_references: {}) { |json| ... } click to toggle source
# File lib/view_model/controller.rb, line 45
def prerender_json_view(json_view, json_references: {})
  json_view = wrap_json_view(json_view)
  json_references = wrap_json_view(json_references)

  encode_jbuilder do |json|
    json.data json_view
    if json_references.present?
      json.references do
        json_references.sort.each do |key, value|
          json.set!(key, value)
        end
      end
    end
    yield(json) if block_given?
  end
end
prerender_viewmodel(viewmodel, status: nil, serialize_context: viewmodel.class.try(:new_serialize_context)) { |json| ... } click to toggle source

Render viewmodel(s) to a JSON API response as a String

# File lib/view_model/controller.rb, line 21
def prerender_viewmodel(viewmodel, status: nil, serialize_context: viewmodel.class.try(:new_serialize_context))
  encode_jbuilder do |json|
    json.data do
      ViewModel.serialize(viewmodel, json, serialize_context: serialize_context)
    end

    if serialize_context && serialize_context.has_references?
      json.references do
        serialize_context.serialize_references(json)
      end
    end

    yield(json) if block_given?
  end
end
render_error(error_view, status = 500) click to toggle source
# File lib/view_model/controller.rb, line 62
def render_error(error_view, status = 500)
  unless error_view.is_a?(ViewModel)
    raise "Expected ViewModel error view, received #{error_view.inspect}"
  end

  render_jbuilder(status: status) do |json|
    json.error do
      ctx = error_view.class.new_serialize_context(access_control: ViewModel::AccessControl::Open.new)
      ViewModel.serialize(error_view, json, serialize_context: ctx)
    end
  end
end
render_json_view(json_view, json_references: {}, status: nil, &block) click to toggle source

Render an arbitrarily nested tree of hashes and arrays with pre-rendered JSON string terminals. Useful for rendering cached views without parsing then re-serializing the cached JSON.

# File lib/view_model/controller.rb, line 40
def render_json_view(json_view, json_references: {}, status: nil, &block)
  prerender = prerender_json_view(json_view, json_references: json_references, &block)
  render_json_string(prerender, status: status)
end
render_viewmodel(viewmodel, status: nil, serialize_context: viewmodel.class.try(:new_serialize_context), &block) click to toggle source
# File lib/view_model/controller.rb, line 15
def render_viewmodel(viewmodel, status: nil, serialize_context: viewmodel.class.try(:new_serialize_context), &block)
  prerender = prerender_viewmodel(viewmodel, serialize_context: serialize_context, &block)
  render_json_string(prerender, status: status)
end

Protected Instance Methods

parse_bulk_update() click to toggle source
# File lib/view_model/controller.rb, line 89
def parse_bulk_update
  data, references = parse_viewmodel_updates

  ViewModel::Schemas.verify_schema!(ViewModel::Schemas::BULK_UPDATE, data)

  updates_by_parent =
    data.fetch(ViewModel::BULK_UPDATES_ATTRIBUTE).each_with_object({}) do |parent_update, acc|
      parent_id = parent_update.fetch(ViewModel::ID_ATTRIBUTE)
      update    = parent_update.fetch(ViewModel::BULK_UPDATE_ATTRIBUTE)

      acc[parent_id] = update
    end

  return updates_by_parent, references
end
parse_viewmodel_updates() click to toggle source
# File lib/view_model/controller.rb, line 77
def parse_viewmodel_updates
  data_param = params.fetch(:data) do
    raise ViewModel::Error.new(status: 400, detail: "Missing 'data' parameter")
  end
  refs_param = params.fetch(:references, {})

  update_hash = _extract_update_data(data_param)
  refs        = _extract_param_hash(refs_param)

  return update_hash, refs
end

Private Instance Methods

_extract_param_hash(data) click to toggle source
# File lib/view_model/controller.rb, line 120
def _extract_param_hash(data)
  case data
  when Hash
    data
  when ActionController::Parameters
    data.to_unsafe_h
  else
    raise ViewModel::Error.new(status: 400, detail: "Invalid data submitted, expected hash: #{data.inspect}")
  end
end
_extract_update_data(data) click to toggle source
# File lib/view_model/controller.rb, line 108
def _extract_update_data(data)
  if data.is_a?(Array)
    if data.blank?
      raise ViewModel::Error.new(status: 400, detail: "No data submitted: #{data.inspect}")
    end

    data.map { |el| _extract_param_hash(el) }
  else
    _extract_param_hash(data)
  end
end
encode_jbuilder() { |json| ... } click to toggle source
# File lib/view_model/controller.rb, line 131
def encode_jbuilder
  builder = Jbuilder.new do |json|
    yield json
  end

  ViewModel.encode_json(builder.attributes!)
end
render_jbuilder(status:) { |json| ... } click to toggle source
# File lib/view_model/controller.rb, line 139
def render_jbuilder(status:)
  response = encode_jbuilder do |json|
    yield json
  end

  render_json_string(response, status: status)
end
render_json_string(response, status: nil) click to toggle source
# File lib/view_model/controller.rb, line 147
def render_json_string(response, status: nil)
  render(json: response, status: status)
end
wrap_json_view(view) click to toggle source

Traverse a tree and wrap all String terminals in CompiledJson

# File lib/view_model/controller.rb, line 171
def wrap_json_view(view)
  case view
  when Array
    view.map { |v| wrap_json_view(v) }
  when Hash
    view.transform_values { |v| wrap_json_view(v) }
  when String, Symbol
    CompiledJson.new(view)
  else
    view
  end
end