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

Upsert #334

Merged
merged 1 commit into from
Jul 13, 2021
Merged

Upsert #334

merged 1 commit into from
Jul 13, 2021

Conversation

paulcsmith
Copy link
Member

@paulcsmith paulcsmith commented Mar 17, 2020

Closes #298

Needs

  • Document the macro upsert_lookup_columns
  • Document how to use upsert and upsert!
  • Create in luckyframework/website to add section in the guides Document Avram#upsert website#716
  • Extract a #save method that accepts a block so we don't have duplicate code

@jkthorne
Copy link
Contributor

So this does not use on conflict. Is that going to be added in a later PR?

@paulcsmith
Copy link
Member Author

@wontruefree Yep! Ideally it will use on conflict, but that'll require adding new methods to the query builder so figured we can at least get this out there in the meantime, then improve it later

@paulcsmith paulcsmith force-pushed the pcs/298-upsert branch 2 times, most recently from aa5a9c8 to cab822b Compare March 19, 2020 20:14
@confact
Copy link
Contributor

confact commented Mar 24, 2020

@paulcsmith A idea i have for find_or_create is to maybe add posibility to use a block.
then it use the parameters to find it and if not find call the block to add those fields. It makes more sense in my head using that.

as example:

email = "hakan@example.com"
SaveUser.find_or_create(email: email) do |u|
  u.email = email
  u.username = "confact"
  u.role = :user 
  u.name = params["name"]
end

Edit: changed to an more luckilized example instead of ruby on rails

@paulcsmith
Copy link
Member Author

paulcsmith commented Mar 26, 2020

@confact I like that API, but for a couple of reasons it is tricky to get type-safe and to work with param parsing. But I like the idea. I tried a few APIs before and couldn't get something that worked, but I'll think on it and see if we can do something closer to that style.

@stephendolan
Copy link
Member

@jwoertink I've merged in master to this branch and resolved the conflicts/updates necessary. What are the next steps to get this merge-able?

I'm happy to take some guidance and attempt to tackle finishing this one up myself, too!

Copy link
Member

@jwoertink jwoertink left a comment

Choose a reason for hiding this comment

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

@stephendolan Overall this looks good. I left a few suggestions to fix. The only major thing is we don't have the block forms of these methods. So we can either add those in, or roll with this as is and add the block forms as a separate PR. I'm good either way.

src/avram/save_operation.cr Outdated Show resolved Hide resolved
src/avram/save_operation.cr Outdated Show resolved Hide resolved
src/avram/unique_columns.cr Outdated Show resolved Hide resolved
src/avram/unique_columns.cr Outdated Show resolved Hide resolved
@stephendolan stephendolan changed the title [WIP] find_or_create and upsert find_or_create and upsert Apr 23, 2021
@stephendolan stephendolan changed the title find_or_create and upsert find_or_create and upsert Apr 23, 2021
@stephendolan stephendolan changed the title find_or_create and upsert find_or_create and upsert Apr 23, 2021
@stephendolan
Copy link
Member

@jwoertink I opted not to introduce all the block variants in this PR so that we can get it cleaned out of the queue and at least have the basics available for folks in the next release.

If we merge this as-is, I can follow up with an issue to document the need for those additional overloads.

Copy link
Member

@matthewmcgarvey matthewmcgarvey left a comment

Choose a reason for hiding this comment

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

I feel iffy about this. Here's some things going through my mind, they might or might not be worth anything, just what I'm thinking:

  • As I commented, unique_columns is weird to me because the call site provides data that isn't used in the fetch. It feels disjointed
  • It's introducing two methods/macros that have to be used together
  • We are depending on the query object that we generated

Because we separate out queries and operations I'm hesitant to believe this is the best way to go so I looked into Elixir's Ecto ORM. They don't have a find_or_create method or an upsert. Instead, they provide options on their Repo.insert function to handle conflicts.

https://hexdocs.pm/ecto/Ecto.Repo.html#c:insert/2

Can we talk before merging this?

spec/operations/save_operation_spec.cr Outdated Show resolved Hide resolved
@jwoertink
Copy link
Member

Yeah, I'm ok with holding off on this.

@stephendolan
Copy link
Member

stephendolan commented Apr 23, 2021

I'm definitely cool with a different approach, as long as this doesn't sit for another year untouched 😆 .

Having just implemented this manually in two apps, it feels like an area where it'll be easy for end-users of Lucky to make mistakes until we provide the capability.

@confact
Copy link
Contributor

confact commented Apr 25, 2021

Yea, I think it is good to have something like this. I am doing find and check if nil to create now in many places, so it would surely save a lot of code.

But the current flow is confusing to me. I am not sure what it is using to find it and what it will update. Is it some of them or all of them?

If we find a good way to handle that in a good way, it would be good. But I understand the issue @paulcsmith discussed with the parameters and block, so a ruby on a rails-like method might be hard.

Not sure exactly how to fix it. I think it is a good call to wait out and think it through.

@paulcsmith paulcsmith changed the title find_or_create and upsert Upsert Jul 12, 2021
@paulcsmith paulcsmith dismissed jwoertink’s stale review July 12, 2021 15:39

Working on updating this

Copy link
Member

@jwoertink jwoertink left a comment

Choose a reason for hiding this comment

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

This is looking nice! Just a few questions, but I dig the direction.

@@ -57,6 +57,10 @@ private class ParamKeySaveOperation < ValueColumnModel::SaveOperation
param_key :custom_param
end

private class UpsertUserOperation < User::SaveOperation
upsert_lookup_columns :name, :nickname
Copy link
Member

Choose a reason for hiding this comment

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

I like how this reads.

spec/operations/save_operation_spec.cr Show resolved Hide resolved
src/avram/save_operation.cr Outdated Show resolved Hide resolved
src/avram/upsert.cr Show resolved Hide resolved
src/avram/upsert.cr Show resolved Hide resolved
@paulcsmith paulcsmith marked this pull request as draft July 12, 2021 18:03
@paulcsmith paulcsmith marked this pull request as ready for review July 13, 2021 18:39
if operation.save
yield operation, operation.record.not_nil!
else
operation.published_save_failed_event
Copy link
Member Author

Choose a reason for hiding this comment

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

This was moved to SaveOperation#save so we don't need to remember to call it in multiple places

Copy link
Member

@jwoertink jwoertink left a comment

Choose a reason for hiding this comment

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

This is great stuff! Overall, the implementation seems fairly simple which is nice. Just a few small wording suggestions, but if you're cool with it, merge away!

src/avram/upsert.cr Outdated Show resolved Hide resolved
src/avram/upsert.cr Outdated Show resolved Hide resolved
@paulcsmith paulcsmith merged commit 15f6a78 into master Jul 13, 2021
@paulcsmith paulcsmith deleted the pcs/298-upsert branch July 13, 2021 23:14
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

Successfully merging this pull request may close these issues.

Add upsert ability to SaveOperations
6 participants