Swift Vapor - configure.swift 中的“无法使用类型为...的参数列表调用 'add'”错误
Swift Vapor - 'Cannot invoke 'add' with an argument list of type...' errors in configure.swift
我正在 YouTube 上学习 Paul Hudson 的电子商务教程。我在 configure.swift
:
中收到以下错误
import FluentSQLite
import Vapor
import Leaf // added
/// Called before your application initializes.
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
// Register providers first
try services.register(FluentSQLiteProvider())
// Register routes to the router
let router = EngineRouter.default()
try routes(router)
services.register(router, as: Router.self)
// Register middleware
var middlewares = MiddlewareConfig() // Create _empty_ middleware config
// middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response
services.register(middlewares)
// Configure a SQLite database
let sqlite = try SQLiteDatabase(storage: .memory)
// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
// Configure migrations
var migrations = MigrationConfig()
migrations.add(model: Todo.self, database: .sqlite)
services.register(migrations)
let leafProvider = LeafProvider() // added
try services.register(leafProvider) // added
config.prefer(LeafRenderer.self, for: ViewRenderer.self)// added
// http://localhost:8080/ already in use so adding new server http://localhost:8080/ below -
let serverConfigure = NIOServerConfig.default(hostname: "0.0.0.0", port: 9090)
services.register(serverConfigure)
let directoryConfig = DirectoryConfig.detect()
services.register(directoryConfig)
try services.register(FluentSQLiteProvider())
var databaseConfig = DatabasesConfig()
let db = try SQLiteDatabase(storage: .file(path: "\(directoryConfig.workDir)pizza.db"))
databaseConfig.add(model: db, database: as .sqlite)
/**
The line just above shows errors -
errror 1 -> Cannot invoke 'add' with an argument list of type '(model:
SQLiteDatabase)'
error 2 -> Expected expression in list of expressions
*/
services.register(databaseConfig)
var migrationConfig = MigrationConfig()
migrationConfig.add(model: pizza.self, database: sqlite)
/**
The line just above shows error -> Cannot invoke 'add' with an argument list of type '(model: pizza.Type, database: SQLiteDatabase)'
*/
services.register(migrationConfig)
}
// configure.swift ends here
我也贴上我的Package.swift代码供参考-
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "vv",
products: [
.library(name: "vv", targets: ["App"]),
],
dependencies: [
// A server-side Swift web framework.
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
// Swift ORM (queries, models, relations, etc) built on SQLite 3.
.package(url: "https://github.com/vapor/fluent-sqlite.git", from: "3.0.0"),
.package(url: "https://github.com/vapor/leaf.git", from: "3.0.0"),
],
targets: [
.target(name: "App", dependencies: ["Leaf", "Vapor","FluentSQLite"]),
.target(name: "Run", dependencies: ["App"]),
.testTarget(name: "AppTests", dependencies: ["App"])
]
)
pizza.swift 文件 -
import Foundation
import Vapor
import FluentSQLite
struct pizza: Encodable, Content, Decodable, SQLiteModel {
var id: Int?
var name: String
var description: String
var price: Int
}
我无法理解以上错误是什么意思!谢谢。
routes.swift 文件 -
import Routing
import Vapor
import FluentSQLite
public func routes(_ router: Router) throws {
router.get { req -> Future <View> in
let Newyorker = Pizza(id: 5, name: "statinisland", description: "impracticaljokers", price: 55)
let Traditional = Pizza(id: 5, name: "rome", description: "pope", price: 55)
return try req.view().render("welcome",["pizza":[Newyorker,Traditional]])
}
router.post(Pizza.self, at: "add") { req, pizza ->
Future<Response> in
return Pizza.save(on:req).map(to:Response.self) {Pizza
in
return req.redirect(to: "/")
}
}
/*Error - Type 'Pizza' has no member 'save'; did you mean 'name'?
Replace 'save' with 'name' */
}
这是对我原来的回答的重写,以解决所有问题:
configure.swift
- 不要定义
MigrationConfig()
和 DatabaseConfig()
的多个实例。
- 将相关任务(例如添加模型)组合在一起将使您的代码更易于调试和维护。
- 您已经添加了
.sqlite
个数据库的两个实例。
- 您在添加
pizza
模型时省略了 .sqlite
中的 .
。
因此,您的 configure.swift 的相关部分变为:
let directoryConfig = DirectoryConfig.detect()
services.register(directoryConfig)
let sqlite = try SQLiteDatabase(storage: .file(path: "\(directoryConfig.workDir)pizza.db"))
// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
var migrations = MigrationConfig()
migrations.add(model: Todo.self, database: .sqlite)
migrations.add(model: Pizza.self, database: .sqlite)
services.register(migrations)
pizza.swift
:
- 我更喜欢使用
final class
而不是 struct
,因为它给你更多的灵活性(例如在你的初始化程序中)。
- 您需要使其符合
Migration
。
因此,最小 Pizza
模型变为:
final class Pizza:SQLiteModel {
var id: Int?
var name: String
var description: String
var price: Int
init(id: Int? = nil, name: String, desc:String, price:Int)
{
self.id = id
self.description = desc
self.name = name
self.price = price
}
}
extension Pizza: Migration { }
为了完整起见,您的 configure.swift 变为:
import FluentSQLite
import Vapor
import Leaf // added
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
// Register providers first
try services.register(FluentSQLiteProvider())
// Register routes to the router
let router = EngineRouter.default()
try routes(router)
services.register(router, as: Router.self)
// Register middleware
var middlewares = MiddlewareConfig() // Create _empty_ middleware config
// middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response
services.register(middlewares)
let directoryConfig = DirectoryConfig.detect()
services.register(directoryConfig)
let sqlite = try SQLiteDatabase(storage: .file(path:"\(directoryConfig.workDir)pizza.db"))
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
var migrations = MigrationConfig()
migrations.add(model: Todo.self, database: .sqlite)
migrations.add(model: Pizza.self, database: .sqlite)
services.register(migrations)
let leafProvider = LeafProvider() // added
try services.register(leafProvider) // added
config.prefer(LeafRenderer.self, for: ViewRenderer.self)// added
let serverConfigure = NIOServerConfig.default(hostname: "0.0.0.0", port: 9090)
services.register(serverConfigure)
}
我正在 YouTube 上学习 Paul Hudson 的电子商务教程。我在 configure.swift
:
import FluentSQLite
import Vapor
import Leaf // added
/// Called before your application initializes.
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
// Register providers first
try services.register(FluentSQLiteProvider())
// Register routes to the router
let router = EngineRouter.default()
try routes(router)
services.register(router, as: Router.self)
// Register middleware
var middlewares = MiddlewareConfig() // Create _empty_ middleware config
// middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response
services.register(middlewares)
// Configure a SQLite database
let sqlite = try SQLiteDatabase(storage: .memory)
// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
// Configure migrations
var migrations = MigrationConfig()
migrations.add(model: Todo.self, database: .sqlite)
services.register(migrations)
let leafProvider = LeafProvider() // added
try services.register(leafProvider) // added
config.prefer(LeafRenderer.self, for: ViewRenderer.self)// added
// http://localhost:8080/ already in use so adding new server http://localhost:8080/ below -
let serverConfigure = NIOServerConfig.default(hostname: "0.0.0.0", port: 9090)
services.register(serverConfigure)
let directoryConfig = DirectoryConfig.detect()
services.register(directoryConfig)
try services.register(FluentSQLiteProvider())
var databaseConfig = DatabasesConfig()
let db = try SQLiteDatabase(storage: .file(path: "\(directoryConfig.workDir)pizza.db"))
databaseConfig.add(model: db, database: as .sqlite)
/**
The line just above shows errors -
errror 1 -> Cannot invoke 'add' with an argument list of type '(model:
SQLiteDatabase)'
error 2 -> Expected expression in list of expressions
*/
services.register(databaseConfig)
var migrationConfig = MigrationConfig()
migrationConfig.add(model: pizza.self, database: sqlite)
/**
The line just above shows error -> Cannot invoke 'add' with an argument list of type '(model: pizza.Type, database: SQLiteDatabase)'
*/
services.register(migrationConfig)
}
// configure.swift ends here
我也贴上我的Package.swift代码供参考-
// swift-tools-version:4.0
import PackageDescription
let package = Package(
name: "vv",
products: [
.library(name: "vv", targets: ["App"]),
],
dependencies: [
// A server-side Swift web framework.
.package(url: "https://github.com/vapor/vapor.git", from: "3.0.0"),
// Swift ORM (queries, models, relations, etc) built on SQLite 3.
.package(url: "https://github.com/vapor/fluent-sqlite.git", from: "3.0.0"),
.package(url: "https://github.com/vapor/leaf.git", from: "3.0.0"),
],
targets: [
.target(name: "App", dependencies: ["Leaf", "Vapor","FluentSQLite"]),
.target(name: "Run", dependencies: ["App"]),
.testTarget(name: "AppTests", dependencies: ["App"])
]
)
pizza.swift 文件 -
import Foundation
import Vapor
import FluentSQLite
struct pizza: Encodable, Content, Decodable, SQLiteModel {
var id: Int?
var name: String
var description: String
var price: Int
}
我无法理解以上错误是什么意思!谢谢。
routes.swift 文件 -
import Routing
import Vapor
import FluentSQLite
public func routes(_ router: Router) throws {
router.get { req -> Future <View> in
let Newyorker = Pizza(id: 5, name: "statinisland", description: "impracticaljokers", price: 55)
let Traditional = Pizza(id: 5, name: "rome", description: "pope", price: 55)
return try req.view().render("welcome",["pizza":[Newyorker,Traditional]])
}
router.post(Pizza.self, at: "add") { req, pizza ->
Future<Response> in
return Pizza.save(on:req).map(to:Response.self) {Pizza
in
return req.redirect(to: "/")
}
}
/*Error - Type 'Pizza' has no member 'save'; did you mean 'name'?
Replace 'save' with 'name' */
}
这是对我原来的回答的重写,以解决所有问题:
configure.swift
- 不要定义
MigrationConfig()
和DatabaseConfig()
的多个实例。 - 将相关任务(例如添加模型)组合在一起将使您的代码更易于调试和维护。
- 您已经添加了
.sqlite
个数据库的两个实例。 - 您在添加
pizza
模型时省略了.sqlite
中的.
。
因此,您的 configure.swift 的相关部分变为:
let directoryConfig = DirectoryConfig.detect()
services.register(directoryConfig)
let sqlite = try SQLiteDatabase(storage: .file(path: "\(directoryConfig.workDir)pizza.db"))
// Register the configured SQLite database to the database config.
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
var migrations = MigrationConfig()
migrations.add(model: Todo.self, database: .sqlite)
migrations.add(model: Pizza.self, database: .sqlite)
services.register(migrations)
pizza.swift
:
- 我更喜欢使用
final class
而不是struct
,因为它给你更多的灵活性(例如在你的初始化程序中)。 - 您需要使其符合
Migration
。
因此,最小 Pizza
模型变为:
final class Pizza:SQLiteModel {
var id: Int?
var name: String
var description: String
var price: Int
init(id: Int? = nil, name: String, desc:String, price:Int)
{
self.id = id
self.description = desc
self.name = name
self.price = price
}
}
extension Pizza: Migration { }
为了完整起见,您的 configure.swift 变为:
import FluentSQLite
import Vapor
import Leaf // added
public func configure(_ config: inout Config, _ env: inout Environment, _ services: inout Services) throws {
// Register providers first
try services.register(FluentSQLiteProvider())
// Register routes to the router
let router = EngineRouter.default()
try routes(router)
services.register(router, as: Router.self)
// Register middleware
var middlewares = MiddlewareConfig() // Create _empty_ middleware config
// middlewares.use(FileMiddleware.self) // Serves files from `Public/` directory
middlewares.use(ErrorMiddleware.self) // Catches errors and converts to HTTP response
services.register(middlewares)
let directoryConfig = DirectoryConfig.detect()
services.register(directoryConfig)
let sqlite = try SQLiteDatabase(storage: .file(path:"\(directoryConfig.workDir)pizza.db"))
var databases = DatabasesConfig()
databases.add(database: sqlite, as: .sqlite)
services.register(databases)
var migrations = MigrationConfig()
migrations.add(model: Todo.self, database: .sqlite)
migrations.add(model: Pizza.self, database: .sqlite)
services.register(migrations)
let leafProvider = LeafProvider() // added
try services.register(leafProvider) // added
config.prefer(LeafRenderer.self, for: ViewRenderer.self)// added
let serverConfigure = NIOServerConfig.default(hostname: "0.0.0.0", port: 9090)
services.register(serverConfigure)
}