-
Notifications
You must be signed in to change notification settings - Fork 44
Application Structure
So here`s how the app is structured right now.
-
The application stores data in a PostGRE SQL Database
-
There's the models, which are types that represent data in the database, and have associated logic for interacting with that data. This is the
aardwolf-models
crate. -
There's operations. Operations are a higher-level view of database interactions. They take input, do some DB stuff, and provide output. Operations are located in:
aardwolf-types/src/operations
. Operations shouldnt make
dieselqueries directly, it should use abstractions provided by the
aardwolf-models` crate to get things done. Sometimes, this means an operation is only one line long. -
Operations implement a trait called
DbAction
, which is defined inaardwolf-types/src/traits.rs
. This provides a generic interface to an operation. Operations also implement a trait calledWrapped
, but now that Im thinking about it, it might make more sense to include the
Wrappedfunctionality in the
DbActiontrait.
Wrappedprovides a method
wrapthat wraps a
DbActiontype in a
DbActionWrapper` struct for easier generic interaction. -
There's forms. Forms are types that represent data that can come in from the user. There are forms for signing up, logging in, etc. these are located in
aardwolf-types/src/forms
-
Form Validation traits Forms implement a trait called
Validate
.Validate
transforms aForm
into aValidatedForm
, possibly producing aFormError
. Forms also implementWrapped
, which provides a methodwrap
that wraps aValidate
type in aValidateWrapper
struct for easier generic interaction. -
Action Traits
ValidateWrapper
andDbActionWrapper
both implement theAction
trait, so they can each be treated the same way. This is important, because theperform!
macros only work on types that implementAction
.Action
is defined twice. Once inaardwolf-rocket/src/action.rs
and once inaardwolf-actix/src/action.rs
. This is because they act differently for each web framework. -
Templates are defined in
aardwolf-templates/templates
, but you dont interact with them directly from code. In order to use a template, there must be a struct that implements
Renderable(defined in
aardwolf-templates/src/lib.rs) that is associated with that template. typically, that means the struct has a similar name (
SignUpfor
sign_up.rs.html), and it
s definition ofrender
should call that template.Renderable
only needs to be defined for structs related to top-level templates, since those are the only ones that should be rendered directly from a front-end application. Top-level template refers to a template that is rendered directly, and not a template that is embedded inside another template. -
The application is served as a webapp via the
aardwolf-rocket
andaardwolf-actix
crates. We have two that we are developing in parallel because it forces us to make design decisions that result in portable code. Each frontend has a unique paradigm that makes writing generic code very interesting.-
There is minimal developer overhead in the rocket frontend, since database operations with diesel are synchronous, and therefore easy to plug into a synchronous web framework.
-
There is some developer overhead in the actix-web frontend, since actix-web expects things to happen asynchronously. The merging of synchronous and asynchronous styles in the actix-web frontend is facilitated by the
DbActor
, which handles synchronous operations, but has an asynchronous API. We send types that implmentDbAction
to theDbActor
, and it sends back the result of the action. Similar interfaces can be built for other synchronous tasks, if we need to do so.
-