Class: Brainstem::PresenterCollection

Inherits:
Object
  • Object
show all
Defined in:
lib/brainstem/presenter_collection.rb

Instance Attribute Summary collapse

Instance Method Summary collapse

Instance Attribute Details

#default_max_filter_and_search_pageObject

Returns the value of attribute default_max_filter_and_search_page.



15
16
17
# File 'lib/brainstem/presenter_collection.rb', line 15

def default_max_filter_and_search_page
  @default_max_filter_and_search_page
end

#default_max_per_pageInteger

Returns The maximum number of objects that can be requested in a single presented hash.

Returns:

  • (Integer)

    The maximum number of objects that can be requested in a single presented hash.



9
10
11
# File 'lib/brainstem/presenter_collection.rb', line 9

def default_max_per_page
  @default_max_per_page
end

#default_per_pageInteger

Returns The default number of objects that will be returned in the presented hash.

Returns:

  • (Integer)

    The default number of objects that will be returned in the presented hash.



13
14
15
# File 'lib/brainstem/presenter_collection.rb', line 13

def default_per_page
  @default_per_page
end

Instance Method Details

#add_presenter_class(presenter_class, *klasses) ⇒ Object

Parameters:

  • presenter_class (String, Class)

    The presenter class that knows how to present all of the classes given in klasses.

  • klasses (*Class)

    One or more classes that can be presented by presenter_class.



111
112
113
114
115
# File 'lib/brainstem/presenter_collection.rb', line 111

def add_presenter_class(presenter_class, *klasses)
  klasses.each do |klass|
    presenters[klass.to_s] = presenter_class
  end
end

#brainstem_key_for!(klass) ⇒ Object

Raises:

  • (ArgumentError)


128
129
130
131
132
# File 'lib/brainstem/presenter_collection.rb', line 128

def brainstem_key_for!(klass)
  presenter = presenters[klass.to_s]
  raise(ArgumentError, "Unable to find a presenter for class #{klass}") unless presenter
  presenter.configuration[:brainstem_key] || klass.table_name
end

#for(klass) ⇒ Brainstem::Presenter?

Returns A new instance of the Presenter that knows how to present the class klass, or nil if there isn’t one.

Returns:

  • (Brainstem::Presenter, nil)

    A new instance of the Presenter that knows how to present the class klass, or nil if there isn’t one.



118
119
120
# File 'lib/brainstem/presenter_collection.rb', line 118

def for(klass)
  presenters[klass.to_s].try(:new)
end

#for!(klass) ⇒ Brainstem::Presenter

Returns A new instance of the Presenter that knows how to present the class klass.

Returns:

  • (Brainstem::Presenter)

    A new instance of the Presenter that knows how to present the class klass.

Raises:

  • (ArgumentError)

    if there is no known Presenter for klass.



124
125
126
# File 'lib/brainstem/presenter_collection.rb', line 124

def for!(klass)
  self.for(klass) || raise(ArgumentError, "Unable to find a presenter for class #{klass}")
end

#presentersHash

Returns The presenters this collection knows about, keyed on the names of the classes that can be presented.

Returns:

  • (Hash)

    The presenters this collection knows about, keyed on the names of the classes that can be presented.



105
106
107
# File 'lib/brainstem/presenter_collection.rb', line 105

def presenters
  @presenters ||= {}
end

#presenting(name, options = {}) { ... } ⇒ Hash

The main presentation method, converting a model name and an optional scope into a hash structure, ready to be converted into JSON. If searching, Brainstem filtering, only, pagination, and ordering are skipped and should be implemented with your search solution. All request options are passed to the search block for your convenience.

Parameters:

  • name (Class, String)

    Either the ActiveRecord Class itself, or its pluralized table name as a string.

  • options (Hash) (defaults to: {})

    The options that will be applied as the objects are converted.

Options Hash (options):

  • :params (Hash)

    The params hash included in a request for the presented object.

  • :model (ActiveRecord::Base)

    The model that is being presented (if different from name).

  • :max_per_page (Integer)

    The maximum number of items that can be requested by params[:per_page].

  • :per_page (Integer)

    The number of items that will be returned if params[:per_page] is not set.

  • :apply_default_filters (Boolean)

    Determine if Presenter’s filter defaults should be applied. On by default.

  • :primary_presenter (Brainstem::Presenter)

    The Presenter to use for filters and sorts. If unspecified, the :model or name will be used to find an appropriate Presenter.

Yields:

  • Must return a scope on the model name, which will then be presented.

Returns:

  • (Hash)

    A hash of arrays of hashes. Top-level hash keys are pluralized model names, with values of arrays containing one hash per object that was found by the given given options.



37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
# File 'lib/brainstem/presenter_collection.rb', line 37

def presenting(name, options = {}, &block)
  options[:params] = HashWithIndifferentAccess.new(options[:params] || {})
  check_for_old_options!(options)
  set_default_filters_option!(options)
  presented_class = (options[:model] || name)
  presented_class = presented_class.classify.constantize if presented_class.is_a?(String)
  scope = presented_class.instance_eval(&block)
  count = 0

  # grab the presenter that knows about filters and sorting etc.
  options[:primary_presenter] ||= for!(presented_class)

  # table name will be used to query the database for the filtered data
  options[:table_name] = presented_class.table_name

  options[:default_per_page] = default_per_page
  options[:default_max_per_page] = default_max_per_page
  options[:default_max_filter_and_search_page] = default_max_filter_and_search_page

  primary_models, count = strategy(options, scope).execute(scope)

  # Determine if an exception should be raised on an empty result set.
  if options[:raise_on_empty] && primary_models.empty?
    raise options[:empty_error_class] || ActiveRecord::RecordNotFound
  end

  structure_response(presented_class, primary_models, count, options)
end

#structure_response(presented_class, primary_models, count, options) ⇒ Object



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
# File 'lib/brainstem/presenter_collection.rb', line 66

def structure_response(presented_class, primary_models, count, options)
  # key these models will use in the struct that is output
  brainstem_key = brainstem_key_for!(presented_class)

  # filter the incoming :includes list by those available from this Presenter in the current context
  selected_associations = filter_includes(options)

  optional_fields = filter_optional_fields(options)

  struct = { 'count' => count, brainstem_key => {}, 'results' => [] }

  # Build top-level keys for all requested associations.
  selected_associations.each do |association|
    struct[brainstem_key_for!(association.target_class)] ||= {} unless association.polymorphic?
  end

  if primary_models.length > 0
    associated_models = {}
    presented_primary_models = options[:primary_presenter].group_present(primary_models,
                                                                         selected_associations.map(&:name),
                                                                         optional_fields: optional_fields,
                                                                         load_associations_into: associated_models)

    struct[brainstem_key] = presented_primary_models.each.with_object({}) { |model, obj| obj[model['id']] = model }
    struct['results'] = presented_primary_models.map { |model| { 'key' => brainstem_key, 'id' => model['id'] } }

    associated_models.each do |association_brainstem_key, associated_models_hash|
      presenter = for!(associated_models_hash.values.first.class)
      struct[association_brainstem_key] ||= {}
      presenter.group_present(associated_models_hash.values).each do |model|
        struct[association_brainstem_key][model['id']] ||= model
      end
    end
  end

  struct
end

#validate!Object

Raises:

  • (StandardError)

    if any presenter in this collection is invalid.



135
136
137
138
139
140
141
142
143
144
# File 'lib/brainstem/presenter_collection.rb', line 135

def validate!
  errors = []
  presenters.each do |name, klass|
    validator = Brainstem::PresenterValidator.new(klass)
    unless validator.valid?
      errors += validator.errors.full_messages.map { |error| "#{name}: #{error}" }
    end
  end
  raise "PresenterCollection invalid:\n - #{errors.join("\n - ")}" if errors.length > 0
end