Skip to content
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

Passing Parameters for Rules #460

Closed
shawnwildermuth opened this issue Jan 30, 2023 · 2 comments
Closed

Passing Parameters for Rules #460

shawnwildermuth opened this issue Jan 30, 2023 · 2 comments

Comments

@shawnwildermuth
Copy link

Please describe why you are requesting a feature

I'd like to be able to pass a parameter to the GenerateXXX() methods so that I can a Rule can use that parameter for initialization

Please provide a code example of what you are trying to achieve

var orderFaker = new Faker<Order>()
  .RuleFor(o => o.OrderId, f => f.IndexFaker)
  .RuleFor(o => o.CustomerId, (f,b,p) => p); //  third parameter to be the passed in value

var custFaker = new Faker<Customer>()
  .RuleFor(c => c.Id, f => f.IndexFaker)  
  .RuleFor(c => c.Name, f => f.Name.FullName())
  .RuleFor(c => c.Orders, f => orderFaker.GenerateWithParam(10, null, f.IndexFaker)); // Passing in the id of the customer to the order faker

Please answer any or all of the questions below

  • Is the feature something that currently cannot be done?

AFAIK

  • What alternatives have you considered?

Post processing the generated data

  • Has the feature been requested in the past?

No.

If the feature request is approved, would you be willing to submit a PR?

Yes

@bchavez
Copy link
Owner

bchavez commented Jan 31, 2023

Hi @shawnwildermuth,

Thank you for posting.

Every Faker<T> internally contains a Faker (non-generic) object; which is used for the f => parameter. The Faker f has an IHasContext interface + .Context property that can be leveraged to flow context. This is a somewhat hidden API, but it's doable with the current release.

Here is one approach (of probably many) shown below:
(Tested with LINQPad 7 and Bogus 34.0.2)

void Main()
{
   var orderFaker = new Faker<Order>()
     .RuleFor(o => o.OrderId, f => f.IndexFaker)
     .RuleFor(o => o.CustomerId, (f,o) => f.FromContext(nameof(o.CustomerId)));

   var custFaker = new Faker<Customer>()
     .RuleFor(c => c.Id, f => f.IndexFaker)
     .RuleFor(c => c.Name, f => f.Name.FullName())
     .RuleFor(c => c.Orders, f => orderFaker.WithContext(nameof(Order.CustomerId), f.IndexFaker).Generate(3));
     
     custFaker.Generate(3).Dump();
}

public static class ExtensionsForIssue460
{
   public static object FromContext(this Faker faker, string key)
   {
      var fakerContext = faker as IHasContext;
      return fakerContext.Context[key];
   }
   
   public static Faker<T> WithContext<T>(this Faker<T> fakerT, string propertyName, object value) where T : class
   {
      var internals = fakerT as IFakerTInternal;
      var faker = internals.FakerHub;
      var fakerContext = faker as IHasContext;
      fakerContext.Context[propertyName] = value;
      return fakerT;
   }
}

public class Order
{
   public int OrderId { get; set; }
   public int CustomerId { get; set; }

}
public class Customer
{
   public int Id { get; set; }
   public string Name { get; set; }
   public List<Order> Orders { get; set; }
}

image

I'm not super convinced yet that introducing an overloaded .GenerateWithParam(...) is exactly the best approach for this kind of context flow. Introducing a new public API like .GenerateWithParam(...) requires passing a very strict and high bar for Bogus; and my gut feeling is that I'm just not there yet for this kind of problem.

Feel free to continue the conversation or close the issue if you find the solution above satisfactory.

Thanks,
Brian Chavez

@shawnwildermuth
Copy link
Author

That's awesome! Thanks, this using Context makes more sense than the overload. Just glad there is a way to do this.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

2 participants