Skip to content
This repository has been archived by the owner on May 25, 2020. It is now read-only.

Commit

Permalink
finished Table structure, start articles
Browse files Browse the repository at this point in the history
  • Loading branch information
avo committed Sep 6, 2017
1 parent 8e4ecee commit 8fad444
Show file tree
Hide file tree
Showing 8 changed files with 135 additions and 18 deletions.
6 changes: 3 additions & 3 deletions readme.md
Original file line number Diff line number Diff line change
@@ -1,14 +1,14 @@
# ![RealWorld Example App](logo.png)

> ### Kotlin-Ktor codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the [RealWorld](https://github.com/gothinkster/realworld) spec and API.
> ### [Kotlin-Ktor](https://github.com/kotlin/ktor) codebase containing real world examples (CRUD, auth, advanced patterns, etc) that adheres to the [RealWorld](https://github.com/gothinkster/realworld) spec and API.

### [Demo](https://github.com/gothinkster/realworld)    [RealWorld](https://github.com/gothinkster/realworld)


This codebase was created to demonstrate a fully fledged fullstack application built with **Kotlin-Ktor** including CRUD operations, authentication, routing, pagination, and more.
This codebase was created to demonstrate a fully fledged fullstack application built with **[Kotlin-Ktor](https://github.com/kotlin/ktor)** including CRUD operations, authentication, routing, pagination, and more.

We've gone to great lengths to adhere to the **Kotlin-Ktor** community styleguides & best practices.
We've gone to great lengths to adhere to the **[Kotlin-Ktor](https://github.com/kotlin/ktor)** community styleguides & best practices.

For more information on how to this works with other frontends/backends, head over to the [RealWorld](https://github.com/gothinkster/realworld) repo.

Expand Down
4 changes: 2 additions & 2 deletions src/main/kotlin/me/avo/realworld/kotlin/ktor/data/Article.kt
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,6 @@ data class Article(
val createdAt: Date,
val updatedAt: Date,
val favorited: Boolean,
val favoritesCount: Int
// TODO author
val favoritesCount: Int,
val author: Profile
)
25 changes: 25 additions & 0 deletions src/main/kotlin/me/avo/realworld/kotlin/ktor/data/ArticleQuery.kt
Original file line number Diff line number Diff line change
@@ -0,0 +1,25 @@
package me.avo.realworld.kotlin.ktor.data

import org.jetbrains.ktor.util.ValuesMap

data class ArticleQuery(
val tag: String?,
val author: String?,
val favoritedBy: String?,
val limit: Int,
val offset: Int
) {

companion object {

fun fromParameter(map: ValuesMap) = ArticleQuery(
tag = map["tag"],
author = map["author"],
favoritedBy = map["favorited"],
limit = map["limit"]?.toInt() ?: 20,
offset = map["offset"]?.toInt() ?: 0
)

}

}
4 changes: 2 additions & 2 deletions src/main/kotlin/me/avo/realworld/kotlin/ktor/data/Comment.kt
Original file line number Diff line number Diff line change
Expand Up @@ -6,6 +6,6 @@ data class Comment(
val id: Int,
val createdAt: Date,
val updatedAt: Date,
val body: String
// TODO Author
val body: String,
val author: Profile
)
Original file line number Diff line number Diff line change
@@ -1,11 +1,12 @@
package me.avo.realworld.kotlin.ktor.persistence

import me.avo.realworld.kotlin.ktor.data.Article
import me.avo.realworld.kotlin.ktor.data.ArticleQuery
import me.avo.realworld.kotlin.ktor.data.Comment

interface ArticleSource {

fun getArticles(): List<Article>
fun getArticles(query: ArticleQuery): List<Article>

fun getFeed(): List<Article>

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,70 @@
package me.avo.realworld.kotlin.ktor.persistence

import me.avo.realworld.kotlin.ktor.data.Article
import me.avo.realworld.kotlin.ktor.data.ArticleQuery
import me.avo.realworld.kotlin.ktor.data.Comment
import org.jetbrains.exposed.sql.Op
import org.jetbrains.exposed.sql.SqlExpressionBuilder
import org.jetbrains.exposed.sql.select
import org.jetbrains.exposed.sql.transactions.transaction

class ArticleSourceImpl : ArticleSource {

override fun getArticles(query: ArticleQuery): List<Article> = transaction {
(Articles leftJoin Tags leftJoin Favorites)
.select { parseQuery(query) }
.orderBy(Articles.createdAt, false)
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

fun parseQuery(query: ArticleQuery): Op<Boolean> = with(SqlExpressionBuilder) {
query.tag?.let { Tags.tag eq it }

TODO()
}

override fun getArticle(slug: String): Article {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun insertArticle(): Article {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun updateArticle(): Article {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun deleteArticle() {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun addComment(comment: Comment): Comment {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun getComments(slug: String): List<Comment> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun deleteComment(slug: String, id: String) {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun favorite(slug: String): Article {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun unfavorite(slug: String): Article {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun getTags(): List<String> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

override fun getFeed(): List<Article> {
TODO("not implemented") //To change body of created functions use File | Settings | File Templates.
}

}
28 changes: 23 additions & 5 deletions src/main/kotlin/me/avo/realworld/kotlin/ktor/persistence/Tables.kt
Original file line number Diff line number Diff line change
Expand Up @@ -2,29 +2,47 @@ package me.avo.realworld.kotlin.ktor.persistence

import org.jetbrains.exposed.sql.Table

val tables = arrayOf(Users, Following)
val tables = arrayOf(Users, Following, Articles, Tags, Comments, Favorites)

object Users : Table("users") {

val id = integer("id").primaryKey().autoIncrement()
val email = varchar("email", 254)
val password = varchar("password", 255)
val username = varchar("name", 50)
val bio = varchar("bio", 255)
val image = varchar("image", 255).nullable()

}


object Following: Table("following") {
object Following : Table("following") {
val sourceId = integer("source_id").primaryKey() references Users.id
val targetId = integer("target_id").primaryKey() references Users.id
}

object Articles : Table("articles") {
val id = integer("id").primaryKey()
val slug = varchar("slug", 255)
val title = varchar("title", 255)
val description = varchar("description", 255)
val body = text("body")
val createdAt = datetime("createdAt")
val updatedAt = datetime("updatedAt")
val authorId = integer("author_id") references Users.id
}

object Tags : Table("tags") {
val articleId = integer("article_id") references Articles.id
val tag = varchar("tag", 255)
}

object Favorites : Table("favorites") {
val userId = integer("user_id") references Users.id
val articleId = integer("article_id") references Articles.id
}

object Comments : Table("comments") {
val id = integer("id").primaryKey()
val createdAt = datetime("createdAt")
val updatedAt = datetime("updatedAt")
val body = text("body")
val authorId = integer("author_id") references Users.id
}
13 changes: 8 additions & 5 deletions src/main/kotlin/me/avo/realworld/kotlin/ktor/server/Routing.kt
Original file line number Diff line number Diff line change
@@ -1,13 +1,11 @@
package me.avo.realworld.kotlin.ktor.server

import me.avo.realworld.kotlin.ktor.auth.LoginHandler
import me.avo.realworld.kotlin.ktor.data.ArticleQuery
import me.avo.realworld.kotlin.ktor.data.LoginCredentials
import me.avo.realworld.kotlin.ktor.data.RegistrationDetails
import me.avo.realworld.kotlin.ktor.data.User
import me.avo.realworld.kotlin.ktor.persistence.ProfileSource
import me.avo.realworld.kotlin.ktor.persistence.ProfileSourceImpl
import me.avo.realworld.kotlin.ktor.persistence.UserSource
import me.avo.realworld.kotlin.ktor.persistence.UserSourceImpl
import me.avo.realworld.kotlin.ktor.persistence.*
import me.avo.realworld.kotlin.ktor.util.user
import org.jetbrains.ktor.application.ApplicationCall
import org.jetbrains.ktor.application.ApplicationCallPipeline
Expand Down Expand Up @@ -83,12 +81,17 @@ fun Routing.setup() = route("api") {
}

route("articles") {
val articleSource: ArticleSource = ArticleSourceImpl()

get {
TODO("Get articles")
val user = optionalLogin()
val query = ArticleQuery.fromParameter(call.parameters)
val articles = articleSource.getArticles(query)
call.respond(articles)
}

get("feed") {
val user = requireLogin()
TODO("Feed Articles")
}

Expand Down

0 comments on commit 8fad444

Please sign in to comment.