class Onsi::Params
Used to handle parsing JSON-API formated params
@example
class PeopleController < ApplicationController include Onsi::Controller def create attributes = Onsi::Param.parse( params, [:first_name, :last_name], [:team] ) render_resource Person.create!(attributes.flatten) end end
Attributes
The attributes for the params.
@return [ActionController::Parameters]
The relationships for the params.
@return [Hash]
Public Class Methods
Create a new Params
instance.
@param attributes [ActionController::Parameters] The attributes
@param relationships [Hash] Flattened relationships hash
@note Should not be created directly. Use .parse or .parse_json
@private
# File lib/onsi/params.rb, line 130 def initialize(attributes, relationships) @attributes = attributes @relationships = relationships end
Parse a JSON-API formatted params object.
@param params [ActionController::Parameters] The parameters to parse.
@param attributes [Array<String, Symbol>] The whitelisted attributes.
@param relationships [Array<String, Symbol>] The whitelisted relationships.
Should be the key for the relationships name.
@return [Params] The new params object.
# File lib/onsi/params.rb, line 74 def parse(params, attributes = [], relationships = []) parser = Onsi::ParamsParser.new(params, attributes, relationships) results = parser.parse! new( results.attributes, results.relationships ) end
Parse a JSON-API formatted JSON object.
@param body [String, read] The parameters to parse.
@param attributes [Array<String, Symbol>] The whitelisted attributes.
@param relationships [Array<String, Symbol>] The whitelisted relationships.
Should be the key for the relationships name.
@return [Onsi::Params] The new params object.
# File lib/onsi/params.rb, line 94 def parse_json(body, attributes = [], relationships = []) content = body.respond_to?(:read) ? body.read : body json = JSON.parse(content) params = ActionController::Parameters.new(json) parse(params, attributes, relationships) end
# File lib/onsi/params.rb, line 101 def safe_fetch(key, id) yield(id) rescue ActiveRecord::RecordNotFound raise RelationshipNotFound.new("Can't find relationship #{key}", key) end
Public Instance Methods
Set a default value for attributes.
This value will only be used if the key is missing from the passed attributes
@param key [String, Symbol] The key to set a default on.
@param value [Any, call] The default value.
If the object responds to call (Lambda) it will be called when parsing attributes
@example
params.default(:missing, -> { :foo }) subject.flatten[:missing] # => :foo
# File lib/onsi/params.rb, line 234 def default(key, value) @attrs_hash = nil defaults[key.to_sym] = value end
Fetch a value from the attributes or return the passed default value
@param key [String, Symbol] The key to fetch.
@param default [Any] The default value if the attribute doesn't exist.
@return [Any]
# File lib/onsi/params.rb, line 151 def fetch(key, default = nil) attrs_hash[key] || default end
Flatten an merge the attributes & relationships into one hash.
@return [Hash] The flattened attributes and relationships
# File lib/onsi/params.rb, line 139 def flatten @flattened ||= attrs_hash.to_h.merge(relationships.to_h).with_indifferent_access end
Make an attributes key required.
@param key [String, Symbol] The key of the attribute to require.
@raise [MissingReqiredAttribute] The value you have required isn't present
@return [Any] The value for the attribute
# File lib/onsi/params.rb, line 163 def require(key) value = attrs_hash[key] if value.nil? raise MissingReqiredAttribute.new("Missing attribute #{key}", key) end value end
# File lib/onsi/params.rb, line 172 def require_path(key_path) value = flatten.dig(*key_path.split('/')) if value.nil? raise MissingReqiredAttribute.new("Missing attribute at key_path #{key_path}", key_path) end value end
Handle finding a relationship's object.
@param key [String, Symbol] The key for the relationship
@raise [RelationshipNotFound] Thrown instead of an `ActiveRecord::RecordNotFound`
This allows the `Onsi::ErrorResponder` to build an appropriate response.
@example
params.safe_fetch(:person) do |id| Person.find(id) end
@return [Any]
# File lib/onsi/params.rb, line 195 def safe_fetch(key, &block) self.class.safe_fetch(key, @relationships[key], &block) end
Perform a transform on the value
Any getter will run the value through the transform block.
@param key [String, Symbol] The key to transform.
@param block [Block] The block to perform the transform.
@note The values are memoized
@example
params.transform(:date) { |date| Time.parse(date) }
@return [Any]
# File lib/onsi/params.rb, line 214 def transform(key, &block) @attrs_hash = nil transforms[key.to_sym] = block end
Private Instance Methods
# File lib/onsi/params.rb, line 249 def attrs_hash @attrs_hash ||= transform_attributes.merge(default_attributes).with_indifferent_access end
# File lib/onsi/params.rb, line 264 def default_attributes raw_attrs = attributes.to_h.symbolize_keys defaults.each_with_object({}) do |(key, value), object| next if raw_attrs.key?(key) if value.respond_to?(:call) object[key] = value.call else object[key] = value end end end
# File lib/onsi/params.rb, line 245 def defaults @defaults ||= {} end
# File lib/onsi/params.rb, line 253 def transform_attributes attributes.to_h.each_with_object({}) do |(key, value), object| transform = transforms[key.to_sym] if transform object[key] = transform.call(value) else object[key] = value end end end
# File lib/onsi/params.rb, line 241 def transforms @transforms ||= {} end