-
-
Notifications
You must be signed in to change notification settings - Fork 53
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
impl #[dynomite(default)] to gracefully handle sparse data #113
Conversation
let name = &ast.ident; | ||
let vis = &ast.vis; | ||
match ast.data { | ||
Struct(DataStruct { fields, .. }) => match fields { | ||
Fields::Named(named) => { | ||
make_dynomite_item(vis, name, &named.named.into_iter().collect::<Vec<_>>()) | ||
} | ||
_ => panic!("Dynomite Items require named fields"), | ||
fields => Err(syn::Error::new( |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
also took some liberty to improve error ux. this change gives the user a precise location of the source of the problem
@@ -25,7 +25,7 @@ use uuid::Uuid; | |||
pub struct Book { | |||
#[dynomite(partition_key)] | |||
id: Uuid, | |||
#[dynomite(rename = "bookTitle")] | |||
#[dynomite(rename = "bookTitle", default)] |
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
need to test this. not quite working yet
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Doug, this will make the structures very verbose and will need a default implementation for any complex type. Would it better to assume that if a field can be absent it would be defined in the struct as Option and we can just return None?
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Actually, Option has None for default. So my only question here is if we can return None in all cases and avoid using #[dynomite(default)] altogether ...
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
To answer your questions in order
- I'd err on the side of being explicit for two practical reasons
- I don't want the default behavior to hide potential application bugs
- Not all types that could impl Attribute are guaranteed to have Default impls. I could add that type constraint but I don't believe that's helpful in cases where you might want to impl attribute for a type that can't have a Default impl by design. These interfaces should be made to fit the types you have as a design goal.
- procmacros aren't type-aware, only syntax-aware. There's not a clear way in a procmacro to dicern types and Rust intentionally avoids runtime reflection by not providing a convenient runtime reflection api. I don't think it's possible to to do this only for option types and relating to question one: I'd strongly prefer an explicit approach to avoid hiding application bugs. Application developers should know which fields should be present and which might not.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
Third thought I had. It might be useful in a future change to allow for a custom defaulting fn when a field is absent. Default::default()
is just an mvp for a more common case.
Just a status update: I'm doing a bit of refactoring. It's actually not possible as far as I can see today for item fields to have multiple attributes in the way one might expect: comma delimited. I would expect a rename attr arg to play well with default. It doesn't in the example code. I want to cover that case before I call this change good |
This should be good to go. Highlight it's now much simpler to add attrs. |
What did you implement:
Like the title says, when you are dealing with dynamodb data you sometimes need to account for sparse data. This is different than the ddb
NULL
type. This is the case where the field is just not present at all.This change allows users to specify a new field attr for Items
#[dynomite(default)]
which is the mvp of dealing with an absent alternativestd::default::Default::default()
! Users will of course have to ensure their field type has a sensible defaultCloses: #92
How did you verify your change:
update example code
cargo install cargo-expand # <-- best tool ever
cargo expand -p dynomite --example demo
What (if anything) would need to be called out in the CHANGELOG for the next release: