Class: Shreddies::Json

Inherits:
Object
  • Object
show all
Defined in:
lib/shreddies/json.rb

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(subject, opts = {}) ⇒ Json

Returns a new instance of Json.



49
50
51
52
53
54
# File 'lib/shreddies/json.rb', line 49

def initialize(subject, opts = {})
  @subject = subject.is_a?(Hash) ? OpenStruct.new(subject) : subject
  @options = { transform_keys: true }.merge(opts).with_indifferent_access

  extend_with_modules
end

Instance Attribute Details

#optionsObject (readonly)

Returns the value of attribute options.



47
48
49
# File 'lib/shreddies/json.rb', line 47

def options
  @options
end

#subjectObject (readonly)

Returns the value of attribute subject.



47
48
49
# File 'lib/shreddies/json.rb', line 47

def subject
  @subject
end

Class Method Details

.delegate(*methods, to: :subject, prefix: nil, allow_nil: nil, private: nil) ⇒ Object

Monkey patches Rails Module#delegate so that the ‘:to` argument defaults to `:subject`.



43
44
45
# File 'lib/shreddies/json.rb', line 43

def self.delegate(*methods, to: :subject, prefix: nil, allow_nil: nil, private: nil)
  super(*methods, to: to, prefix: prefix, allow_nil: allow_nil, private: private)
end

.render(subject, options = {}) ⇒ Object Also known as: render_as_json

Render a subject as json, where ‘subject` is a single object (usually a Rails model), or an array/collection of objects.

If subject is an array/collection then it will look for a ‘Collection` module prepend it to the `module` option.

A Hash of options can be given as the second argument:

- index_by - Key the returned array by the value, transforming it from an array to a hash.
- module   - A Symbol or String of a local module to include. Or an array of several
             modules, where each will be mixed in in order. Use this to mix in groups of
             attributes. Eg. `ArticleSerializer.render(data, module: :WithBody)`.


18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
# File 'lib/shreddies/json.rb', line 18

def render(subject, options = {})
  index_by = options.delete(:index_by)

  if subject.is_a?(Array) || subject.is_a?(ActiveRecord::Relation)
    collection_options = options.merge(from_collection: true)

    if index_by
      mapped = {}
      subject.each do |x|
        mapped[x[index_by]] = new(x, collection_options)
      end
    else
      mapped = subject.map { |x| new(x, collection_options) }
    end

    mapped.as_json
  else
    new(subject, options).as_json
  end
end

Instance Method Details

#as_jsonObject

Travel through the ancestors that are serializers (class name ends with “Serializer”), and call all public instance methods, returning a hash.



58
59
60
61
62
63
64
65
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
# File 'lib/shreddies/json.rb', line 58

def as_json
  output = {}.with_indifferent_access
  methods = Set.new(public_methods(false))

  self.class.ancestors.each do |ancestor|
    if ancestor.to_s.end_with?('Serializer')
      methods.merge ancestor.public_instance_methods(false)
    end
  end

  # Filter out methods using the `only` or `except` options.
  if @options[:only]
    @options[:only] = Array(@options[:only])
    methods = methods.select { |x| @options[:only].include? x }
  elsif @options[:except]
    methods = methods.excluding(@options[:except])
  end

  methods.map do |attr|
    res = public_send(attr)
    if res.is_a?(ActiveRecord::Relation) || res.is_a?(ActiveRecord::Base)
      res = res.as_json(transform_keys: @options[:transform_keys])
    end

    output[attr] = res
  end

  output = before_render(output)

  return output unless @options[:transform_keys]

  output.deep_transform_keys { |key| key.to_s.camelize :lower }
end