Class: Roda::RodaPlugins::TypecastParams::Params
- Inherits:
-
Object
- Object
- Roda::RodaPlugins::TypecastParams::Params
- Defined in:
- lib/roda/plugins/typecast_params.rb
Overview
Class handling conversion of submitted parameters to desired types.
Class Method Summary collapse
-
.handle_type(type, &block) ⇒ Object
Handle conversions for the given type using the given block.
-
.nest(obj, nesting) ⇒ Object
Create a new instance with the given object and nesting level.
Instance Method Summary collapse
-
#[](key) ⇒ Object
Return a new Params instance for the given
key. -
#array(type, key, default = nil) ⇒ Object
Convert the value of
keyto an array of values of the giventype. -
#array!(type, key, default = nil) ⇒ Object
Call
arraywith thetype,key, anddefault, but if the return value is nil or any value in the returned array isnil, raise an Error. -
#convert!(keys = nil, opts = OPTS) ⇒ Object
Captures conversions inside the given block, and returns a hash of all conversions, including conversions of subkeys.
-
#convert_each!(opts = OPTS, &block) ⇒ Object
Runs convert! for each key specified by the :keys option.
-
#dig(type, *nest, key) ⇒ Object
Convert values nested under the current obj.
-
#dig!(type, *nest, key) ⇒ Object
Similar to
dig, but raises an Error instead of returningnilif no value is found. -
#fetch(key) ⇒ Object
Return the nested value for key.
-
#initialize(obj) ⇒ Params
constructor
Set the object used for converting.
-
#present?(key) ⇒ Boolean
If key is a String Return whether the key is present in the object,.
Constructor Details
#initialize(obj) ⇒ Params
Set the object used for converting. Conversion methods will convert members of the passed object.
491 492 493 494 495 496 497 498 499 500 501 502 |
# File 'lib/roda/plugins/typecast_params.rb', line 491 def initialize(obj) case @obj = obj when Hash, Array # nothing else if @nesting handle_error(nil, (@obj.nil? ? :missing : :invalid_type), "value of #{param_name(nil)} parameter not an array or hash: #{obj.inspect}", true) else handle_error(nil, :invalid_type, "parameters given not an array or hash: #{obj.inspect}", true) end end end |
Class Method Details
.handle_type(type, &block) ⇒ Object
Handle conversions for the given type using the given block. For a type named foo, this will create the following methods:
-
foo(key, default=nil)
-
foo!(key)
-
convert_foo(value) # private
-
_convert_array_foo(value) # private
This method is used to define all type conversions, even the built in ones. It can be called in subclasses to setup subclass-specific types.
385 386 387 388 389 390 391 392 393 394 395 396 397 398 399 400 401 402 403 404 |
# File 'lib/roda/plugins/typecast_params.rb', line 385 def self.handle_type(type, &block) convert_meth = :"convert_#{type}" define_method(convert_meth, &block) convert_array_meth = :"_convert_array_#{type}" define_method(convert_array_meth) do |v| raise Error, "expected array but received #{v.inspect}" unless v.is_a?(Array) v.map!{|val| send(convert_meth, val)} end private convert_meth, convert_array_meth define_method(type) do |key, default=nil| process_arg(convert_meth, key, default) if require_hash! end define_method(:"#{type}!") do |key| send(type, key, CHECK_NIL) end end |
.nest(obj, nesting) ⇒ Object
Create a new instance with the given object and nesting level. obj should be an array or hash, and nesting should be an array. Designed for internal use, should not be called by external code.
410 411 412 413 414 415 |
# File 'lib/roda/plugins/typecast_params.rb', line 410 def self.nest(obj, nesting) v = allocate v.instance_variable_set(:@nesting, nesting) v.send(:initialize, obj) v end |
Instance Method Details
#[](key) ⇒ Object
Return a new Params instance for the given key. The value of key should be an array if key is an integer, or hash otherwise.
521 522 523 524 525 526 527 528 529 530 531 532 533 534 535 536 537 538 539 540 541 542 543 544 545 546 547 548 549 |
# File 'lib/roda/plugins/typecast_params.rb', line 521 def [](key) @subs ||= {} if sub = @subs[key] return sub end if @obj.is_a?(Array) unless key.is_a?(Integer) handle_error(key, :invalid_type, "invalid use of non-integer key for accessing array: #{key.inspect}", true) end else if key.is_a?(Integer) handle_error(key, :invalid_type, "invalid use of integer key for accessing hash: #{key}", true) end end v = @obj[key] v = yield if v.nil? && block_given? begin sub = self.class.nest(v, Array(@nesting) + [key]) rescue => e handle_error(key, :invalid_type, e, true) end @subs[key] = sub sub.sub_capture(@capture, @symbolize) sub end |
#array(type, key, default = nil) ⇒ Object
Convert the value of key to an array of values of the given type. If default is given, any nil values in the array are replaced with default. If key is an array then this returns an array of arrays, one for each respective value of key. If there is no value for key, nil is returned instead of an array.
635 636 637 638 639 |
# File 'lib/roda/plugins/typecast_params.rb', line 635 def array(type, key, default=nil) meth = :"_convert_array_#{type}" raise ProgrammerError, "no typecast_params type registered for #{type.inspect}" unless respond_to?(meth, true) process_arg(meth, key, default) if require_hash! end |
#array!(type, key, default = nil) ⇒ Object
Call array with the type, key, and default, but if the return value is nil or any value in the returned array is nil, raise an Error.
643 644 645 646 647 648 649 650 651 652 653 654 655 |
# File 'lib/roda/plugins/typecast_params.rb', line 643 def array!(type, key, default=nil) v = array(type, key, default) if key.is_a?(Array) key.zip(v).each do |key, arr| check_array!(key, arr) end else check_array!(key, v) end v end |
#convert!(keys = nil, opts = OPTS) ⇒ Object
Captures conversions inside the given block, and returns a hash of all conversions, including conversions of subkeys. keys should be an array of subkeys to access, or nil to convert the current object. If keys is given as a hash, it is used as the options hash. Options:
- :symbolize
-
Convert any string keys in the resulting hash and for any conversions below
564 565 566 567 568 569 570 571 572 573 574 575 |
# File 'lib/roda/plugins/typecast_params.rb', line 564 def convert!(keys=nil, opts=OPTS) if keys.is_a?(Hash) opts = keys keys = nil end _capture!(:nested_params, opts) do if sub = subkey(Array(keys).dup, true) yield sub end end end |
#convert_each!(opts = OPTS, &block) ⇒ Object
Runs convert! for each key specified by the :keys option. If no :keys option is given and the object is an array, runs convert! for all entries in the array. Raises an Error if the current object is not an array and :keys option is not specified. Passes any options given to #convert!. Options:
- :keys
-
The keys to extract from the object
583 584 585 586 587 588 589 590 591 592 593 594 595 596 597 598 599 600 601 602 603 604 605 606 |
# File 'lib/roda/plugins/typecast_params.rb', line 583 def convert_each!(opts=OPTS, &block) np = !@capture _capture!(nil, opts) do unless keys = opts[:keys] unless @obj.is_a?(Array) handle_error(nil, :invalid_type, "convert_each! called on non-array") next end keys = (0...@obj.length) end keys.map do |i| begin if v = subkey([i], true) yield v v.nested_params if np end rescue => e handle_error(i, :invalid_type, e) end end end end |
#dig(type, *nest, key) ⇒ Object
Convert values nested under the current obj. Traverses the current object using nest, then converts key on that object using type:
tp.dig(:pos_int, 'foo') # tp.pos_int('foo')
tp.dig(:pos_int, 'foo', 'bar') # tp['foo'].pos_int('bar')
tp.dig(:pos_int, 'foo', 'bar', 'baz') # tp['foo']['bar'].pos_int('baz')
Returns nil if any of the values are not present or not the expected type. If the nest path results in an object that is not an array or hash, then raises an Error.
You can use dig to get access to nested arrays by using :array or :array! as the first argument and providing the type in the second argument:
tp.dig(:array, :pos_int, 'foo', 'bar', 'baz') # tp['foo']['bar'].array(:int, 'baz')
622 623 624 |
# File 'lib/roda/plugins/typecast_params.rb', line 622 def dig(type, *nest, key) _dig(false, type, nest, key) end |
#dig!(type, *nest, key) ⇒ Object
Similar to dig, but raises an Error instead of returning nil if no value is found.
627 628 629 |
# File 'lib/roda/plugins/typecast_params.rb', line 627 def dig!(type, *nest, key) _dig(true, type, nest, key) end |
#fetch(key) ⇒ Object
Return the nested value for key. If there is no nested_value for key, calls the block to return the value, or returns nil if there is no block given.
553 554 555 |
# File 'lib/roda/plugins/typecast_params.rb', line 553 def fetch(key) send(:[], key){return(yield if block_given?)} end |
#present?(key) ⇒ Boolean
If key is a String Return whether the key is present in the object,
505 506 507 508 509 510 511 512 513 514 515 516 517 |
# File 'lib/roda/plugins/typecast_params.rb', line 505 def present?(key) case key when String !any(key).nil? when Array key.all? do |k| raise ProgrammerError, "non-String element in array argument passed to present?: #{k.inspect}" unless k.is_a?(String) !any(k).nil? end else raise ProgrammerError, "unexpected argument passed to present?: #{key.inspect}" end end |