Class: ViewComponent::Base
- Inherits:
-
ActionView::Base
- Object
- ActionView::Base
- ViewComponent::Base
- Includes:
- ActiveSupport::Configurable, Previewable
- Defined in:
- lib/view_component/base.rb
Class Method Summary collapse
- .call_method_name(variant) ⇒ Object
- .collection_parameter_name ⇒ Object
-
.compile(raise_template_errors: false) ⇒ Object
Compile templates to instance methods, assuming they haven’t been compiled already.
- .compile! ⇒ Object
- .compiled? ⇒ Boolean
- .identifier ⇒ Object
- .inherited(child) ⇒ Object
- .inlined? ⇒ Boolean
- .source_location ⇒ Object
-
.type ⇒ Object
we’ll eventually want to update this to support other types.
- .variants ⇒ Object
-
.with_collection(*args) ⇒ Object
Render a component collection.
-
.with_collection_parameter(param) ⇒ Object
Support overriding this component’s collection parameter name.
- .with_content_areas(*areas) ⇒ Object
Instance Method Summary collapse
- #before_render_check ⇒ Object
- #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? ⇒ Boolean
-
#render_in(view_context, &block) ⇒ Object
Entrypoint for rendering components.
- #view_cache_dependencies ⇒ Object
-
#virtual_path ⇒ Object
Removes the first part of the path and the extension.
- #with(area, content = nil, &block) ⇒ Object
Constructor Details
#initialize ⇒ Base
Returns a new instance of Base.
80 |
# File 'lib/view_component/base.rb', line 80 def initialize(*); end |
Class Method Details
.call_method_name(variant) ⇒ Object
148 149 150 151 152 153 154 |
# File 'lib/view_component/base.rb', line 148 def call_method_name(variant) if variant.present? && variants.include?(variant) "call_#{variant}" else "call" end end |
.collection_parameter_name ⇒ Object
227 228 229 |
# File 'lib/view_component/base.rb', line 227 def collection_parameter_name (@with_collection_parameter || name.demodulize.underscore.chomp("_component")).to_sym end |
.compile(raise_template_errors: false) ⇒ 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.
181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 |
# File 'lib/view_component/base.rb', line 181 def compile(raise_template_errors: false) return if compiled? || inlined? if template_errors.present? raise ViewComponent::TemplateError.new(template_errors) if raise_template_errors return false end templates.each do |template| class_eval <<-RUBY, template[:path], -1 def #{call_method_name(template[:variant])} @output_buffer = ActionView::OutputBuffer.new #{compiled_template(template[:path])} end RUBY end @compiled = true end |
.compile! ⇒ Object
174 175 176 |
# File 'lib/view_component/base.rb', line 174 def compile! compile(raise_template_errors: true) end |
.compiled? ⇒ Boolean
166 167 168 |
# File 'lib/view_component/base.rb', line 166 def compiled? @compiled && ActionView::Base.cache_template_loading end |
.identifier ⇒ Object
210 211 212 |
# File 'lib/view_component/base.rb', line 210 def identifier source_location end |
.inherited(child) ⇒ Object
140 141 142 143 144 145 146 |
# File 'lib/view_component/base.rb', line 140 def inherited(child) if defined?(Rails) child.include Rails.application.routes.url_helpers unless child < Rails.application.routes.url_helpers end super end |
.inlined? ⇒ Boolean
170 171 172 |
# File 'lib/view_component/base.rb', line 170 def inlined? instance_methods(false).grep(/^call/).present? && templates.empty? end |
.source_location ⇒ Object
156 157 158 159 160 161 162 163 164 |
# File 'lib/view_component/base.rb', line 156 def source_location @source_location ||= begin # Require `#initialize` to be defined so that we can use `method#source_location` # to look up the filename of the component. initialize_method = instance_method(:initialize) initialize_method.source_location[0] if initialize_method.owner == self end end |
.type ⇒ Object
we’ll eventually want to update this to support other types
206 207 208 |
# File 'lib/view_component/base.rb', line 206 def type "text/html" end |
.variants ⇒ Object
201 202 203 |
# File 'lib/view_component/base.rb', line 201 def variants templates.map { |template| template[:variant] } end |
.with_collection(*args) ⇒ Object
Render a component collection.
19 20 21 |
# File 'lib/view_component/base.rb', line 19 def self.with_collection(*args) Collection.new(self, *args) end |
.with_collection_parameter(param) ⇒ Object
Support overriding this component’s collection parameter name
223 224 225 |
# File 'lib/view_component/base.rb', line 223 def with_collection_parameter(param) @with_collection_parameter = param end |
.with_content_areas(*areas) ⇒ Object
214 215 216 217 218 219 220 |
# File 'lib/view_component/base.rb', line 214 def with_content_areas(*areas) if areas.include?(:content) raise ArgumentError.new ":content is a reserved content area name. Please use another name, such as ':body'" end attr_reader *areas self.content_areas = areas end |
Instance Method Details
#before_render_check ⇒ Object
72 73 74 |
# File 'lib/view_component/base.rb', line 72 def before_render_check # noop end |
#controller ⇒ Object
90 91 92 |
# File 'lib/view_component/base.rb', line 90 def controller @controller ||= view_context.controller end |
#format ⇒ Object
:nodoc:
108 109 110 |
# File 'lib/view_component/base.rb', line 108 def format # :nodoc: @variant end |
#helpers ⇒ Object
Provides a proxy to access helper methods through
95 96 97 |
# File 'lib/view_component/base.rb', line 95 def helpers @helpers ||= view_context end |
#render(options = {}, args = {}, &block) ⇒ Object
82 83 84 85 86 87 88 |
# File 'lib/view_component/base.rb', line 82 def render( = {}, args = {}, &block) if .is_a?(String) || (.is_a?(Hash) && .has_key?(:partial)) view_context.render(, args, &block) else super end end |
#render? ⇒ Boolean
76 77 78 |
# File 'lib/view_component/base.rb', line 76 def render? true end |
#render_in(view_context, &block) ⇒ Object
Entrypoint for rendering components.
view_context: ActionView context from calling view 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 < ViewComponent::Base
def initialize(title:)
@title = title
end
end
app/components/my_component.html.erb <span title=“<%= @title %>”>Hello, <%= content %>!</span>
In use: <%= render MyComponent.new(title: “greeting”) do %>world<% end %> returns: <span title=“greeting”>Hello, world!</span>
47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 |
# File 'lib/view_component/base.rb', line 47 def render_in(view_context, &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(self, &block) if block_given? before_render_check if render? send(self.class.call_method_name(@variant)) else "" end ensure @current_template = old_current_template end |
#view_cache_dependencies ⇒ Object
104 105 106 |
# File 'lib/view_component/base.rb', line 104 def view_cache_dependencies [] end |
#virtual_path ⇒ Object
Removes the first part of the path and the extension.
100 101 102 |
# File 'lib/view_component/base.rb', line 100 def virtual_path self.class.source_location.gsub(%r{(.*app/components)|(\.rb)}, "") end |
#with(area, content = nil, &block) ⇒ Object
112 113 114 115 116 117 118 119 120 121 122 123 |
# File 'lib/view_component/base.rb', line 112 def with(area, content = nil, &block) unless content_areas.include?(area) raise ArgumentError.new "Unknown content_area '#{area}' - expected one of '#{content_areas}'" end if block_given? content = view_context.capture(&block) end instance_variable_set("@#{area}".to_sym, content) nil end |