Class: ActionView::Component::Base
- Inherits:
-
Base
- Object
- Base
- ActionView::Component::Base
- Includes:
- Previewable, ActiveModel::Validations, ActiveSupport::Configurable
- Defined in:
- lib/action_view/component/base.rb
Class Method Summary collapse
- .call_method_name(variant) ⇒ Object
-
.compile ⇒ Object
Compile templates to instance methods, assuming they haven’t been compiled already.
- .compiled? ⇒ Boolean
- .has_initializer? ⇒ Boolean
- .identifier ⇒ Object
- .inherited(child) ⇒ Object
- .source_location ⇒ Object
-
.type ⇒ Object
we’ll eventually want to update this to support other types.
- .variants ⇒ Object
Instance Method Summary collapse
- #controller ⇒ Object
-
#format ⇒ Object
:nodoc:.
-
#helpers ⇒ Object
Provides a proxy to access helper methods through.
-
#initialize ⇒ Base
constructor
A new instance of Base.
- #render(options = {}, args = {}, &block) ⇒ Object
-
#render_in(view_context, *args, &block) ⇒ Object
Entrypoint for rendering components.
- #view_cache_dependencies ⇒ Object
-
#virtual_path ⇒ Object
Removes the first part of the path and the extension.
Constructor Details
#initialize ⇒ Base
Returns a new instance of Base.
58 |
# File 'lib/action_view/component/base.rb', line 58 def initialize(*); end |
Class Method Details
.call_method_name(variant) ⇒ Object
105 106 107 108 109 110 111 |
# File 'lib/action_view/component/base.rb', line 105 def call_method_name(variant) if variant.present? && variants.include?(variant) "call_#{variant}" else "call" end end |
.compile ⇒ Object
Compile templates to instance methods, assuming they haven’t been compiled already. We could in theory do this on app boot, at least in production environments. Right now this just compiles the first time the component is rendered.
137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 |
# File 'lib/action_view/component/base.rb', line 137 def compile return if compiled? validate_templates templates.each do |template| class_eval " def \#{call_method_name(template[:variant])}\n @output_buffer = ActionView::OutputBuffer.new\n \#{compiled_template(template[:path])}\n end\n RUBY\n end\n\n @compiled = true\nend\n", __FILE__, __LINE__ + 1 |
.compiled? ⇒ Boolean
130 131 132 |
# File 'lib/action_view/component/base.rb', line 130 def compiled? @compiled && ActionView::Base.cache_template_loading end |
.has_initializer? ⇒ Boolean
113 114 115 |
# File 'lib/action_view/component/base.rb', line 113 def has_initializer? self.instance_method(:initialize).owner == self end |
.identifier ⇒ Object
163 164 165 |
# File 'lib/action_view/component/base.rb', line 163 def identifier source_location end |
.inherited(child) ⇒ Object
99 100 101 102 103 |
# File 'lib/action_view/component/base.rb', line 99 def inherited(child) child.include Rails.application.routes.url_helpers unless child < Rails.application.routes.url_helpers super end |
.source_location ⇒ Object
117 118 119 120 121 122 123 124 125 126 127 128 |
# File 'lib/action_view/component/base.rb', line 117 def source_location # Require #initialize to be defined so that we can use # method#source_location to look up the file name # of the component. # # If we were able to only support Ruby 2.7+, # We could just use Module#const_source_location, # rendering this unnecessary. raise NotImplementedError.new("#{self} must implement #initialize.") unless has_initializer? instance_method(:initialize).source_location[0] end |
.type ⇒ Object
we’ll eventually want to update this to support other types
159 160 161 |
# File 'lib/action_view/component/base.rb', line 159 def type "text/html" end |
.variants ⇒ Object
154 155 156 |
# File 'lib/action_view/component/base.rb', line 154 def variants templates.map { |template| template[:variant] } end |
Instance Method Details
#controller ⇒ Object
68 69 70 |
# File 'lib/action_view/component/base.rb', line 68 def controller @controller ||= view_context.controller end |
#format ⇒ Object
:nodoc:
86 87 88 |
# File 'lib/action_view/component/base.rb', line 86 def format # :nodoc: @variant end |
#helpers ⇒ Object
Provides a proxy to access helper methods through
73 74 75 |
# File 'lib/action_view/component/base.rb', line 73 def helpers @helpers ||= view_context end |
#render(options = {}, args = {}, &block) ⇒ Object
60 61 62 63 64 65 66 |
# File 'lib/action_view/component/base.rb', line 60 def render( = {}, args = {}, &block) if .is_a?(String) || (.is_a?(Hash) && .has_key?(:partial)) view_context.render(, args, &block) else super end end |
#render_in(view_context, *args, &block) ⇒ Object
Entrypoint for rendering components. Called by ActionView::Base#render.
view_context: ActionView context from calling view args(hash): params to be passed to component being rendered block: optional block to be captured within the view context
returns HTML that has been escaped by the respective template handler
Example subclass:
app/components/my_component.rb: class MyComponent < ActionView::Component::Base
def initialize(title:)
@title = title
end
end
app/components/my_component.html.erb <span title=“<%= @title %>”>Hello, <%= content %>!</span>
In use: <%= render MyComponent, title: “greeting” do %>world<% end %> returns: <span title=“greeting”>Hello, world!</span>
39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 |
# File 'lib/action_view/component/base.rb', line 39 def render_in(view_context, *args, &block) self.class.compile @view_context = view_context @view_renderer ||= view_context.view_renderer @lookup_context ||= view_context.lookup_context @view_flow ||= view_context.view_flow @virtual_path ||= virtual_path @variant = @lookup_context.variants.first old_current_template = @current_template @current_template = self @content = view_context.capture(&block) if block_given? validate! send(self.class.call_method_name(@variant)) ensure @current_template = old_current_template end |
#view_cache_dependencies ⇒ Object
82 83 84 |
# File 'lib/action_view/component/base.rb', line 82 def view_cache_dependencies [] end |
#virtual_path ⇒ Object
Removes the first part of the path and the extension.
78 79 80 |
# File 'lib/action_view/component/base.rb', line 78 def virtual_path self.class.source_location.gsub(%r{(.*app/components)|(\.rb)}, "") end |