class Praxis::FieldExpander

Attributes

history[R]
stack[R]

Public Class Methods

expand(object, fields = true, displayable_filter = nil) click to toggle source
# File lib/praxis/field_expander.rb, line 5
def self.expand(object, fields = true, displayable_filter = nil)
  # check the displayability of the whole type/attr object at the top as well, not just the inner ones
  if (privs = object.options[:displayable])
    raise 'Attempting to expand fields for a type that uses :displayable, but the system (or at least this controller) does not have a displayable_filter setup.' unless privs && displayable_filter
    return {} unless displayable_filter.call(Array(privs))

  end
  new(displayable_filter: displayable_filter).expand(object, fields)
end
new(displayable_filter: nil) click to toggle source

displayable_filter is a proc that takes a set of strings (representing privileges of sort) and returns true if it should be displayed

# File lib/praxis/field_expander.rb, line 18
def initialize(displayable_filter: nil)
  @stack = Hash.new do |hash, key|
    hash[key] = Set.new
  end
  @history = Hash.new do |hash, key|
    hash[key] = {}
  end
  @displayable_filter = displayable_filter
end

Public Instance Methods

expand(object, fields = true) click to toggle source
# File lib/praxis/field_expander.rb, line 28
def expand(object, fields = true)
  if stack[object].include? fields
    return history[object][fields] if history[object].include? fields

    # We should probably never get here, since we should have a record
    # of the history of an expansion if we're trying to redo it,
    # but we should also be conservative and raise here just in case.
    raise "Circular expansion detected for object #{object.inspect} with fields #{fields.inspect}"
  else
    stack[object] << fields
  end

  result = if object.is_a? Attributor::Attribute
             expand_type(object.type, fields)
           else
             expand_type(object, fields)
           end

  result
ensure
  stack[object].delete fields
end
expand_fields(attributes, fields) { |dumpable, sub_fields| ... } click to toggle source
# File lib/praxis/field_expander.rb, line 51
def expand_fields(attributes, fields)
  raise ArgumentError, 'expand_fields must be given a block' unless block_given?

  unless fields == true
    attributes = attributes.select do |k, _v|
      fields.key?(k)
    end
  end

  attributes.each_with_object({}) do |(name, dumpable), hash|
    # Filter out attributes that are not displayable (if a filter is provided and there is a displayable option)
    if (privs = dumpable.options[:displayable])
      raise "Found field named #{name} using :displayable, but the system (or at least this controller) does not have a displayable_filter setup." unless privs && @displayable_filter
      next unless @displayable_filter.call(Array(privs))

    end

    sub_fields = case fields
                 when true
                   true
                 when Hash
                   fields[name] || true
                 end
    hash[name] = yield(dumpable, sub_fields)
  end
end
expand_type(object, fields = true) click to toggle source
# File lib/praxis/field_expander.rb, line 78
def expand_type(object, fields = true)
  unless object.respond_to?(:attributes)
    return expand_type(object.member_attribute.type, fields) if object.respond_to?(:member_attribute)

    return true
  end

  # just include the full thing if it has no attributes
  return fields if object.attributes.empty?

  # True, expands to the default fieldset for blueprints
  fields = object.default_fieldset if object < Praxis::Blueprint && fields == true

  return history[object][fields] if history[object].include? fields

  history[object][fields] = {}
  result = expand_fields(object.attributes, fields) do |dumpable, sub_fields|
    expand(dumpable.type, sub_fields)
  end
  unless fields == true
    non_matching = fields.keys - object.attributes.keys
    raise "FieldExpansion error: attribute(s) #{non_matching} do not exist in #{object}" unless non_matching.empty?
  end
  history[object][fields].merge!(result)
end