Server Side Swift with Vapor - Part 22: Challenge: | Ray Wenderlich

Put all of your Leaf skills to the test and create your own pages.


This is a companion discussion topic for the original entry at https://www.raywenderlich.com/4493-server-side-swift-with-vapor/lessons/22

Hi Tim,
I could follow along this challenge, but in the end, I encountered an issue.

My page “index” works fine, as do the pages “All Users” and “All Categories”.
However, after I added categories, the detail page for an acronym seems broken now.
The page “http://localhost:8080/acronyms/1” returns a blank page with the error message “Oops: This parent relationship could not be resolved”.

I double-checked that my acronym.leaf page was identical to yours, as well as the files in my Xcode project.
Also, the REST Apis work fine in Rested too.

Would you have an idea of what went wrong, or what to look for to debug this issue ?

Thanks
Frederic

@freddyf it sounds like your database has gotten messed up. That error message usually happens when there is no ID in the table and it is looking for one for the parent. Try resetting the database and trying again. (Although the fact the RESTed works is confusing).

After stopping the app in Xcode, run:

docker stop mysql
docker rm mysql
docker run --name mysql -e MYSQL_USER=til -e MYSQL_PASSWORD=password -e MYSQL_DATABASE=vapor -p 3306:3306 -d mysql/mysql-server

Then build and run your application again and see if that fixes it.

Nope, does not work.

I get this error in Xcode too, by the way:

[ ERROR ] Fluent.FluentError.parent-not-found: This parent relationship could not be resolved (Parent.swift:38)

@freddyf hmm can you show me your Acronym.swift and route handler code?

Archive.zip (2.6 KB)

Here they are!
Thaks for your help!

Also, a lot of weird things are happening:

  • I can’t load the logo.png file (lesson 21)
  • I created the allCategories.leaf and category.leaf templates but the category template is not found by the web inspector (as a consequence, the table is not styles using the css)
  • I can’t have the “create acronym” nav item appear (lesson 23)

Should I delete the cache in safari maybe ?

@freddyf something is definitely up! The code looks fine as well. First try start from scratch with the DB and update all of your dependencies. Reset the Docker container following the code above. Then run swift package update && vapor xcode -y to get the latest dependencies. The try building again.

Can you create acronyms successfully?

Ah, no, I think I found it :slight_smile:
The menu showing in Atom was from the materials downloaded form the course, and not the ones in the project !!

1 Like

Haha I had lots of run when creating the course, had about 5 different versions open, very confusing!

Yes, and I am far from being an HTML expert !

OK, so I solved these issues by using the correct .leaf files:

  • I created the allCategories.leaf and category.leaf templates but the category template is not found by the web inspector (as a consequence, the table is not styles using the css)
  • I can’t have the “create acronym” nav item appear (lesson 23)

For the logo, it’s still not loading. Even when I remove the “class=…”. I guess there may be an issue with the FileMiddleware (I’m using the same beta since I started the course, so maybe there is a newer version).

And for the “Oops: This parent relationship could not be resolved” message, I reverted to the previous version of acronymHandler:
func acronymHandler(_ req: Request) throws -> Future {
return try req.parameter(Acronym.self).flatMap(to: View.self) { acronym in
return acronym.creator.get(on: req).flatMap(to: View.self) { creator in
let context = AcronymContext(title: acronym.long, acronym: acronym, creator: creator)
return try req.leaf().render(“acronym”, context)
}
}
}

This works :

return acronym.creator.get(on: req).flatMap(to: View.self) { creator in
let context = AcronymContext(title: acronym.long, acronym: acronym, creator: creator)

This does not work:

return try flatMap(to: View.self, acronym.creator.get(on: req), acronym.categories.query(on: req).all()) { creator, categories in
let context = AcronymContext(title: acronym.long, acronym: acronym, creator: creator, categories: categories.isEmpty ? nil : categories)

Again, is there a newer beta that I should use?
How do you update vapor?

Thanks!
Fred

@freddyf I have another theory - try the following code:

func acronymHandler(_ req: Request) throws -> Future<View> {
  return try req.parameter(Acronym.self).flatMap(to: View.self) { acronym in
    return acronym.creator.get(on: req).flatMap(to: View.self) { creator in
      return try acronym.categories.query(on: req).all().flatMap(to: View.self) { categories in
        let context = AcronymContext(title: acronym.long, acronym: acronym, creator: creator, categories: categories.isEmpty ? nil : categories)
        return try req.leaf().render("acronym", context)
      }
    }
  }
}

There is most likely a newer beta. In terminal try:

vapor update

That should update it for you

Great !
So updating vapor fixed the issue with the image.
And your alternative code fixed the parent relationship issue!

Everything is fine now!
Thanks a lot!

1 Like

@freddyf Awesome! That’s a known bug that should hopefully be fixed soon!

Honestly, this course is one of the best I’ve ever watched!
I learned so much on subjects I previously didn’t dare to tackle.
A course like this completely justifies my video subscription to the site.

Very nice job, Tim!

Cheers

PS: and since I ordered the book, the fun has just begun :-]

1 Like

@freddyf thanks for the feedback, really appreciate it! Hopefully we can get the early access chapters out soon so the fun keeps going!

Well I was cruising along with the challenge, got everything working myself! Was very impressed, then I tried changing my code for acronymHandler to the simpler (less nested) version you had. Well, same issue as @freddyf, parent relationship issue. So I reverted back to my code:

func acronymHandler(_ req: Request) throws -> Future<View> {
return try req.parameter(Acronym.self).flatMap(to: View.self) { acronym in
    return try acronym.categories.query(on: req).all().flatMap(to: View.self) { category in
        return acronym.creator.get(on: req).flatMap(to: View.self) { creator in
            let context = AcronymContext(title: acronym.long, acronym: acronym, creator: creator, categories: category)
            return try req.leaf().render("acronym", context)
        }
    }
}
} // acronymHandler

Notice that my nesting is a bit different than yours, I initially had your setup and couldn’t get it to compile, but changing the nesting to have the creator last is the only thing that would work for me.

And thanks for the update advice, couldn’t figure out why the logo wasn’t displaying either until I updated and magically it started working!

JT

@jtrimble hmm interesting! What error were you getting when you tried to do it the way I suggested above?

Oops: This parent relationship could not be resolved