Skip to content

Commit

Permalink
Add distinct GeneratedSlotMethods module to ViewComponents and define…
Browse files Browse the repository at this point in the history
… `#{slot}` and `#{slot?}` methods on this module, allowing these methods to be overridden with access to `super` implementation.
  • Loading branch information
ozydingo committed Aug 24, 2024
1 parent e10551e commit 90598cf
Show file tree
Hide file tree
Showing 7 changed files with 99 additions and 16 deletions.
4 changes: 4 additions & 0 deletions docs/CHANGELOG.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,10 @@ nav_order: 5

## main

* Allow overridden slot methods to use `super` to call the standard implementation.

*Andrew Schwartz*

* Defer to built-in caching for language environment setup, rather than manually using `actions/cache` in CI.

*Simon Fish*
Expand Down
17 changes: 9 additions & 8 deletions docs/CONTRIBUTING.md
Original file line number Diff line number Diff line change
Expand Up @@ -42,14 +42,15 @@ The codespace environment includes a minimal Rails app with ViewComponent instal
## Submitting a pull request

1. [Fork](https://github.com/viewcomponent/view_component/fork) and clone the repository.
1. Configure and install the dependencies: `bundle exec appraisal install`.
2. Make sure the tests pass: `bundle exec appraisal rake` (see below for specific cases).
3. Create a new branch: `git checkout -b my-branch-name`.
4. Add tests, make the change, and make sure the tests still pass.
5. Add an entry to the top of `docs/CHANGELOG.md` for the changes, no matter how small.
6. If it's your first time contributing, add yourself to `docs/index.md`.
7. Push to the fork and [submit a pull request](https://github.com/viewcomponent/view_component/compare).
8. Wait for the pull request to be reviewed and merged.
1. Configure and install local dependencies: `bundle install`.
1. Configure and install testing dependencies: `bundle exec appraisal install`.
1. Make sure the tests pass: `bundle exec appraisal rake` (see below for specific cases).
1. Create a new branch: `git checkout -b my-branch-name`.
1. Add tests, make the change, and make sure the tests still pass.
1. Add an entry to the top of `docs/CHANGELOG.md` for the changes, no matter how small.
1. If it's your first time contributing, add yourself to `docs/index.md`.
1. Push to the fork and [submit a pull request](https://github.com/viewcomponent/view_component/compare).
1. Wait for the pull request to be reviewed and merged.

### Running a subset of tests

Expand Down
1 change: 1 addition & 0 deletions docs/index.md
Original file line number Diff line number Diff line change
Expand Up @@ -182,6 +182,7 @@ ViewComponent is built by over a hundred members of the community, including:
<img src="https://avatars.githubusercontent.com/nicolas-brousse?s=64" alt="nicolas-brousse" width="32" />
<img src="https://avatars.githubusercontent.com/nielsslot?s=64" alt="nshki" width="32" />
<img src="https://avatars.githubusercontent.com/nshki?s=64" alt="nshki" width="32" />
<img src="https://avatars.githubusercontent.com/ozydingo?s=64" alt="ozydingo" width="32" />
<img src="https://avatars.githubusercontent.com/patrickarnett?s=64" alt="patrickarnett" width="32" />
<img src="https://avatars.githubusercontent.com/rainerborene?s=64" alt="rainerborene" width="32" />
<img src="https://avatars.githubusercontent.com/rdavid1099?s=64" alt="rdavid1099" width="32" />
Expand Down
25 changes: 17 additions & 8 deletions lib/view_component/slotable.rb
Original file line number Diff line number Diff line change
Expand Up @@ -89,11 +89,11 @@ def renders_one(slot_name, callable = nil)
end
ruby2_keywords(setter_method_name) if respond_to?(:ruby2_keywords, true)

define_method slot_name do
self::GeneratedSlotMethods.define_method slot_name do
get_slot(slot_name)
end

define_method :"#{slot_name}?" do
self::GeneratedSlotMethods.define_method :"#{slot_name}?" do
get_slot(slot_name).present?
end

Expand Down Expand Up @@ -176,11 +176,11 @@ def renders_many(slot_name, callable = nil)
end
end

define_method slot_name do
self::GeneratedSlotMethods.define_method slot_name do
get_slot(slot_name)
end

define_method :"#{slot_name}?" do
self::GeneratedSlotMethods.define_method :"#{slot_name}?" do
get_slot(slot_name).present?
end

Expand All @@ -199,19 +199,28 @@ def slot_type(slot_name)
end
end

# Clone slot configuration into child class
# see #test_slots_pollution
def inherited(child)
# Clone slot configuration into child class
# see #test_slots_pollution
child.registered_slots = registered_slots.clone

# Add a module for slot methods, allowing them to be overriden by the component class
# see #test_slot_name_can_be_overriden
unless child.const_defined?(:GeneratedSlotMethods, false)
generated_slot_methods = Module.new
child.const_set(:GeneratedSlotMethods, generated_slot_methods)
child.include generated_slot_methods
end

super
end

def register_polymorphic_slot(slot_name, types, collection:)
define_method(slot_name) do
self::GeneratedSlotMethods.define_method(slot_name) do
get_slot(slot_name)
end

define_method(:"#{slot_name}?") do
self::GeneratedSlotMethods.define_method(:"#{slot_name}?") do
get_slot(slot_name).present?
end

Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
<div class="card <%= @classes %>">
<% if title? %>
<div class="title">
<%= title %>
</div>
<% end %>
</div>
27 changes: 27 additions & 0 deletions test/sandbox/app/components/slot_name_override_component.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,27 @@
# frozen_string_literal: true

class SlotNameOverrideComponent < ViewComponent::Base
renders_one :title

def initialize(title: nil)
@title = title
end

def title
@title || super
end

def title?
@title.present? || super
end
end

class SlotNameOverrideComponent::OtherComponent < ViewComponent::Base
renders_one :title
end

class SlotNameOverrideComponent::SubComponent < SlotNameOverrideComponent
def title
super.upcase
end
end
34 changes: 34 additions & 0 deletions test/sandbox/test/slotable_test.rb
Original file line number Diff line number Diff line change
Expand Up @@ -785,4 +785,38 @@ def test_slotable_default_instance

assert_text "hello,world!", count: 1
end

def test_slot_name_can_be_overriden
# Uses overridden `title` slot method
render_inline(SlotNameOverrideComponent.new(title: "Simple Title"))

assert_selector(".title", text: "Simple Title")
end

def test_slot_name_override_can_use_super
# Uses standard `title` slot method via `super`
render_inline(SlotNameOverrideComponent.new) do |component|
component.with_title do
"Block Title with More Complexity"
end
end

assert_selector(".title", text: "Block Title with More Complexity")
end

def overriden_slot_name_predicate_returns_false_when_not_set
render_inline(SlotNameOverrideComponent.new)

refute_selector(".title")
end

def test_overridden_slot_name_can_be_inherited
render_inline(SlotNameOverrideComponent::SubComponent.new(title: "lowercase"))

assert_selector(".title", text: "LOWERCASE")
end

def test_slot_name_methods_are_not_shared_accross_components
assert_not_equal SlotsComponent.instance_method(:title).owner, SlotNameOverrideComponent::OtherComponent.instance_method(:title).owner
end
end

0 comments on commit 90598cf

Please sign in to comment.