Closed aroth closed 5 months ago
Hey @aroth, there's no _combobox partial as of the latest version. It got renamed to _component at some point. Is it possible you coupled your wrapper to _combobox and then updated the gem?
@josefarias I'm in 0.1.40 and am seeing:
app/views/hotwire_combobox/_combobox.html.erb
% cd /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/hotwire_combobox-0.1.40/app/views/hotwire_combobox/
% ls -l
total 32
-rw-r--r-- 1 aroth staff 368 Mar 11 11:41 _combobox.html.erb
-rw-r--r-- 1 aroth staff 291 Mar 11 11:41 _next_page.turbo_stream.erb
-rw-r--r-- 1 aroth staff 207 Mar 11 11:41 _paginated_options.turbo_stream.erb
-rw-r--r-- 1 aroth staff 306 Mar 11 11:41 _pagination.html.erb
drwxr-xr-x 6 aroth staff 192 Mar 11 11:41 combobox
Ah sorry @aroth, I was thinking about the changes in https://github.com/josefarias/hotwire_combobox/pull/80/files#diff-36941d6ca27cc45f677b8d89ca6a8f2ff93e438f0bfe4cdead4f5c9fa93ffe00 which I thought had been released, but they've only been merged to main and not released. Anyway, that change should be coming soon!
I think this might be due to the engine being isolated, which is modifiable.
Can you share your ViewComponent implementation please? So I have something to test against
@josefarias Sure thing. Reduced to bare minimum, I hope this helps:
Class:
class HwComboboxComponent < ApplicationComponent
def initialize(attribute:, collection:, form:)
@attribute = attribute
@form = form
@collection = collection
end
attr_reader :attribute, :form, :collection
end
Template:
<%= form.combobox attribute, collection %>
Usage:
<%= form_for Unit.new, url: "/" do |form| %>
<%= render HwComboboxComponent.new(form:, collection: Unit.all, attribute: User) %>
<% end %>
Spec:
# frozen_string_literal: true
require "rails_helper"
RSpec.describe HwComboboxComponent, type: :component do
let(:object) { OpenStruct.new(source: [], errors: {}) }
let(:form) { form_builder_for("model_name", object) }
let(:collection) { [{id: 1, display: "First"}, {id: 2, display: "Second"}] }
let(:component) { described_class.new(attribute: :source, form:, collection:) }
it "renders component" do
render_inline component
expect(rendered_content).to have_css "input.hw-combobox__input"
end
end
Failure:
Failures:
1) HwComboboxComponent renders component
Failure/Error: <%= form.combobox attribute, collection %>
ActionView::MissingTemplate:
Missing partial hotwire_combobox/_combobox with {:locale=>[:en], :formats=>[:html, :text, :js, :css, :ics, :csv, :vcf, :vtt, :png, :jpeg, :gif, :bmp, :tiff, :svg, :webp, :mpeg, :mp3, :ogg, :m4a, :webm, :mp4, :otf, :ttf, :woff, :woff2, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json, :pdf, :zip, :gzip, :turbo_stream], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder, :arb]}.
@aroth, could I get you to point your gem to this branch and see if it's fixed for you, please? https://github.com/josefarias/hotwire_combobox/pull/99
@siddhartharun @pranavbabu @adrianthedev if any of you have a spare minute, could I get you to also point your gem to that branch and check whether things keep working as expected?
I'm worried about something similar to https://github.com/josefarias/hotwire_combobox/issues/16 coming back if we merge that branch – and you three had previously experienced that issue whereas I hadn't. No worries if you're busy, I don't want to unnecessarily take up your time.
Thank you all so much!
As I remember sometimes when I used ViewComponents there was a problem with rendering partials without specified formats, and usually putting explicit format works something like this <%= render partial: hotwire_combobox/combobox formats: [:html] %>
@josefarias
Still seeing a failure. Stacktrace below:
Failures:
1) Forms::HwComboboxComponent renders component
Failure/Error: <%= form.combobox attribute, collection %>
ActionView::MissingTemplate:
Missing partial hotwire_combobox/_component with {:locale=>[:en], :formats=>[:html, :text, :js, :css, :ics, :csv, :vcf, :vtt, :png, :jpeg, :gif, :bmp, :tiff, :svg, :webp, :mpeg, :mp3, :ogg, :m4a, :webm, :mp4, :otf, :ttf, :woff, :woff2, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json, :pdf, :zip, :gzip, :turbo_stream], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder, :arb]}.
Searched in:
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/path_set.rb:42:in `find'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/lookup_context.rb:131:in `find'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/renderer/partial_renderer.rb:264:in `find_template'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/renderer/partial_renderer.rb:231:in `render'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/renderer/renderer.rb:83:in `render_partial_to_object'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/renderer/renderer.rb:29:in `render_to_object'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/renderer/renderer.rb:24:in `render'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/helpers/rendering_helper.rb:37:in `block in render'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/base.rb:291:in `in_rendering_context'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/helpers/rendering_helper.rb:33:in `render'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/bundler/gems/hotwire_combobox-7995c15a24bf/app/presenters/hotwire_combobox/component.rb:36:in `render_in'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/gems/actionview-7.1.3.2/lib/action_view/helpers/rendering_helper.rb:42:in `render'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/bundler/gems/hotwire_combobox-7995c15a24bf/lib/hotwire_combobox/helper.rb:21:in `hw_combobox_tag'
# /Users/aroth/.rbenv/versions/3.2.2/lib/ruby/gems/3.2.0/bundler/gems/hotwire_combobox-7995c15a24bf/lib/hotwire_combobox/engine.rb:11:in `combobox'
# ./app/components/forms/hw_combobox_component.html.erb:1:in `call'
@aroth sorry you're still having problems! I spent some more time on this today but wasn't able to replicate.
If at all possible, would you mind sharing an example app that exhibits this behavior? Ideally a brand new rails app as a minimal reproduction. Appreciate your time!
@josefarias Here you go:
https://github.com/aroth/hw_combo_vc_rspec
On closer investigation, the issue has something to do with the output of FormBuilderHelper#form_builder_for
which we use in our testing setup... and hasn't been an issue up until now. Perhaps you'll notice something that is not obvious to us.
Running rspec
should produce the same issue above.
% rspec
F
Failures:
1) SearchComponent works
Failure/Error: <%= form.combobox "cats", ["Cornish Rex", "Ragdoll", "Scottish Fold"] %>
ActionView::MissingTemplate:
Missing partial hotwire_combobox/_component with {:locale=>[:en], :formats=>[:html, :text, :js, :css, :ics, :csv, :vcf, :vtt, :png, :jpeg, :gif, :bmp, :tiff, :svg, :webp, :mpeg, :mp3, :ogg, :m4a, :webm, :mp4, :otf, :ttf, :woff, :woff2, :xml, :rss, :atom, :yaml, :multipart_form, :url_encoded_form, :json, :pdf, :zip, :gzip, :turbo_stream], :variants=>[], :handlers=>[:raw, :erb, :html, :builder, :ruby, :jbuilder]}.
Searched in:
# ./app/components/search_component.html.erb:3:in `call'
# ./spec/components/search_component_spec.rb:10:in `block (2 levels) in <top (required)>'
Finished in 0.01869 seconds (files took 0.73511 seconds to load)
1 example, 1 failure
Failed examples:
The useful commit: https://github.com/aroth/hw_combo_vc_rspec/commit/0ed8dab1c229b5bfeca3dba0314cd373de866e79
Hi @josefarias -- following up to see if you've had a chance to take a look.
Sorry @aroth, not yet! I prioritized shipping multiselect and grouped options over this. But keeping this open and visible.
Hey @aroth meant to take a look at this one today but the repo above is 404ing on me. Any chance it's been deleted or private?
@josefarias Now public!
Hey @aroth, thanks for sharing that minimal reproduction. Super helpful.
I do believe this is an issue with how your #form_builder_for
helper is set up.
I can see you're initializing a stubbed LookupContext
with an empty array as the view paths. This probably works most of the time because Rails-native form helpers don't do any view lookups (that I'm aware). But the form.combobox
helper added by this gem uses a view template for rendering its more complex markup — so you need to add the engine's view paths to the lookup context if you want to stub the form builder in this way.
These changes make the test in your app pass for me locally:
diff --git a/spec/components/search_component_spec.rb b/spec/components/search_component_spec.rb
index 24be4f7..661a811 100644
--- a/spec/components/search_component_spec.rb
+++ b/spec/components/search_component_spec.rb
@@ -10,6 +10,6 @@ RSpec.describe SearchComponent, type: :component do
render_inline described_class.new(form:)
expect(rendered_content).to include("Search Component")
- expect(rendered_content).to have_css "input.hw-combobox__input"
+ expect(page).to have_css "input.hw-combobox__input"
end
end
\ No newline at end of file
diff --git a/spec/support/form_builder.rb b/spec/support/form_builder.rb
index 0e51ce5..1dc5c4b 100644
--- a/spec/support/form_builder.rb
+++ b/spec/support/form_builder.rb
@@ -4,10 +4,11 @@ module FormBuilderHelper
# Creates a form builder for the given model name and object which can be used
# to render form components.
def form_builder_for(model_name, object, builder: ActionView::Helpers::FormBuilder)
- lookup_context = ActionView::LookupContext.new([])
+ tested_view_paths = [ HotwireCombobox::Engine.root.join("app", "views") ]
+ lookup_context = ActionView::LookupContext.new(tested_view_paths)
assigns = {}
controller = ActionController::Base.new
- view_context = ActionView::Base.new(lookup_context, assigns, controller)
+ view_context = ActionView::Base.with_empty_template_cache.new(lookup_context, assigns, controller)
builder.new(model_name, object, view_context, {})
end
Please try that and let me know if it's still not working. Closing for now. Thanks!
Great library, thank you!
I've wrapped hotwire_combobox in a ViewComponent. The template is straightforward:
When testing the ViewCompnent, the
hotwire_combobox/_combobox
partial from the gem cannot be found.Please advise. Might there be something you need to do in the library such that the partial can be found?