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
Builder + Figment #317
Comments
The ask is a bit different from some previously addressed issues in that we are leveraging the builder still as the primary way to construct the object; however, we are instead constructing a partial which provides overrides and the merging behavior is taken care of by figment. |
Not at this time;
Happily, though I don't know how much you need to alter the core to make this happen. Would the following work? #[derive(Builder, FigmentFromBuilder)]
pub struct Config {
pub path: String,
pub log_level: String,
pub runtime: RuntimeConfig,
}
// Generated builder...
pub struct ConfigBuilder {
// elided
}
impl ConfigBuilder {
// setters
}
// Generated by FigmentFromBuilder
impl<'a> From<&'a ConfigBuilder> for Figment {
fn from(v: &'a ConfigBuilder) -> Self {
let mut figment = Figment::new();
// generate this for each field
if let Some(val) = v.path.cloned() {
figment.join(("path", val));
}
}
} Would something like that work for your use-case? Note that there are a number of ways to possibly improve/extend this:
|
Thanks @TedDriggs very helpful. I think the only issue is that within the current builder pattern, the |
I'm not understanding this piece. Referring back to this example from the original post: let config = Config::figment()
.path("/path/to/my/data")
.runtime(RuntimeConfig::figment()
.enable_overlap(Some(true))
.build()?)
.build()?; Based on how struct ConfigFigmentBuilder {
path: Option<String>,
log_level: Option<String>,
runtime: Option<RuntimeConfig>,
}
impl ConfigFigmentBuilder {
pub fn path(&mut self, path: String) -> &mut Self {
self.path = Some(path);
self
}
pub fn log_level(&mut self, log_level: String) -> &mut Self {
self.log_level = Some(log_level);
self
}
pub fn runtime(&mut self, runtime: RuntimeConfig) -> &mut Self {
self.runtime = Some(runtime);
self
}
} That requires finishing the
Based on this line, I think the original example was trying to show was passing a partial of let config = Config::figment()
.path("/path/to/my/data")
.runtime(RuntimeConfig::figment()
.enable_overlap(Some(true)))
.build()?; I'm not too familiar with
If my adjustment to the desired calling code is correct, the next task is figuring out what type the |
I'd be curious what your thoughts would be to support a "builder" being a
figment::Provider
?Why would we want to do this? The thought here is that we have some configuration that is locally discoverable by local files or environment variables; however, in our code, we want to both discover those local configuration, but then at the point at which we apply the configuration have some last minute developer override.
The natural way for that developer override is the builder pattern, but in this case, we are not building the entire config, but rather providing some sets of overrides to apply on top of the discovered local configuration.
This would be difficult to do manually and difficult to maintain a forked version of this project; however, with the infrastructure in this project, I think the implementation of a
FigmentBuilder
would be rather trivial; however, I defer to the authors and their guidance.An interface might be the creation of a
FigmentBuilder
for use instead of aBuilder
.The resulting object would be a
Figment
rather than a concrete object.Take for example
What this would do is for any value set by the FigmentBuilder, it would set a "key path" for the global profile,
Serialized::global()
.With the code above:
The
Config::build_private
would ultimately produce a figment with two key paths set:("path", "/path/to/my/data")
("runtime.enable_overlap", true)
To the authors, I have two questions:
The text was updated successfully, but these errors were encountered: