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(validate: false) ⇒ Object
Compile templates to instance methods, assuming they haven’t been compiled already.
- .compile! ⇒ Object
- .compiled? ⇒ Boolean
- .identifier ⇒ Object
- .inherited(child) ⇒ Object
- .source_location ⇒ Object
-
.type ⇒ Object
we’ll eventually want to update this to support other types.
- .variants ⇒ Object
- .with_content_areas(*areas) ⇒ 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? ⇒ Boolean
-
#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.
- #with(area, content = nil, &block) ⇒ Object
Constructor Details
#initialize ⇒ Base
Returns a new instance of Base.
69 |
# File 'lib/action_view/component/base.rb', line 69 def initialize(*); end |
Class Method Details
.call_method_name(variant) ⇒ Object
135 136 137 138 139 140 141 |
# File 'lib/action_view/component/base.rb', line 135 def call_method_name(variant) if variant.present? && variants.include?(variant) "call_#{variant}" else "call" end end |
.compile(validate: 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.
166 167 168 169 170 171 172 173 174 175 176 177 178 179 180 181 182 183 184 |
# File 'lib/action_view/component/base.rb', line 166 def compile(validate: false) return if compiled? if template_errors.present? raise ActionView::Component::TemplateError.new(template_errors) if validate return false end templates.each do |template| class_eval <<-RUBY, __FILE__, __LINE__ + 1 def #{call_method_name(template[:variant])} @output_buffer = ActionView::OutputBuffer.new #{compiled_template(template[:path])} end RUBY end @compiled = true end |
.compile! ⇒ Object
159 160 161 |
# File 'lib/action_view/component/base.rb', line 159 def compile! compile(validate: true) end |
.compiled? ⇒ Boolean
155 156 157 |
# File 'lib/action_view/component/base.rb', line 155 def compiled? @compiled && ActionView::Base.cache_template_loading end |
.identifier ⇒ Object
195 196 197 |
# File 'lib/action_view/component/base.rb', line 195 def identifier source_location end |
.inherited(child) ⇒ Object
129 130 131 132 133 |
# File 'lib/action_view/component/base.rb', line 129 def inherited(child) child.include Rails.application.routes.url_helpers unless child < Rails.application.routes.url_helpers super end |
.source_location ⇒ Object
143 144 145 146 147 148 149 150 151 152 153 |
# File 'lib/action_view/component/base.rb', line 143 def source_location @source_location ||= if const_source_location_supported? const_source_location(self.name)[0] else # 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
191 192 193 |
# File 'lib/action_view/component/base.rb', line 191 def type "text/html" end |
.variants ⇒ Object
186 187 188 |
# File 'lib/action_view/component/base.rb', line 186 def variants templates.map { |template| template[:variant] } end |
.with_content_areas(*areas) ⇒ Object
199 200 201 202 203 204 205 |
# File 'lib/action_view/component/base.rb', line 199 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
#controller ⇒ Object
79 80 81 |
# File 'lib/action_view/component/base.rb', line 79 def controller @controller ||= view_context.controller end |
#format ⇒ Object
:nodoc:
97 98 99 |
# File 'lib/action_view/component/base.rb', line 97 def format # :nodoc: @variant end |
#helpers ⇒ Object
Provides a proxy to access helper methods through
84 85 86 |
# File 'lib/action_view/component/base.rb', line 84 def helpers @helpers ||= view_context end |
#render(options = {}, args = {}, &block) ⇒ Object
71 72 73 74 75 76 77 |
# File 'lib/action_view/component/base.rb', line 71 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
65 66 67 |
# File 'lib/action_view/component/base.rb', line 65 def render? true 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>
42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/action_view/component/base.rb', line 42 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(self, &block) if block_given? validate! return "" unless render? send(self.class.call_method_name(@variant)) ensure @current_template = old_current_template end |
#view_cache_dependencies ⇒ Object
93 94 95 |
# File 'lib/action_view/component/base.rb', line 93 def view_cache_dependencies [] end |
#virtual_path ⇒ Object
Removes the first part of the path and the extension.
89 90 91 |
# File 'lib/action_view/component/base.rb', line 89 def virtual_path self.class.source_location.gsub(%r{(.*app/components)|(\.rb)}, "") end |
#with(area, content = nil, &block) ⇒ Object
101 102 103 104 105 106 107 108 109 110 111 112 |
# File 'lib/action_view/component/base.rb', line 101 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 |