Skip to content

Commit

Permalink
Auto-inject dependencies into components
Browse files Browse the repository at this point in the history
By using dry-system's auto_inject feature, we can get rid of the
boilerplate code that injects dependencies into components.

We create a `SolidusAdmin::Import` constant that can be used to dynamically
create a module that gets included into a component. This module will
provide instance methods to fetch the declared dependencies from the
component.

We also register a top level `main_nav_items` dependency to avoid
calling a private in nature `.within_namespace` method.

[1] - https://dry-rb.org/gems/dry-system/1.0/dependency-auto-injection/
  • Loading branch information
waiting-for-dev committed Jun 5, 2023
1 parent 8150c02 commit 5dbf45b
Show file tree
Hide file tree
Showing 5 changed files with 21 additions and 7 deletions.
2 changes: 2 additions & 0 deletions admin/app/components/solidus_admin/base_component.rb
Original file line number Diff line number Diff line change
@@ -1,5 +1,7 @@
# frozen_string_literal: true

require "solidus_admin/system/import"

module SolidusAdmin
# BaseComponent is the base class for all components in Solidus Admin.
class BaseComponent < ViewComponent::Base
Expand Down
13 changes: 6 additions & 7 deletions admin/app/components/solidus_admin/main_nav_component.rb
Original file line number Diff line number Diff line change
Expand Up @@ -3,16 +3,15 @@
module SolidusAdmin
# Renders the main navigation of Solidus Admin.
class MainNavComponent < BaseComponent
def initialize(main_nav_item_component: component("main_nav_item"), items: container.within_namespace("main_nav"))
@main_nav_item_component = main_nav_item_component
@items = items
super
end
include Import[
"main_nav_item_component",
items: "main_nav_items"
]

erb_template <<~ERB
<nav>
<%=
render @main_nav_item_component.with_collection(
render main_nav_item_component.with_collection(
sorted_items
)
%>
Expand All @@ -22,7 +21,7 @@ def initialize(main_nav_item_component: component("main_nav_item"), items: conta
private

def sorted_items
@items.sort_by(&:position)
items.sort_by(&:position)
end
end
end
2 changes: 2 additions & 0 deletions admin/lib/solidus_admin/container.rb
Original file line number Diff line number Diff line change
Expand Up @@ -23,6 +23,8 @@ class Container < Dry::System::Container
end

# Returns all the registered components for a given namespace.
#
# @api private
def self.within_namespace(namespace)
keys.filter_map do
_1.start_with?("#{namespace}#{config.namespace_separator}") && resolve(_1)
Expand Down
7 changes: 7 additions & 0 deletions admin/lib/solidus_admin/system/import.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
# frozen_string_literal: true

require "solidus_admin/container"

module SolidusAdmin
Import = Container.injector
end
4 changes: 4 additions & 0 deletions admin/lib/solidus_admin/system/providers/main_nav.rb
Original file line number Diff line number Diff line change
Expand Up @@ -12,6 +12,10 @@ module Providers
register("second_item", MainNavItem.new(title: "Second item", position: "20"))
register("third_item", MainNavItem.new(title: "Third item", position: "30"))
end

container.register("main_nav_items") do
Container.within_namespace("main_nav")
end
end
end
end
Expand Down

0 comments on commit 5dbf45b

Please sign in to comment.