Class: Jbuilder::Schema::Template

Inherits:
JbuilderTemplate
  • Object
show all
Defined in:
lib/jbuilder/schema/template.rb

Defined Under Namespace

Classes: Configuration, Handler, TargetWrapper

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize(context, json: nil, **options) ⇒ Template

Returns a new instance of Template.



69
70
71
72
73
74
75
# File 'lib/jbuilder/schema/template.rb', line 69

def initialize(context, json: nil, **options)
  @json = json
  @configuration = Configuration.new(**options)
  super(context)
  @ignore_nil = false
  @within_block = false
end

Dynamic Method Handling

This class handles dynamic methods through the method_missing method

#method_missingObject

TODO: Remove once Jbuilder passes keyword arguments along to ‘set!` in its `method_missing`.



125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
# File 'lib/jbuilder/schema/template.rb', line 125

def set!(key, value = BLANK, *args, schema: nil, **options, &block)
  old_configuration, @configuration = @configuration, Configuration.build(**schema) if schema&.dig(:object)
  _required << key if schema&.delete(:required) == true
  @within_block = _within_block?(&block)

  _with_schema_overrides(key => schema) do
    keys = args.presence || _extract_possible_keys(value)

    # Detect `json.articles user.articles` to override Jbuilder's logic, which wouldn't hit `array!` and set a `type: :array, items: {"$ref": "#/components/schemas/article"}` ref.
    if block.nil? && keys.blank? && _is_collection?(value) && (value.empty? || value.all? { _is_active_model?(_1) })
      _set_value(key, _scope { _set_ref(key.to_s.singularize, array: true) })
    elsif _partial_options?(options)
      _set_value(key, _scope { _set_ref(options[:as].to_s, array: _is_collection?(value)) })
    else
      super(key, value, *keys, **options, &block)
    end
  end
ensure
  @configuration = old_configuration if old_configuration
  @within_block = false
end

Class Method Details

.build(view_context, local_assigns) ⇒ Object



19
20
21
22
23
24
25
# File 'lib/jbuilder/schema/template.rb', line 19

def self.build(view_context, local_assigns)
  if (options = local_assigns[:__jbuilder_schema_options])
    new(view_context, **options)
  else
    ::JbuilderTemplate.new(view_context)
  end
end

Instance Method Details

#array!(collection = [], *args, schema: nil, **options, &block) ⇒ Object



127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
# File 'lib/jbuilder/schema/template.rb', line 127

def array!(collection = [], *args, schema: nil, **options, &block)
  if _partial_options?(options)
    partial!(collection: collection, **options)
  else
    @within_block = _within_block?(&block)

    _with_schema_overrides(schema) do
      # TODO: Find a better solution
      # Here we basically remove allOf key from items, because it's redundant, although valid.
      # Better would be not to set it if it's not needed, but I couldn't figure how,
      # as we have array of separate object partials hare, so each one of them would legally have allOf key.
      items = _scope { super(collection, *args, &block) }
      if items.is_a?(::Hash)
        items = items[:allOf].first if items.key?(:allOf)
        items = _object(items, _required!(items.keys)) unless items.key?(:$ref) || items.key?(:object)
      end
      _attributes.merge! type: :array, items: items
    end
  end
ensure
  @within_block = false
end

#cache!(key = nil, **options) ⇒ Object



176
177
178
# File 'lib/jbuilder/schema/template.rb', line 176

def cache!(key = nil, **options)
  yield # TODO: Our schema generation breaks Jbuilder's fragment caching.
end

#extract!(object, *attributes, schema: nil) ⇒ Object



150
151
152
# File 'lib/jbuilder/schema/template.rb', line 150

def extract!(object, *attributes, schema: nil)
  _with_schema_overrides(schema) { super(object, *attributes) }
end

#merge!(object) ⇒ Object



171
172
173
174
# File 'lib/jbuilder/schema/template.rb', line 171

def merge!(object)
  object = object.to_h { [_1, _schema(_1, _2)] } if object.is_a?(::Hash)
  super
end

#partial!(model = nil, *args, partial: nil, collection: nil, **options) ⇒ Object



154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
# File 'lib/jbuilder/schema/template.rb', line 154

def partial!(model = nil, *args, partial: nil, collection: nil, **options)
  if args.none? && _is_active_model?(model)
    # TODO: Find where it is being used
    _render_active_model_partial model
  else
    local = options.except(:partial, :as, :collection, :cached, :schema).first
    as = options[:as] || ((local.is_a?(::Array) && local.size == 2 && local.first.is_a?(::Symbol) && local.last.is_a?(::Object)) ? local.first.to_s : nil)

    if @within_block || collection.present?
      _set_ref(as&.to_s || partial || model, array: collection&.any?)
    else
      json = ::Jbuilder::Schema.renderer.original_render partial: model || partial, locals: options
      json.each { |key, value| set!(key, value) }
    end
  end
end

#schema!Object



95
96
97
98
99
100
101
# File 'lib/jbuilder/schema/template.rb', line 95

def schema!
  if [@attributes, *@attributes.first].select { |a| a.is_a?(::Hash) && a[:type] == :array && a.key?(:items) }.any?
    @attributes
  else
    _object(@attributes, _required!(@attributes.keys))
  end.merge(example: @json).compact
end

#set!(key, value = BLANK, *args, schema: nil, **options, &block) ⇒ Object Also known as: method_missing



103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
# File 'lib/jbuilder/schema/template.rb', line 103

def set!(key, value = BLANK, *args, schema: nil, **options, &block)
  old_configuration, @configuration = @configuration, Configuration.build(**schema) if schema&.dig(:object)
  _required << key if schema&.delete(:required) == true
  @within_block = _within_block?(&block)

  _with_schema_overrides(key => schema) do
    keys = args.presence || _extract_possible_keys(value)

    # Detect `json.articles user.articles` to override Jbuilder's logic, which wouldn't hit `array!` and set a `type: :array, items: {"$ref": "#/components/schemas/article"}` ref.
    if block.nil? && keys.blank? && _is_collection?(value) && (value.empty? || value.all? { _is_active_model?(_1) })
      _set_value(key, _scope { _set_ref(key.to_s.singularize, array: true) })
    elsif _partial_options?(options)
      _set_value(key, _scope { _set_ref(options[:as].to_s, array: _is_collection?(value)) })
    else
      super(key, value, *keys, **options, &block)
    end
  end
ensure
  @configuration = old_configuration if old_configuration
  @within_block = false
end

#target!Object



91
92
93
# File 'lib/jbuilder/schema/template.rb', line 91

def target!
  TargetWrapper.new(schema!)
end