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

Overriding inherited partials #411

Closed
awead opened this issue Jul 17, 2020 · 14 comments
Closed

Overriding inherited partials #411

awead opened this issue Jul 17, 2020 · 14 comments
Labels

Comments

@awead
Copy link

awead commented Jul 17, 2020

Steps to reproduce

When inheriting view component from another Rails gem, I was expecting to be able to override a component's partial in my local app. For example:

Given:

[gem_home]/app/components/some_component.html.erb

A local file with the same name and location:

app/components/some_component.html.erb

Would replace/override the content of the gem's partial.

Expected behavior

I was expecting what Rails does with other types such as views, and replace/override the content of the gem's partial.

Actual behavior

It doesn't seem to. I can sub-class the gem's component Ruby class and write my own partial, which is fine, but I'm wondering if this is a bug and we should expect overriding things the way we typically to with other things.

System configuration

Rails version: 6.0.3.2

Ruby version: 2.6.6p146

Gem version: 2.14.0

@joelhawksley
Copy link
Member

@awead thanks for taking the time to file this issue! I'm wondering what others might think about the right conventions/techniques for achieving this goal.

Can you provide an example of the gem you're working with, and what you're trying to do by replacing the component's template with your own?

@jonspalmer
Copy link
Contributor

I'm curious about the examples of other places where you can just replace the view? I'm don't remember seeing that. I'm also not sure I understand the use case of subclassing the component but also replacing the gem components view file. I would expect you to want one or the other.

Remember that Rails does view looking/path resolution by convention based on the path derived from the namespace and class name of the Controller or in our case Component.

So if you have a gem like

[gem_home]/app/components/some_component.rb
[gem_home]/app/components/some_component.html.erb

You subclass it as:

/app/components/subclassed_some_component.rb

then the view would expect to be:

/app/components/subclassed_some_component.html.erb

IMO it would be a bit strange to change any of that as its pretty fundamental to how Rails apps work.

@awead
Copy link
Author

awead commented Jul 22, 2020

Hi all, sorry for the delayed response, and thanks for the input. Here's a link to a commit that I made in the repo I'm trying to do the override in:

psu-libraries/scholarsphere@21b3313

The Blacklight gem has the file app/components/blacklight/constraint_layout_component.html.erb. I'm placing a modified variant of this file in the same relative path and it's not getting picked up.

I know for sure I can do these sorts of things in app/views. I think it's part of the controller's wiring to look through inherited paths to different views.

I'm guessing that a view component's Ruby class isn't doing that same kind of inheritance dance that a controller does. I can definitely override the gem's component Ruby class, though.

One thing I haven't tried is overriding both the Ruby class and the view...

@joelhawksley
Copy link
Member

@jcoyne you're involved with Blacklight, right? What do you think is the right approach for us to take here?

@cdmo
Copy link

cdmo commented Jul 29, 2020

Controllers have to be open classed or subclassed if you want to modify their behavior, but their partial (View) can just be overridden via path lookup in your application.

ViewComponents have to be open classed or sublcassed if you want to modify their behavior OR their partial.

I can see how the pattern with controllers/models and their associated views might setup an expectation that you could override just the partial by being present in the path.

So let's say I want to change a single tag in an inherited engine's ViewComponent template. I'd rather have a <span> instead of <div> or something like that. In that case I'd create an ViewComponent that was empty save for subclassing the original component and then I could create a partial that changed the markup in the template? Is that how overriding just the template would work?

@stale
Copy link

stale bot commented Aug 29, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Aug 29, 2020
@BlakeWilliams BlakeWilliams self-assigned this Aug 31, 2020
@stale stale bot removed the stale label Aug 31, 2020
@BlakeWilliams BlakeWilliams removed their assignment Sep 3, 2020
@stale
Copy link

stale bot commented Oct 4, 2020

This issue has been automatically marked as stale because it has not had recent activity. It will be closed if no further activity occurs. Thank you for your contributions.

@stale stale bot added the stale label Oct 4, 2020
@stale stale bot closed this as completed Oct 12, 2020
@jcoyne
Copy link
Collaborator

jcoyne commented Oct 12, 2020

@joelhawksley sorry, I just saw this mention. I think @awead was on the right track. Typically Rails looks through a list of search paths until it finds a partial. The application directory are in the front of of the list and the gem paths are at the back of this list, so the application views always get preference over any in the gem. I think it would be easiest for new adopters if view_component also used this way, however there's a likely performance penalty there.

@joelhawksley
Copy link
Member

@jcoyne @awead @cdmo Feel free to reopen if you'd like to take this on! I'd love to see a PR with a suggested API/example case you'd expect to work ❤️

@coorasse
Copy link

Overriding also the component works...but is quite nasty. I am trying to figure out how to path this behaviour but I am bit lost...

@coorasse
Copy link

There's probably something to change here: https://github.com/github/view_component/blob/main/lib/view_component/compiler.rb#L145 if we want to support overriding the partials I guess

@barmintor
Copy link

I think a layer further down (unfortunately in an experimental API) is the place to incorporate the view_path logic that @jcoyne mentioned: https://github.com/github/view_component/blob/32d7bab3e0744f95ce11b0dba2508a46d9bf12a1/lib/view_component/base.rb#L358

Using the partial search paths is an important part of reusing Rails engines for which display is intended to be controlled by the installing app. However, I'm not sure it matches the envisioned use case for ViewComponents - the component seems intended to be tightly bound to a particular template, for reuse across a complex but unitary app (or I guess a group of apps with a common front-end). I guess a related question would be how a Rails app using an engine's components could add local translations (it's the other use of _sidecar_files as far as I can tell)?

The use case @awead posts is an important one for the specific engine we collaborate on, and I'd be sympathetic to the idea that we ought to deal with it (at least initially) in a base ViewComponent class in our codebase - but ViewComponent::Compiler#templates is private, and ViewComponent::Base._sidecar_files is specifically documented as an unstable API (I'd also feel kind of bad to override a method called "sidecar_files" to return... not sidecar files, but in this case that method is a stand-in for the template lookup). So making the intervention there seems pretty risky. I'm going to open a ticket to try a simple modification that checks Rails.root for the template before the component's source location to see if that gets us close enough.

@marlo-longley
Copy link

I wanted to add some findings on this that I recently encountered in case it helps anybody. I was able to override the view component partial with a few steps and using the subclassing approach suggested by @cdmo above. Here's what I did to override app/components/blacklight/search_bar_component.html.erb:

  1. Make a simple subclass of the Blacklight component in my local app at app/components/dlme_search_bar_component.rb with the following code:
class DlmeSearchBarComponent < Blacklight::SearchBarComponent 
end
  1. Edit the accompanying partial at app/components/dlme_search_bar_component.html.erb to reflect my HTML changes.

  2. Then, I have to tell my local app to find the new DlmeSearchBarComponent rather than Blacklight's. This works like a more typical view override. In app/views/catalog/_search_form.html.erb I replaced the class reference

<%= render(Blacklight::SearchBarComponent.new( ... )) %>

with

<%= render(DlmeSearchBarComponent.new( ... )) %>

After adding these 3 files to my local app, my changes were reflected.

@barmintor
Copy link

FWIW, I prototyped the two approaches (a Compiler change, a change to _sidecar_files) mentioned here in this commit (for an engine that uses ViewComponent): barmintor/blacklight@3b834bc

In a pinch, I think you could monkey-patch components to get this behavior. I think if you want to be able to add sidecar files in a downstream app, you need the _sidecar_files override.

waiting-for-dev added a commit to solidusio/solidus that referenced this issue May 26, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
waiting-for-dev added a commit to solidusio/solidus that referenced this issue May 29, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
waiting-for-dev added a commit to solidusio/solidus that referenced this issue May 31, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
waiting-for-dev added a commit to solidusio/solidus that referenced this issue Jun 1, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
waiting-for-dev added a commit to solidusio/solidus that referenced this issue Jun 1, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
waiting-for-dev added a commit to solidusio/solidus that referenced this issue Jun 5, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Jun 9, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Jun 9, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Jun 19, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Jul 11, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Aug 2, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
waiting-for-dev added a commit to solidusio/solidus that referenced this issue Aug 8, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
waiting-for-dev added a commit to solidusio/solidus that referenced this issue Aug 9, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Sep 25, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Sep 27, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Sep 28, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Sep 29, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
elia pushed a commit to solidusio/solidus that referenced this issue Oct 6, 2023
Unfortunately, view_component doesn't allow overriding templates from
the host application by just having the same relative path [1].

For now, we'll use the inline templates feature from v3 [2] so that host
applications can override only the template while still inheriting the
rest of view logic.

[1] - ViewComponent/view_component#411
[2] - https://viewcomponent.org/guide/templates.html#inline
kirkkwang added a commit to notch8/archives_online that referenced this issue Aug 23, 2024
This commit will add relevant SVG files for the breadcrumbs and a few
helpers as well as some SolrDocument methods that we'll need.  The main
thing is adding the Ngao::Arclight::BreadcrumbsHierarchyComponent
because we want to override the breadcrumbs_hierarchy_component view.
Overriding view component views are a little different that regular view
files where if you match the path you'll be set.  This required us to
create the component object in this application and then it would be
able to pick up the overridden view component erb.

Ref:
- ViewComponent/view_component#411
kirkkwang added a commit to notch8/archives_online that referenced this issue Aug 23, 2024
This commit will add relevant SVG files for the breadcrumbs and a few
helpers as well as some SolrDocument methods that we'll need.  The main
thing is adding the Ngao::Arclight::BreadcrumbsHierarchyComponent
because we want to override the breadcrumbs_hierarchy_component view.
Overriding view component views are a little different that regular view
files where if you match the path you'll be set.  This required us to
create the component object in this application and then it would be
able to pick up the overridden view component erb.

Ref:
- ViewComponent/view_component#411
kirkkwang added a commit to notch8/archives_online that referenced this issue Aug 24, 2024
This commit will add relevant SVG files for the breadcrumbs and a few
helpers as well as some SolrDocument methods that we'll need.  The main
thing is adding the Ngao::Arclight::BreadcrumbsHierarchyComponent
because we want to override the breadcrumbs_hierarchy_component view.
Overriding view component views are a little different that regular view
files where if you match the path you'll be set.  This required us to
create the component object in this application and then it would be
able to pick up the overridden view component erb.

Ref:
- ViewComponent/view_component#411
kirkkwang added a commit to notch8/archives_online that referenced this issue Aug 26, 2024
This commit will add relevant SVG files for the breadcrumbs and a few
helpers as well as some SolrDocument methods that we'll need.  The main
thing is adding the Ngao::Arclight::BreadcrumbsHierarchyComponent
because we want to override the breadcrumbs_hierarchy_component view.
Overriding view component views are a little different that regular view
files where if you match the path you'll be set.  This required us to
create the component object in this application and then it would be
able to pick up the overridden view component erb.

Ref:
- ViewComponent/view_component#411
kirkkwang added a commit to notch8/archives_online that referenced this issue Aug 26, 2024
This commit will add relevant SVG files for the breadcrumbs and a few
helpers as well as some SolrDocument methods that we'll need.  The main
thing is adding the Ngao::Arclight::BreadcrumbsHierarchyComponent
because we want to override the breadcrumbs_hierarchy_component view.
Overriding view component views are a little different that regular view
files where if you match the path you'll be set.  This required us to
create the component object in this application and then it would be
able to pick up the overridden view component erb.

Ref:
- ViewComponent/view_component#411
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
Projects
None yet
Development

No branches or pull requests

9 participants