Skip to content
New issue

Have a question about this project? # for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “#”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? # to your account

[WIP] Adding a new belongs_to association [for factories. #950

Open
wants to merge 1 commit into
base: main
Choose a base branch
from

Conversation

jwoertink
Copy link
Member

Fixes #385

This PR adds in a new belongs_to association macro for Factory that allows you to association another model and build on demand.

class ProductFactory < Avram::Factory
  belongs_to store : StoreFactory

  def initialize
    title "Cool Thing"
    create_store(&.name("Example Store"))
  end
end

# You can use it many different ways

product = ProductFactory.create
product.store.name == "Example Store"

product = ProductFactory.create(&.create_store(&.name("Different Store")))
product.store.name == "Different Store"

store = StoreFactory.create(&.name("Evil Store"))
product = ProductFactory.create &.store(store)
product.store_id == store.id

One weird thing I ran in to is naming order with requires, but I think that's just a Crystal thing...

For example, with a require "./factories/**", doing this will throw a undefined constant PostFactory because in alphabetical order, "PostFactory" comes after "CommentFactory", so the file hasn't been loaded. You'd just need to do an extra require "./post_factory" at the top if that's the case...

class CommentFactory < BaseFactory
  belongs_to post : PostFactory
end

def {{ type_declaration.var }}(%m : {{ type_declaration.type.stringify.gsub(/Factory$/, "").id }})
{{ type_declaration.var }}_id(%m.id)
end
def create_{{ type_declaration.var }}(&blk : {{ type_declaration.type }} ->)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Does this allow calling the method without a block? I'm not sure it does

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Ooo, good call. I'll add that in.

@jwoertink jwoertink changed the title Adding a new belongs_to association for factories. [WIP] Adding a new belongs_to association [for factories. Jun 28, 2023
@jwoertink
Copy link
Member Author

Putting this in WIP... Just ran in to an issue that I'm not sure how to handle yet.. If your Factory has create_thing(&.some_default) set in the initializer, and you want to override that, it's currently not working.

class CommentFactory < Avram::Factory
  belongs_to post : PostFactory

  def initialize
    body("Test Comment")
    create_post(&.title("Test Post"))
  end
end

# the post title will be "Test Post" here...
TempCommentFactory.create(&.create_post(&.title("A new post")))

This is because it chains the before_saves, and runs the first one, then doesn't run the second because the value has already been set.

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

Successfully merging this pull request may close these issues.

Make it easier to set default associations in a Factory
2 participants