Class: Grape::Validations::ParamsScope

Inherits:
Object
  • Object
show all
Includes:
DSL::Parameters, ParamsDocumentation
Defined in:
lib/grape/validations/params_scope.rb

Defined Under Namespace

Classes: Attr

Constant Summary collapse

RESERVED_DOCUMENTATION_KEYWORDS =

There are a number of documentation options on entities that don’t have corresponding validators. Since there is nowhere that enumerates them all, we maintain a list of them here and skip looking up validators for them.

%i[as required param_type is_array format example].freeze
SPECIAL_JSON =
[JSON, Array[JSON]].freeze

Instance Attribute Summary collapse

Instance Method Summary collapse

Methods included from ParamsDocumentation

#document_params

Methods included from DSL::Parameters

#build_with, #declared_param?, #given, #map_params, #optional, #params, #requires, #use, #with

Constructor Details

#initialize(api:, element: nil, element_renamed: nil, parent: nil, optional: false, type: nil, group: nil, dependent_on: nil) { ... } ⇒ ParamsScope

Open up a new ParamsScope, allowing parameter definitions per

Grape::DSL::Params.

Parameters:

  • api (API)

    the API endpoint to modify

  • element (Symbol) (defaults to: nil)

    the element that contains this scope; for this to be relevant, parent must be set

  • element_renamed (Symbol, nil) (defaults to: nil)

    whenever this scope should be renamed and to what, given nil no renaming is done

  • parent (ParamsScope) (defaults to: nil)

    the scope containing this scope

  • optional (Boolean) (defaults to: false)

    whether or not this scope needs to have any parameters set or not

  • type (Class) (defaults to: nil)

    a type meant to govern this scope (deprecated)

  • type (Hash) (defaults to: nil)

    group options for this scope

  • dependent_on (Symbol) (defaults to: nil)

    if present, this scope should only validate if this param is present in the parent scope

Yields:

  • the instance context, open for parameter definitions



66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
# File 'lib/grape/validations/params_scope.rb', line 66

def initialize(api:, element: nil, element_renamed: nil, parent: nil, optional: false, type: nil, group: nil, dependent_on: nil, &block)
  @element          = element
  @element_renamed  = element_renamed
  @parent           = parent
  @api              = api
  @optional         = optional
  @type             = type
  @group            = group
  @dependent_on     = dependent_on
  # Must be an ivar: push_declared_params is dispatched on self during
  # instance_eval, so local variables from initialize are unreachable.
  # configure_declared_params consumes it and clears @declared_params to nil.
  @declared_params = []
  @full_path = build_full_path

  instance_eval(&block) if block

  configure_declared_params
  @nearest_array_ancestor = find_nearest_array_ancestor
  freeze
end

Instance Attribute Details

#full_pathObject (readonly)

Returns the value of attribute full_path.



6
7
8
# File 'lib/grape/validations/params_scope.rb', line 6

def full_path
  @full_path
end

#nearest_array_ancestorObject (readonly)

Returns the value of attribute nearest_array_ancestor.



6
7
8
# File 'lib/grape/validations/params_scope.rb', line 6

def nearest_array_ancestor
  @nearest_array_ancestor
end

#parentObject (readonly)

Returns the value of attribute parent.



6
7
8
# File 'lib/grape/validations/params_scope.rb', line 6

def parent
  @parent
end

#typeObject (readonly)

Returns the value of attribute type.



6
7
8
# File 'lib/grape/validations/params_scope.rb', line 6

def type
  @type
end

Instance Method Details

#attr_meets_dependency?(params) ⇒ Boolean

Returns:

  • (Boolean)


117
118
119
120
121
122
# File 'lib/grape/validations/params_scope.rb', line 117

def attr_meets_dependency?(params)
  return true unless @dependent_on
  return false if @parent.present? && !@parent.attr_meets_dependency?(params)

  meets_hash_dependency?(params)
end

#brackets(val) ⇒ Object



155
156
157
# File 'lib/grape/validations/params_scope.rb', line 155

def brackets(val)
  "[#{val}]" if val
end

#configurationObject



88
89
90
# File 'lib/grape/validations/params_scope.rb', line 88

def configuration
  (@api.configuration.respond_to?(:evaluate) && @api.configuration.evaluate) || @api.configuration
end

#full_name(name, index: nil) ⇒ String

Returns the proper attribute name, with nesting considered.

Returns:

  • (String)

    the proper attribute name, with nesting considered.



139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
# File 'lib/grape/validations/params_scope.rb', line 139

def full_name(name, index: nil)
  tracker = ParamScopeTracker.current
  if nested?
    # Find our containing element's name, and append ours.
    resolved_index = index || tracker&.index_for(self)
    "#{@parent.full_name(@element)}#{brackets(resolved_index)}#{brackets(name)}"
  elsif lateral?
    # Find the name of the element as if it was at the same nesting level
    # as our parent. We need to forward our index upward to achieve this.
    @parent.full_name(name, index: tracker&.index_for(self))
  else
    # We must be the root scope, so no prefix needed.
    name.to_s
  end
end

#lateral?Boolean

A lateral scope is subordinate to its parent, but its keys are at the same level as its parent and thus is not contained within an element.

Returns:

  • (Boolean)

    whether or not this scope is lateral



173
174
175
# File 'lib/grape/validations/params_scope.rb', line 173

def lateral?
  @parent && !@element
end

#meets_dependency?(params, request_params) ⇒ Boolean

Returns:

  • (Boolean)


104
105
106
107
108
109
110
111
112
113
114
115
# File 'lib/grape/validations/params_scope.rb', line 104

def meets_dependency?(params, request_params)
  return true unless @dependent_on
  return false if @parent.present? && !@parent.meets_dependency?(@parent.params(request_params), request_params)

  if params.is_a?(Array)
    filtered = params.flatten.filter { |param| meets_dependency?(param, request_params) }
    ParamScopeTracker.current&.store_qualifying_params(self, filtered)
    return filtered.present?
  end

  meets_hash_dependency?(params)
end

#meets_hash_dependency?(params) ⇒ Boolean

Returns:

  • (Boolean)


124
125
126
127
128
129
130
131
132
133
134
135
136
# File 'lib/grape/validations/params_scope.rb', line 124

def meets_hash_dependency?(params)
  # params might be anything what looks like a hash, so it must implement a `key?` method
  return false unless params.respond_to?(:key?)

  @dependent_on.all? do |dependency|
    if dependency.is_a?(Hash)
      key, callable = dependency.first
      callable.call(params[key])
    else
      params[dependency].present?
    end
  end
end

#nested?Boolean

A nested scope is contained in one of its parent’s elements.

Returns:

  • (Boolean)

    whether or not this scope is nested



166
167
168
# File 'lib/grape/validations/params_scope.rb', line 166

def nested?
  @parent && @element
end

#qualifying_paramsObject



8
9
10
# File 'lib/grape/validations/params_scope.rb', line 8

def qualifying_params
  ParamScopeTracker.current&.qualifying_params(self)
end

#required?Boolean

Returns whether or not this scope needs to be present, or can be blank.

Returns:

  • (Boolean)

    whether or not this scope needs to be present, or can be blank



179
180
181
# File 'lib/grape/validations/params_scope.rb', line 179

def required?
  !@optional
end

#root?Boolean

Returns whether or not this scope is the root-level scope.

Returns:

  • (Boolean)

    whether or not this scope is the root-level scope



160
161
162
# File 'lib/grape/validations/params_scope.rb', line 160

def root?
  !@parent
end

#should_validate?(parameters) ⇒ Boolean

Returns whether or not this entire scope needs to be validated.

Returns:

  • (Boolean)

    whether or not this entire scope needs to be validated



94
95
96
97
98
99
100
101
102
# File 'lib/grape/validations/params_scope.rb', line 94

def should_validate?(parameters)
  scoped_params = params(parameters)

  return false if @optional && (scoped_params.blank? || all_element_blank?(scoped_params))
  return false unless meets_dependency?(scoped_params, parameters)
  return true if @parent.nil?

  @parent.should_validate?(parameters)
end