Skip to content

Commit

Permalink
return null for first, last, nth on error
Browse files Browse the repository at this point in the history
Instead of empty string, return null value that's considered undefined
(and can be piped to the default filter) if the array is empty for the
filters first, last and nth. For nth, also change the out-of-bounds
value from empty string to null.

Closes #534, and is a breaking change.
  • Loading branch information
sooda committed Jul 22, 2020
1 parent 5dc12af commit 347c28e
Show file tree
Hide file tree
Showing 2 changed files with 11 additions and 11 deletions.
8 changes: 4 additions & 4 deletions docs/content/docs/_index.md
Original file line number Diff line number Diff line change
Expand Up @@ -819,15 +819,15 @@ before `striptags`.

#### first
Returns the first element of an array.
If the array is empty, returns empty string.
If the array is empty, returns null (undefined) that can be chained to the default filter.

#### last
Returns the last element of an array.
If the array is empty, returns empty string.
If the array is empty, returns null (undefined) that can be chained to the default filter.

#### nth
Returns the nth element of an array.§
If the array is empty, returns empty string.
Returns the nth element of an array.
If the array is empty or if the nth is out of bounds, returns null (undefined) that can be chained to the default filter.
It takes a required `n` argument, corresponding to the 0-based index you want to get.

Example: `{{ value | nth(n=2) }}`
Expand Down
14 changes: 7 additions & 7 deletions src/builtins/filters/array.rs
Original file line number Diff line number Diff line change
Expand Up @@ -12,15 +12,15 @@ pub fn nth(value: &Value, args: &HashMap<String, Value>) -> Result<Value> {
let arr = try_get_value!("nth", "value", Vec<Value>, value);

if arr.is_empty() {
return Ok(to_value("").unwrap());
return Ok(Value::Null);
}

let index = match args.get("n") {
Some(val) => try_get_value!("nth", "n", usize, val),
None => return Err(Error::msg("The `nth` filter has to have an `n` argument")),
};

Ok(arr.get(index).unwrap_or(&to_value("").unwrap()).to_owned())
Ok(arr.get(index).map(|x| x.to_owned()).unwrap_or(Value::Null))
}

/// Returns the first value of an array
Expand All @@ -29,7 +29,7 @@ pub fn first(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let mut arr = try_get_value!("first", "value", Vec<Value>, value);

if arr.is_empty() {
Ok(to_value("").unwrap())
Ok(Value::Null)
} else {
Ok(arr.swap_remove(0))
}
Expand All @@ -40,7 +40,7 @@ pub fn first(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
pub fn last(value: &Value, _: &HashMap<String, Value>) -> Result<Value> {
let mut arr = try_get_value!("last", "value", Vec<Value>, value);

Ok(arr.pop().unwrap_or_else(|| to_value("").unwrap()))
Ok(arr.pop().unwrap_or(Value::Null))
}

/// Joins all values in the array by the `sep` argument given
Expand Down Expand Up @@ -319,7 +319,7 @@ mod tests {
args.insert("n".to_string(), to_value(1).unwrap());
let result = nth(&to_value(&v).unwrap(), &args);
assert!(result.is_ok());
assert_eq!(result.unwrap(), to_value("").unwrap());
assert_eq!(result.unwrap(), Value::Null);
}

#[test]
Expand All @@ -335,7 +335,7 @@ mod tests {

let result = first(&to_value(&v).unwrap(), &HashMap::new());
assert!(result.is_ok());
assert_eq!(result.ok().unwrap(), to_value("").unwrap());
assert_eq!(result.ok().unwrap(), Value::Null);
}

#[test]
Expand All @@ -351,7 +351,7 @@ mod tests {

let result = last(&to_value(&v).unwrap(), &HashMap::new());
assert!(result.is_ok());
assert_eq!(result.ok().unwrap(), to_value("").unwrap());
assert_eq!(result.ok().unwrap(), Value::Null);
}

#[test]
Expand Down

0 comments on commit 347c28e

Please sign in to comment.