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

Turn embed into a behaviour #201

Merged
merged 8 commits into from
Jan 4, 2021
Merged

Conversation

Awlexus
Copy link
Contributor

@Awlexus Awlexus commented Nov 25, 2020

Basic implementation. If this approach is acceptable I'll add documentation about the usage, before merging.

Copy link
Owner

@Kraigie Kraigie left a comment

Choose a reason for hiding this comment

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

Thanks for the PR! I definitely don't hate this idea and it doesn't seem like it'd cause any harm if it were to be added. Additionally there must be a use case if you're suggesting adding this capability. However, I do have some feedback about it!

I'll be the first to admit I haven't looked closely at behaviors in the past or how they're implemented, so feel free to correct me if I'm wrong on anything. To me it feels like this implementation is too closely coupled to the actual struct module itself, and I'm not sure how we'd fix that.

Take the author field for example. The author that their implementation returns needs to have the correct fields (name, url, icon_url). Do you think this is clear? The only indicator is the type spec which now that I'm thinking about it might be enough?

Additionally, if these fields don't exist the user will not get a useful error. For example, if their author/1 method doesn't return a term with the url field they'll get an error that :url doesn't exist in their term. IMO this would be unfriendly inside of a function doing as much as from/1 is.

@@ -381,6 +422,46 @@ defmodule Nostrum.Struct.Embed do
put_field(%__MODULE__{embed | fields: []}, name, value, inline)
end

@doc """
Create an embed from a struct that implements the protocol `Nostrum.Struct.Embed.Protocol`.
Copy link
Owner

Choose a reason for hiding this comment

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

I don't think I'm 100% happy with the wording here. Structs don't necessarily implement a protocol per se, right? It's the module that implements the behavior. I obviously get what you're trying to say but it's not 100% correct and if someone is unfamiliar with behaviors I could see there being issues.

Also, this still mentions a protocol when we're using a behavior now.

Copy link
Contributor Author

Choose a reason for hiding this comment

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

My bad. I wrote this while I still relied on protocols and forgot to update it 🙏

@Awlexus
Copy link
Contributor Author

Awlexus commented Nov 26, 2020

Elixir LS should pick up on type mismatching in this case and emit a warning, but we can always add strict pattern matching and error messages to further help devs

@Kraigie
Copy link
Owner

Kraigie commented Dec 2, 2020

Sorry for the late response, I'm happy to move forward with this. I do think I would like to include the mentioned pattern matching and/or better error messages!

@Awlexus
Copy link
Contributor Author

Awlexus commented Dec 9, 2020

Added some pattern matching for the callbacks that return structs (author, footer and fields). I wasn't sure whether wanted a check for all other fields as well, so I omitted it for now.

@Kraigie
Copy link
Owner

Kraigie commented Dec 28, 2020

This looks good! I think some short examples would be nice, but besides that I'd be happy to merge it!

@Awlexus
Copy link
Contributor Author

Awlexus commented Dec 30, 2020

While adding some short examples with with doc tests I noticed that I call put_image/2 and put_thumbnail/2 with the value nil, which creates the structs with the urls set to nil. Should I handle this by adding function clauses to the mentioned functions that replace the current value with nil or should I just handle this in from/1, by checking if the values are nil?

Copy link
Collaborator

@jb3 jb3 left a comment

Choose a reason for hiding this comment

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

Looking good!

@Kraigie Kraigie merged commit f76a5e9 into Kraigie:master Jan 4, 2021
@Kraigie
Copy link
Owner

Kraigie commented Jan 4, 2021

Thanks!

jb3 pushed a commit that referenced this pull request Jan 4, 2021
* Turn embed into a behaviour

* Adjust type specs

* defmacro

* consistency

* Fix wording

* Add type check for callbacks

* handle nil

* add example in documentation and tests

Co-authored-by: Awlex <no thank you>
jb3 pushed a commit to jb3/nostrum that referenced this pull request Jan 16, 2021
* Turn embed into a behaviour

* Adjust type specs

* defmacro

* consistency

* Fix wording

* Add type check for callbacks

* handle nil

* add example in documentation and tests

Co-authored-by: Awlex <no thank you>
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.

None yet

3 participants