From f9be01afb35078fca36c85b3951ef41acc6ebd84 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Zen=C3=A9ixe?= <1379179+Zeneixe@users.noreply.github.com>
Date: Fri, 3 Nov 2023 18:53:28 +0100
Subject: [PATCH 1/8] Search for the Rails module in the root namespace (#1894)
---
docs/CHANGELOG.md | 4 ++++
lib/view_component/base.rb | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 4af977c041..c9b233a5e0 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -10,6 +10,10 @@ nav_order: 5
## main
+* Fix bug where the `Rails` module wasn't being searched from the root namespace.
+
+ *Zenéixe*
+
* Fix bug where `#with_request_url`, set the incorrect `request.fullpath`.
*Nachiket Pusalkar*
diff --git a/lib/view_component/base.rb b/lib/view_component/base.rb
index 0bdee95af1..f5a91ac117 100644
--- a/lib/view_component/base.rb
+++ b/lib/view_component/base.rb
@@ -219,7 +219,7 @@ def helpers
@__vc_helpers ||= __vc_original_view_context || controller.view_context
end
- if Rails.env.development? || Rails.env.test?
+ if ::Rails.env.development? || ::Rails.env.test?
def method_missing(method_name, *args) # rubocop:disable Style/MissingRespondToMissing
super
rescue => e # rubocop:disable Style/RescueStandardError
From 2bc5763a39c67e0d7da335cfa4ee403afa363d75 Mon Sep 17 00:00:00 2001
From: Reegan Viljoen <62689748+reeganviljoen@users.noreply.github.com>
Date: Fri, 3 Nov 2023 20:25:12 +0200
Subject: [PATCH 2/8] Add new helper API (#1860)
---
docs/CHANGELOG.md | 4 ++++
docs/guide/helpers.md | 20 +++++++++++++++++++
lib/view_component/base.rb | 1 +
lib/view_component/use_helpers.rb | 20 +++++++++++++++++++
.../components/use_helpers_component.html.erb | 3 +++
.../app/components/use_helpers_component.rb | 7 +++++++
test/sandbox/test/rendering_test.rb | 5 +++++
7 files changed, 60 insertions(+)
create mode 100644 lib/view_component/use_helpers.rb
create mode 100644 test/sandbox/app/components/use_helpers_component.html.erb
create mode 100644 test/sandbox/app/components/use_helpers_component.rb
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index c9b233a5e0..9ab9a22967 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -10,6 +10,10 @@ nav_order: 5
## main
+* Add `use_helper` API.
+
+ *Reegan Viljoen*
+
* Fix bug where the `Rails` module wasn't being searched from the root namespace.
*Zenéixe*
diff --git a/docs/guide/helpers.md b/docs/guide/helpers.md
index 1407fe14a8..172c3aea08 100644
--- a/docs/guide/helpers.md
+++ b/docs/guide/helpers.md
@@ -51,6 +51,26 @@ class UserComponent < ViewComponent::Base
end
```
+## UseHelpers setter
+
+By default, ViewComponents don't have access to helper methods defined externally. The `use_helpers` method allows external helpers to be called from the component.
+
+To use the `use_helpers` method, include `ViewComponent::UseHelpers`.
+`UseHelpers` defines the helper on the component and is similar in use to using `delegate` on helpers.
+
+```ruby
+class UseHelpersComponent < ViewComponent::Base
+ include ViewComponent::UseHelpers
+ use_helpers :icon
+
+ erb_template <<-ERB
+
+ <%= icon :user %>
+
+ ERB
+end
+```
+
## Nested URL helpers
Rails nested URL helpers implicitly depend on the current `request` in certain cases. Since ViewComponent is built to enable reusing components in different contexts, nested URL helpers should be passed their options explicitly:
diff --git a/lib/view_component/base.rb b/lib/view_component/base.rb
index f5a91ac117..6a2538c422 100644
--- a/lib/view_component/base.rb
+++ b/lib/view_component/base.rb
@@ -12,6 +12,7 @@
require "view_component/slotable"
require "view_component/translatable"
require "view_component/with_content_helper"
+require "view_component/use_helpers"
module ViewComponent
class Base < ActionView::Base
diff --git a/lib/view_component/use_helpers.rb b/lib/view_component/use_helpers.rb
new file mode 100644
index 0000000000..32d13cd433
--- /dev/null
+++ b/lib/view_component/use_helpers.rb
@@ -0,0 +1,20 @@
+# frozen_string_literal: true
+
+module ViewComponent::UseHelpers
+ extend ActiveSupport::Concern
+
+ class_methods do
+ def use_helpers(*args)
+ args.each do |helper_method|
+ class_eval(<<-RUBY, __FILE__, __LINE__ + 1)
+ def #{helper_method}(*args, &block)
+ raise HelpersCalledBeforeRenderError if view_context.nil?
+ __vc_original_view_context.#{helper_method}(*args, &block)
+ end
+ RUBY
+
+ ruby2_keywords(helper_method) if respond_to?(:ruby2_keywords, true)
+ end
+ end
+ end
+end
diff --git a/test/sandbox/app/components/use_helpers_component.html.erb b/test/sandbox/app/components/use_helpers_component.html.erb
new file mode 100644
index 0000000000..f24542007a
--- /dev/null
+++ b/test/sandbox/app/components/use_helpers_component.html.erb
@@ -0,0 +1,3 @@
+
+ <%= message %>
+
diff --git a/test/sandbox/app/components/use_helpers_component.rb b/test/sandbox/app/components/use_helpers_component.rb
new file mode 100644
index 0000000000..375c07db63
--- /dev/null
+++ b/test/sandbox/app/components/use_helpers_component.rb
@@ -0,0 +1,7 @@
+# frozen_string_literal: true
+
+class UseHelpersComponent < ViewComponent::Base
+ include ViewComponent::UseHelpers
+
+ use_helpers :message
+end
diff --git a/test/sandbox/test/rendering_test.rb b/test/sandbox/test/rendering_test.rb
index 2f5069ea45..cd985beb66 100644
--- a/test/sandbox/test/rendering_test.rb
+++ b/test/sandbox/test/rendering_test.rb
@@ -1094,4 +1094,9 @@ def test_content_security_policy_nonce
assert_selector("script", text: "\n//\n", visible: :hidden)
end
+
+ def test_use_helper
+ render_inline(UseHelpersComponent.new)
+ assert_selector ".helper__message", text: "Hello helper method"
+ end
end
From ad27702b38d5d4d5f5752ca64d1e7ce389677406 Mon Sep 17 00:00:00 2001
From: Blake Williams
Date: Fri, 3 Nov 2023 14:42:29 -0400
Subject: [PATCH 3/8] Fix slot names that start with call (#1828)
* Fix slot names that start with call
When a component is registered that starts with `call` the compiler detects it as a template method which is not correct. This changes the compiler to look for `call(_|$)` instead of `call` to avoid this issue.
This means that slots can't (and couldn't) start with `call_` since we still rely on the `call_` naming convention to generate the template methods. To make this more dev friendly, this adds a check that raises an error if a slot name starts with `call_`.
A more long-term fix would be to use some kind of template method container instead of relying on the `call_` naming convention.
---
docs/CHANGELOG.md | 4 ++++
lib/view_component/compiler.rb | 4 ++--
lib/view_component/errors.rb | 9 ++++++---
lib/view_component/slotable.rb | 8 ++++++++
test/sandbox/test/slotable_test.rb | 22 ++++++++++++++++++++++
5 files changed, 42 insertions(+), 5 deletions(-)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 9ab9a22967..84a0c8f45c 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -10,6 +10,10 @@ nav_order: 5
## main
+* Resolve an issue where slots starting with `call` would cause a `NameError`
+
+ *Blake Williams*
+
* Add `use_helper` API.
*Reegan Viljoen*
diff --git a/lib/view_component/compiler.rb b/lib/view_component/compiler.rb
index 72c7367c46..c5ee5b8bd9 100644
--- a/lib/view_component/compiler.rb
+++ b/lib/view_component/compiler.rb
@@ -219,12 +219,12 @@ def inline_calls
component_class.included_modules
)
- view_component_ancestors.flat_map { |ancestor| ancestor.instance_methods(false).grep(/^call/) }.uniq
+ view_component_ancestors.flat_map { |ancestor| ancestor.instance_methods(false).grep(/^call(_|$)/) }.uniq
end
end
def inline_calls_defined_on_self
- @inline_calls_defined_on_self ||= component_class.instance_methods(false).grep(/^call/)
+ @inline_calls_defined_on_self ||= component_class.instance_methods(false).grep(/^call(_|$)/)
end
def variants
diff --git a/lib/view_component/errors.rb b/lib/view_component/errors.rb
index 36f9ee570c..b896f53d1c 100644
--- a/lib/view_component/errors.rb
+++ b/lib/view_component/errors.rb
@@ -104,7 +104,10 @@ class InvalidSlotDefinitionError < BaseError
"string, or callable (that is proc, lambda, etc)"
end
- class SlotPredicateNameError < StandardError
+ class InvalidSlotNameError < StandardError
+ end
+
+ class SlotPredicateNameError < InvalidSlotNameError
MESSAGE =
"COMPONENT declares a slot named SLOT_NAME, which ends with a question mark.\n\n" \
"This isn't allowed because the ViewComponent framework already provides predicate " \
@@ -126,7 +129,7 @@ def initialize(klass_name, slot_name)
end
end
- class ReservedSingularSlotNameError < StandardError
+ class ReservedSingularSlotNameError < InvalidSlotNameError
MESSAGE =
"COMPONENT declares a slot named SLOT_NAME, which is a reserved word in the ViewComponent framework.\n\n" \
"To fix this issue, choose a different name."
@@ -136,7 +139,7 @@ def initialize(klass_name, slot_name)
end
end
- class ReservedPluralSlotNameError < StandardError
+ class ReservedPluralSlotNameError < InvalidSlotNameError
MESSAGE =
"COMPONENT declares a slot named SLOT_NAME, which is a reserved word in the ViewComponent framework.\n\n" \
"To fix this issue, choose a different name."
diff --git a/lib/view_component/slotable.rb b/lib/view_component/slotable.rb
index ecb4826a20..d46094b3cf 100644
--- a/lib/view_component/slotable.rb
+++ b/lib/view_component/slotable.rb
@@ -295,6 +295,7 @@ def validate_plural_slot_name(slot_name)
raise ReservedPluralSlotNameError.new(name, slot_name)
end
+ raise_if_slot_conflicts_with_call(slot_name)
raise_if_slot_ends_with_question_mark(slot_name)
raise_if_slot_registered(slot_name)
end
@@ -308,6 +309,7 @@ def validate_singular_slot_name(slot_name)
raise ReservedSingularSlotNameError.new(name, slot_name)
end
+ raise_if_slot_conflicts_with_call(slot_name)
raise_if_slot_ends_with_question_mark(slot_name)
raise_if_slot_registered(slot_name)
end
@@ -322,6 +324,12 @@ def raise_if_slot_registered(slot_name)
def raise_if_slot_ends_with_question_mark(slot_name)
raise SlotPredicateNameError.new(name, slot_name) if slot_name.to_s.ends_with?("?")
end
+
+ def raise_if_slot_conflicts_with_call(slot_name)
+ if slot_name.start_with?("call_")
+ raise InvalidSlotNameError, "Slot cannot start with 'call_'. Please rename #{slot_name}"
+ end
+ end
end
def get_slot(slot_name)
diff --git a/test/sandbox/test/slotable_test.rb b/test/sandbox/test/slotable_test.rb
index 3a931167e6..086f418e59 100644
--- a/test/sandbox/test/slotable_test.rb
+++ b/test/sandbox/test/slotable_test.rb
@@ -719,4 +719,26 @@ def test_slot_with_content_shorthand
assert component.title.content?
end
+
+ def test_slot_names_cannot_start_with_call_
+ assert_raises ViewComponent::InvalidSlotNameError do
+ Class.new(ViewComponent::Base) do
+ renders_one :call_out_title
+ end
+ end
+
+ assert_raises ViewComponent::InvalidSlotNameError do
+ Class.new(ViewComponent::Base) do
+ renders_many :call_out_titles
+ end
+ end
+ end
+
+ def test_slot_names_can_start_with_call
+ assert_nothing_raised do
+ Class.new(ViewComponent::Base) do
+ renders_one :callhome_et
+ end
+ end
+ end
end
From 090ee0d118d94bc46008ea0bf166b2ca97e300c7 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 6 Nov 2023 10:57:33 +0100
Subject: [PATCH 4/8] Bump net-imap from 0.4.2 to 0.4.4 (#1901)
Bumps [net-imap](https://github.com/ruby/net-imap) from 0.4.2 to 0.4.4.
- [Release notes](https://github.com/ruby/net-imap/releases)
- [Commits](https://github.com/ruby/net-imap/compare/v0.4.2...v0.4.4)
---
updated-dependencies:
- dependency-name: net-imap
dependency-type: direct:production
update-type: version-update:semver-patch
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Gemfile.lock | 5 ++++-
1 file changed, 4 insertions(+), 1 deletion(-)
diff --git a/Gemfile.lock b/Gemfile.lock
index c5b1fa3608..c54a207e37 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -160,7 +160,7 @@ GEM
mini_mime (1.1.5)
mini_portile2 (2.8.4)
minitest (5.20.0)
- net-imap (0.4.2)
+ net-imap (0.4.4)
date
net-protocol
net-pop (0.1.2)
@@ -333,6 +333,9 @@ DEPENDENCIES
jbuilder (~> 2)
m (~> 1)
minitest (~> 5.18)
+ net-imap
+ net-pop
+ net-smtp
pry (~> 0.13)
puma (~> 6)
rails (~> 7.0.0)
From 47191f0e96707e64ffa315843a38c1b5583ee056 Mon Sep 17 00:00:00 2001
From: "dependabot[bot]" <49699333+dependabot[bot]@users.noreply.github.com>
Date: Mon, 6 Nov 2023 11:06:30 +0100
Subject: [PATCH 5/8] Bump cuprite from 0.14.3 to 0.15 (#1900)
Bumps [cuprite](https://github.com/rubycdp/cuprite) from 0.14.3 to 0.15.
- [Release notes](https://github.com/rubycdp/cuprite/releases)
- [Changelog](https://github.com/rubycdp/cuprite/blob/main/CHANGELOG.md)
- [Commits](https://github.com/rubycdp/cuprite/compare/v0.14.3...v0.15)
---
updated-dependencies:
- dependency-name: cuprite
dependency-type: direct:development
update-type: version-update:semver-minor
...
Signed-off-by: dependabot[bot]
Co-authored-by: dependabot[bot] <49699333+dependabot[bot]@users.noreply.github.com>
---
Gemfile | 2 +-
Gemfile.lock | 16 ++++++++--------
2 files changed, 9 insertions(+), 9 deletions(-)
diff --git a/Gemfile b/Gemfile
index e4028ffb43..4cb0507415 100644
--- a/Gemfile
+++ b/Gemfile
@@ -11,7 +11,7 @@ gem "rails", (rails_version == "main") ? {git: "https://github.com/rails/rails",
gem "rspec-rails", "~> 5"
group :test do
- gem "cuprite", "~> 0.8"
+ gem "cuprite", "~> 0.15"
gem "puma", "~> 6"
gem "selenium-webdriver", "4.9.0" # 4.9.1 requires Ruby 3+
diff --git a/Gemfile.lock b/Gemfile.lock
index c54a207e37..93a216c4d0 100644
--- a/Gemfile.lock
+++ b/Gemfile.lock
@@ -74,7 +74,7 @@ GEM
i18n (>= 1.6, < 2)
minitest (>= 5.1)
tzinfo (~> 2.0)
- addressable (2.8.4)
+ addressable (2.8.5)
public_suffix (>= 2.0.2, < 6.0)
ansi (1.5.0)
appraisal (2.5.0)
@@ -104,9 +104,9 @@ GEM
coderay (1.1.3)
concurrent-ruby (1.2.2)
crass (1.0.6)
- cuprite (0.14.3)
+ cuprite (0.15)
capybara (~> 3.0)
- ferrum (~> 0.13.0)
+ ferrum (~> 0.14.0)
date (3.3.3)
debug (1.8.0)
irb (>= 1.5.0)
@@ -121,7 +121,7 @@ GEM
rubocop
smart_properties
erubi (1.12.0)
- ferrum (0.13)
+ ferrum (0.14)
addressable (~> 2.5)
concurrent-ruby (~> 1.1)
webrick (~> 1.7)
@@ -158,7 +158,7 @@ GEM
matrix (0.4.2)
method_source (1.0.0)
mini_mime (1.1.5)
- mini_portile2 (2.8.4)
+ mini_portile2 (2.8.5)
minitest (5.20.0)
net-imap (0.4.4)
date
@@ -180,10 +180,10 @@ GEM
pry (0.14.2)
coderay (~> 1.1)
method_source (~> 1.0)
- public_suffix (5.0.1)
+ public_suffix (5.0.3)
puma (6.4.0)
nio4r (~> 2.0)
- racc (1.7.1)
+ racc (1.7.3)
rack (2.2.8)
rack-test (2.1.0)
rack (>= 1.3)
@@ -326,7 +326,7 @@ DEPENDENCIES
better_html
bundler (~> 2)
capybara (~> 3)
- cuprite (~> 0.8)
+ cuprite (~> 0.15)
debug
erb_lint
haml (~> 6)
From b11ba1f197e71cab1cc0758373a58c9b2e364755 Mon Sep 17 00:00:00 2001
From: Andrew Duthie
Date: Mon, 6 Nov 2023 18:56:55 -0500
Subject: [PATCH 6/8] Allow setting method when using the test helper (#1805)
---
docs/CHANGELOG.md | 4 ++++
docs/index.md | 1 +
lib/view_component/test_helpers.rb | 14 +++++++++++++-
.../app/components/current_page_component.rb | 6 +-----
test/sandbox/config/routes.rb | 1 +
test/sandbox/test/test_helper_test.rb | 12 ++++++++++--
6 files changed, 30 insertions(+), 8 deletions(-)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index 84a0c8f45c..ffd121035f 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -26,6 +26,10 @@ nav_order: 5
*Nachiket Pusalkar*
+* Allow setting method when using the `with_request_url` test helper.
+
+ *Andrew Duthie*
+
## 3.7.0
* Support Rails 7.1 in CI.
diff --git a/docs/index.md b/docs/index.md
index 393772ac4d..b20009efdb 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -211,6 +211,7 @@ ViewComponent is built by over a hundred members of the community, including:
+
## Who uses ViewComponent?
diff --git a/lib/view_component/test_helpers.rb b/lib/view_component/test_helpers.rb
index 3a24b1aa31..02d1a9b7c4 100644
--- a/lib/view_component/test_helpers.rb
+++ b/lib/view_component/test_helpers.rb
@@ -163,10 +163,20 @@ def with_controller_class(klass)
# end
# ```
#
+ # To specify a request method, pass the method param:
+ #
+ # ```ruby
+ # with_request_url("/users/42", method: "POST") do
+ # render_inline(MyComponent.new)
+ # end
+ # ```
+ #
# @param path [String] The path to set for the current request.
# @param host [String] The host to set for the current request.
- def with_request_url(full_path, host: nil)
+ # @param method [String] The request method to set for the current request.
+ def with_request_url(full_path, host: nil, method: nil)
old_request_host = vc_test_request.host
+ old_request_method = vc_test_request.request_method
old_request_path_info = vc_test_request.path_info
old_request_path_parameters = vc_test_request.path_parameters
old_request_query_parameters = vc_test_request.query_parameters
@@ -177,6 +187,7 @@ def with_request_url(full_path, host: nil)
vc_test_request.instance_variable_set(:@fullpath, full_path)
vc_test_request.instance_variable_set(:@original_fullpath, full_path)
vc_test_request.host = host if host
+ vc_test_request.request_method = method if method
vc_test_request.path_info = path
vc_test_request.path_parameters = Rails.application.routes.recognize_path_with_request(vc_test_request, path, {})
vc_test_request.set_header("action_dispatch.request.query_parameters",
@@ -185,6 +196,7 @@ def with_request_url(full_path, host: nil)
yield
ensure
vc_test_request.host = old_request_host
+ vc_test_request.request_method = old_request_method
vc_test_request.path_info = old_request_path_info
vc_test_request.path_parameters = old_request_path_parameters
vc_test_request.set_header("action_dispatch.request.query_parameters", old_request_query_parameters)
diff --git a/test/sandbox/app/components/current_page_component.rb b/test/sandbox/app/components/current_page_component.rb
index 559862199d..afd1c327e7 100644
--- a/test/sandbox/app/components/current_page_component.rb
+++ b/test/sandbox/app/components/current_page_component.rb
@@ -2,10 +2,6 @@
class CurrentPageComponent < ViewComponent::Base
def text
- if current_page?("/slots")
- "Inside /slots"
- else
- "Outside /slots"
- end
+ "#{current_page?("/slots") ? "Inside" : "Outside"} /slots (#{request.method} #{request.path})"
end
end
diff --git a/test/sandbox/config/routes.rb b/test/sandbox/config/routes.rb
index e921c0003d..afbb357be9 100644
--- a/test/sandbox/config/routes.rb
+++ b/test/sandbox/config/routes.rb
@@ -29,6 +29,7 @@
get :cached_partial, to: "integration_examples#cached_partial"
get :inherited_sidecar, to: "integration_examples#inherited_sidecar"
get :inherited_from_uncompilable_component, to: "integration_examples#inherited_from_uncompilable_component"
+ post :create, to: "integration_examples#create"
constraints(lambda { |request| request.env["warden"].authenticate! }) do
get :constraints_with_env, to: "integration_examples#index"
diff --git a/test/sandbox/test/test_helper_test.rb b/test/sandbox/test/test_helper_test.rb
index 90339a10fc..c55dfc0ebf 100644
--- a/test/sandbox/test/test_helper_test.rb
+++ b/test/sandbox/test/test_helper_test.rb
@@ -8,7 +8,7 @@ def test_with_request_url_inside_slots_path
render_inline(CurrentPageComponent.new)
end
- assert_selector("div", text: "Inside /slots")
+ assert_selector("div", text: "Inside /slots (GET /slots)")
end
def test_with_request_url_outside_slots_path
@@ -16,7 +16,15 @@ def test_with_request_url_outside_slots_path
render_inline(CurrentPageComponent.new)
end
- assert_selector("div", text: "Outside /slots")
+ assert_selector("div", text: "Outside /slots (GET /)")
+ end
+
+ def test_with_request_url_specifying_method
+ with_request_url "/create", method: "POST" do
+ render_inline(CurrentPageComponent.new)
+ end
+
+ assert_selector("div", text: "Outside /slots (POST /create)")
end
def test_with_request_url_under_constraint
From 00cdde88e7b9d45e557edd70fd4839b32276a744 Mon Sep 17 00:00:00 2001
From: Reegan Viljoen <62689748+reeganviljoen@users.noreply.github.com>
Date: Tue, 7 Nov 2023 21:22:01 +0200
Subject: [PATCH 7/8] Don't add ActionDispatch::Static middleware continued
(#1892)
* Don't add ActionDispatch::Static middleware
In the case that rails do not serve static files is not
necessary to add ActionDispatch::Static middleware. Making
possible to deploy ViewComponenets previews on a production
environment where Nginx or Apache is managing the static files.
* Apply suggestions from code review
Co-authored-by: Joel Hawksley
* Update index.md
* add: prism cdn if no asset precompiler found
* edit: change prism cdn version to 1.28
* Update app/helpers/preview_helper.rb
Co-authored-by: Cameron Dutro
* Update app/helpers/preview_helper.rb
Co-authored-by: Cameron Dutro
* Update app/helpers/preview_helper.rb
Co-authored-by: Cameron Dutro
* Update app/helpers/preview_helper.rb
Co-authored-by: Cameron Dutro
* Update lib/view_component/engine.rb
Co-authored-by: Cameron Dutro
* edit: fix brocken tests
* edit: refactor tests
* edit: fix for rails > 6.1
* edit: fix lint issues
* Update lib/view_component/engine.rb
Co-authored-by: Hans Lemuet
---------
Co-authored-by: Daniel Gonzalez
Co-authored-by: Joel Hawksley
Co-authored-by: Cameron Dutro
Co-authored-by: Hans Lemuet
---
app/helpers/preview_helper.rb | 14 ++++++++
.../view_components/_preview_source.html.erb | 4 +--
docs/CHANGELOG.md | 5 +++
docs/index.md | 1 +
lib/view_component/engine.rb | 6 +++-
test/sandbox/test/preview_helper_test.rb | 32 +++++++++++++++++++
test/view_component/engine_test.rb | 10 ++++++
7 files changed, 69 insertions(+), 3 deletions(-)
create mode 100644 test/view_component/engine_test.rb
diff --git a/app/helpers/preview_helper.rb b/app/helpers/preview_helper.rb
index 0485b47751..222334985e 100644
--- a/app/helpers/preview_helper.rb
+++ b/app/helpers/preview_helper.rb
@@ -1,6 +1,8 @@
# frozen_string_literal: true
module PreviewHelper
+ include ActionView::Helpers::AssetUrlHelper if Rails.version.to_f < 6.1
+
AVAILABLE_PRISM_LANGUAGES = %w[ruby erb haml]
FALLBACK_LANGUAGE = "ruby"
@@ -10,6 +12,14 @@ def preview_source
render "preview_source"
end
+ def prism_css_source_url
+ serve_static_preview_assets? ? asset_path("prism.css", skip_pipeline: true) : "https://cdn.jsdelivr.net/npm/prismjs@1.28.0/themes/prism.min.css"
+ end
+
+ def prism_js_source_url
+ serve_static_preview_assets? ? asset_path("prism.min.js", skip_pipeline: true) : "https://cdn.jsdelivr.net/npm/prismjs@1.28.0/prism.min.js"
+ end
+
def find_template_data(lookup_context:, template_identifier:)
template = lookup_context.find_template(template_identifier)
@@ -62,4 +72,8 @@ def prism_language_name_by_template_path(template_file_path:)
language
end
+
+ def serve_static_preview_assets?
+ ViewComponent::Base.config.show_previews && Rails.application.config.public_file_server.enabled
+ end
end
diff --git a/app/views/view_components/_preview_source.html.erb b/app/views/view_components/_preview_source.html.erb
index f1259f291e..606b8ac80a 100644
--- a/app/views/view_components/_preview_source.html.erb
+++ b/app/views/view_components/_preview_source.html.erb
@@ -1,4 +1,4 @@
-
+
Source:
@@ -14,4 +14,4 @@
<% end %>
-
+
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index ffd121035f..b66e6ec701 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -10,6 +10,11 @@ nav_order: 5
## main
+* Don't add ActionDispatch::Static middleware unless `public_file_server.enabled`.
+
+ *Daniel Gonzalez*
+ *Reegan Viljoen*
+
* Resolve an issue where slots starting with `call` would cause a `NameError`
*Blake Williams*
diff --git a/docs/index.md b/docs/index.md
index b20009efdb..24f750a5c6 100644
--- a/docs/index.md
+++ b/docs/index.md
@@ -204,6 +204,7 @@ ViewComponent is built by over a hundred members of the community, including:
+
diff --git a/lib/view_component/engine.rb b/lib/view_component/engine.rb
index 7c3740bceb..47618fe261 100644
--- a/lib/view_component/engine.rb
+++ b/lib/view_component/engine.rb
@@ -110,11 +110,15 @@ class Engine < Rails::Engine # :nodoc:
end
initializer "static assets" do |app|
- if app.config.view_component.show_previews
+ if serve_static_preview_assets?(app.config)
app.middleware.use(::ActionDispatch::Static, "#{root}/app/assets/vendor")
end
end
+ def serve_static_preview_assets?(app_config)
+ app_config.view_component.show_previews && app_config.public_file_server.enabled
+ end
+
initializer "compiler mode" do |_app|
ViewComponent::Compiler.mode = if Rails.env.development? || Rails.env.test?
ViewComponent::Compiler::DEVELOPMENT_MODE
diff --git a/test/sandbox/test/preview_helper_test.rb b/test/sandbox/test/preview_helper_test.rb
index 108a8a71dd..5921a525d1 100644
--- a/test/sandbox/test/preview_helper_test.rb
+++ b/test/sandbox/test/preview_helper_test.rb
@@ -155,5 +155,37 @@ def test_raises_with_conflict_in_template_resolution
assert_equal("Found multiple templates for #{template_identifier}.", exception.message)
end
end
+
+ def test_prism_css_source_url_with_asset_pipeline
+ Rails.application.config.public_file_server.stub(:enabled, true) do
+ if Rails.version.to_f >= 6.1
+ assert_equal "/assets/prism.css", PreviewHelper.prism_css_source_url
+ else
+ assert_equal "/prism.css", PreviewHelper.prism_css_source_url
+ end
+ end
+ end
+
+ def test_prism_css_source_url_with_no_asset_pipeline
+ Rails.application.config.public_file_server.stub(:enabled, false) do
+ assert_equal "https://cdn.jsdelivr.net/npm/prismjs@1.28.0/themes/prism.min.css", PreviewHelper.prism_css_source_url
+ end
+ end
+
+ def test_prism_js_source_with_asset_pipeline
+ Rails.application.config.public_file_server.stub(:enabled, true) do
+ if Rails.version.to_f >= 6.1
+ assert_equal "/assets/prism.min.js", PreviewHelper.prism_js_source_url
+ else
+ assert_equal "/prism.min.js", PreviewHelper.prism_js_source_url
+ end
+ end
+ end
+
+ def test_prism_js_source_url_with_no_asset_pipeline
+ Rails.application.config.public_file_server.stub(:enabled, false) do
+ assert_equal "https://cdn.jsdelivr.net/npm/prismjs@1.28.0/prism.min.js", PreviewHelper.prism_js_source_url
+ end
+ end
end
end
diff --git a/test/view_component/engine_test.rb b/test/view_component/engine_test.rb
new file mode 100644
index 0000000000..5c5c037260
--- /dev/null
+++ b/test/view_component/engine_test.rb
@@ -0,0 +1,10 @@
+# frozen_string_literal: true
+
+require "test_helper"
+
+class ViewComponent::EngineTest < ActionDispatch::IntegrationTest
+ def test_serve_static_previews?
+ app.config.public_file_server.enabled = false
+ refute ViewComponent::Engine.instance.serve_static_preview_assets?(app.config)
+ end
+end
From 0820ce829b0519bbc1573df6001a36750d322e2d Mon Sep 17 00:00:00 2001
From: halo
Date: Wed, 8 Nov 2023 21:40:58 +0100
Subject: [PATCH 8/8] Use native String#end_with?, not the Rails wrapper
(#1905)
There is technically no need to depend on this core extension:
https://github.com/rails/rails/blob/939fd3bc41bbb90194e4b93a001c803bdceb592c/activesupport/lib/active_support/core_ext/string/starts_ends_with.rb
---
docs/CHANGELOG.md | 4 ++++
lib/view_component/slotable.rb | 2 +-
2 files changed, 5 insertions(+), 1 deletion(-)
diff --git a/docs/CHANGELOG.md b/docs/CHANGELOG.md
index b66e6ec701..236db227e5 100644
--- a/docs/CHANGELOG.md
+++ b/docs/CHANGELOG.md
@@ -10,6 +10,10 @@ nav_order: 5
## main
+* Replace usage of `String#ends_with?` with `String#end_with?` to reduce the dependency on ActiveSupport core extensions.
+
+ *halo*
+
* Don't add ActionDispatch::Static middleware unless `public_file_server.enabled`.
*Daniel Gonzalez*
diff --git a/lib/view_component/slotable.rb b/lib/view_component/slotable.rb
index d46094b3cf..b38ab3100f 100644
--- a/lib/view_component/slotable.rb
+++ b/lib/view_component/slotable.rb
@@ -322,7 +322,7 @@ def raise_if_slot_registered(slot_name)
end
def raise_if_slot_ends_with_question_mark(slot_name)
- raise SlotPredicateNameError.new(name, slot_name) if slot_name.to_s.ends_with?("?")
+ raise SlotPredicateNameError.new(name, slot_name) if slot_name.to_s.end_with?("?")
end
def raise_if_slot_conflicts_with_call(slot_name)