support for iterating array of tuples with more than two values
This commit is contained in:
@@ -7,6 +7,7 @@
|
||||
- Added support for resolving superclass properties for not-NSObject subclasses
|
||||
- The `{% for %}` tag can now iterate over tuples, structures and classes via
|
||||
their stored properties.
|
||||
- Added support for iterating arrays of tuples
|
||||
|
||||
### Bug Fixes
|
||||
|
||||
|
||||
@@ -53,25 +53,26 @@ class ForNode : NodeType {
|
||||
self.where = `where`
|
||||
}
|
||||
|
||||
func push<Result>(value: Any, context: Context, closure: () throws -> (Result)) rethrows -> Result {
|
||||
func push<Result>(value: Any, context: Context, closure: () throws -> (Result)) throws -> Result {
|
||||
if loopVariables.isEmpty {
|
||||
return try context.push() {
|
||||
return try closure()
|
||||
}
|
||||
}
|
||||
|
||||
if let value = value as? (Any, Any) {
|
||||
let first = loopVariables[0]
|
||||
|
||||
if loopVariables.count == 2 {
|
||||
let second = loopVariables[1]
|
||||
|
||||
return try context.push(dictionary: [first: value.0, second: value.1]) {
|
||||
return try closure()
|
||||
let valueMirror = Mirror(reflecting: value)
|
||||
if case .tuple? = valueMirror.displayStyle {
|
||||
if loopVariables.count > Int(valueMirror.children.count) {
|
||||
throw TemplateSyntaxError("Tuple '\(value)' has less values than loop variables")
|
||||
}
|
||||
var variablesContext = [String: Any]()
|
||||
valueMirror.children.prefix(loopVariables.count).enumerated().forEach({ (offset, element) in
|
||||
if loopVariables[offset] != "_" {
|
||||
variablesContext[loopVariables[offset]] = element.value
|
||||
}
|
||||
})
|
||||
|
||||
return try context.push(dictionary: [first: value.0]) {
|
||||
return try context.push(dictionary: variablesContext) {
|
||||
return try closure()
|
||||
}
|
||||
}
|
||||
|
||||
@@ -11,7 +11,8 @@ func testForNode() {
|
||||
"dict": [
|
||||
"one": "I",
|
||||
"two": "II",
|
||||
]
|
||||
],
|
||||
"tuples": [(1, 2, 3), (4, 5, 6)]
|
||||
])
|
||||
|
||||
$0.it("renders the given nodes for each item") {
|
||||
@@ -127,6 +128,53 @@ func testForNode() {
|
||||
try expect(result) == fixture
|
||||
}
|
||||
|
||||
$0.context("given array of tuples") {
|
||||
$0.it("can iterate over all tuple values") {
|
||||
let templateString = "{% for first,second,third in tuples %}" +
|
||||
"{{ first }}, {{ second }}, {{ third }}\n" +
|
||||
"{% endfor %}\n"
|
||||
|
||||
let template = Template(templateString: templateString)
|
||||
let result = try template.render(context)
|
||||
|
||||
let fixture = "1, 2, 3\n4, 5, 6\n\n"
|
||||
try expect(result) == fixture
|
||||
}
|
||||
|
||||
$0.it("can iterate with less number of variables") {
|
||||
let templateString = "{% for first,second in tuples %}" +
|
||||
"{{ first }}, {{ second }}\n" +
|
||||
"{% endfor %}\n"
|
||||
|
||||
let template = Template(templateString: templateString)
|
||||
let result = try template.render(context)
|
||||
|
||||
let fixture = "1, 2\n4, 5\n\n"
|
||||
try expect(result) == fixture
|
||||
}
|
||||
|
||||
$0.it("can use _ to skip variables") {
|
||||
let templateString = "{% for first,_,third in tuples %}" +
|
||||
"{{ first }}, {{ third }}\n" +
|
||||
"{% endfor %}\n"
|
||||
|
||||
let template = Template(templateString: templateString)
|
||||
let result = try template.render(context)
|
||||
|
||||
let fixture = "1, 3\n4, 6\n\n"
|
||||
try expect(result) == fixture
|
||||
}
|
||||
|
||||
$0.it("throws when number of variables is more than number of tuple values") {
|
||||
let templateString = "{% for key,value,smth in dict %}" +
|
||||
"{% endfor %}\n"
|
||||
|
||||
let template = Template(templateString: templateString)
|
||||
try expect(template.render(context)).toThrow()
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$0.it("can iterate over dictionary") {
|
||||
let templateString = "{% for key,value in dict %}" +
|
||||
"{{ key }}: {{ value }}," +
|
||||
|
||||
Reference in New Issue
Block a user