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

Add basic attributes API (experimental) #963

Open
wants to merge 7 commits into
base: main
Choose a base branch
from
Open

Conversation

BlakeWilliams
Copy link
Member

@BlakeWilliams BlakeWilliams commented Jun 14, 2021

This adds a basic and experimental attributes API that is used to define the
properties that a component accepts when initialized.

The idea behind this API is to give the library more control over the
initializer, attempt to close API gaps like helpers sometimes not being
callable, and reduce boilerplate when assigning attributes.

As-is, the API introduces two new methods:

  1. requires :name - defines a required attribute accessible via the name property.. If this value is not provided when initializing the component an ArgumentError is raised.
  2. accepts :name - defines an optional attribute accessible via the name property. Optionally, a default value can be provided by passing a default kwarg. e.g. accepts :name, default: "NullUser".

This API is not added to all components by default, but can be opted-into by
adding include ViewComponent::Attributes to a component.

Feedback/thoughts welcome!

@BlakeWilliams
Copy link
Member Author

@BlakeWilliams BlakeWilliams commented Jun 14, 2021

related to #639

@BlakeWilliams BlakeWilliams mentioned this pull request Jun 14, 2021
content_tag(:h1, @title),
content_tag(:p, @body),
content_tag(:date, @posted_at),
Copy link
Member Author

@BlakeWilliams BlakeWilliams Jun 14, 2021

Choose a reason for hiding this comment

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

Suggested change
content_tag(:h1, @title),
content_tag(:p, @body),
content_tag(:date, @posted_at),
content_tag(:h1, title),
content_tag(:p, body),
content_tag(:date, posted_at),

@BlakeWilliams
Copy link
Member Author

@BlakeWilliams BlakeWilliams commented Jun 14, 2021

This API does somewhat deviate from Rails, but I think if Rails does decide to adopt ViewComponent (or parts of it) we can easily omit this extra module.

There is some overlap with ActiveModel::AttributeAssignment. Maybe one potential path forward here is trying to build a similar API on top of it (maybe by introducing attr_required?)

@BlakeWilliams BlakeWilliams marked this pull request as ready for review Jun 16, 2021
@pinzonjulian
Copy link

@pinzonjulian pinzonjulian commented Jul 2, 2021

I believe Rails already has a powerful attribute assignment API: ActiveModel::Attributes. The problem is that it still needs a bit of work before it can become a public API in Rails.

See this thread where Rafael França talks a little bit about it.
https://twitter.com/rafaelfranca/status/1361444817578971139?s=20

The AttributeAssignment module is more of a convenient but simple way to initialise allowed parameters.

How would you feel about checking in with Rails Core about the status of ActiveModel::Attributes and maybe help make it public to use it in VC?

@jonspalmer
Copy link
Collaborator

@jonspalmer jonspalmer commented Jul 17, 2021

I like something along the lines of this API. We've been just using ActiveModel::Attributes and we'll deal with it if it breaks down the line. I'm also experimenting with dry-initializer.

I believe we need to support positional arguments too.

What would be really terrific would be to have some common API that ViewComponent accepts and that we could write a number of "Adapters" that would translate dry-initializer -> VS attributes etc. We could cover common cases and consumers could write or contribute their own for more esoteric patterns. You could imagine auto detecting common cases too.

A nice benefit of a having an API like this is the ability to interrogate them to discover facts about the component. In https://github.com/jonspalmer/view_component_storybook we just added a bunch of code to inspect the constructor of the component so that we can validate stories written against the component as trying to set constructor arguments. I'm just introspecting the results of MyComponeont.instance_method(:initialize).parameters That works well enough. Though interestingly if the component is using dry-initializer that information is lost ( in fact its even worse: dry-rb/dry-initializer#88)

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