Class: ViewComponent::Base
- Inherits:
-
ActionView::Base
- Object
- ActionView::Base
- ViewComponent::Base
show all
- Includes:
- ActiveSupport::Configurable, Previewable
- Defined in:
- lib/view_component/base.rb
Class Method Summary
collapse
Instance Method Summary
collapse
Constructor Details
#initialize ⇒ Base
Returns a new instance of Base.
74
|
# File 'lib/view_component/base.rb', line 74
def initialize(*); end
|
Class Method Details
.call_method_name(variant) ⇒ Object
142
143
144
145
146
147
148
|
# File 'lib/view_component/base.rb', line 142
def call_method_name(variant)
if variant.present? && variants.include?(variant)
"call_#{variant}"
else
"call"
end
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.
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
|
# File 'lib/view_component/base.rb', line 175
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
168
169
170
|
# File 'lib/view_component/base.rb', line 168
def compile!
compile(raise_template_errors: true)
end
|
.compiled? ⇒ Boolean
160
161
162
|
# File 'lib/view_component/base.rb', line 160
def compiled?
@compiled && ActionView::Base.cache_template_loading
end
|
.identifier ⇒ Object
204
205
206
|
# File 'lib/view_component/base.rb', line 204
def identifier
source_location
end
|
.inherited(child) ⇒ Object
134
135
136
137
138
139
140
|
# File 'lib/view_component/base.rb', line 134
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
164
165
166
|
# File 'lib/view_component/base.rb', line 164
def inlined?
instance_methods(false).grep(/^call/).present? && templates.empty?
end
|
.source_location ⇒ Object
150
151
152
153
154
155
156
157
158
|
# File 'lib/view_component/base.rb', line 150
def source_location
@source_location ||=
begin
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
200
201
202
|
# File 'lib/view_component/base.rb', line 200
def type
"text/html"
end
|
.variants ⇒ Object
195
196
197
|
# File 'lib/view_component/base.rb', line 195
def variants
templates.map { |template| template[:variant] }
end
|
.with_content_areas(*areas) ⇒ Object
208
209
210
211
212
213
214
|
# File 'lib/view_component/base.rb', line 208
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
66
67
68
|
# File 'lib/view_component/base.rb', line 66
def before_render_check
end
|
#controller ⇒ Object
84
85
86
|
# File 'lib/view_component/base.rb', line 84
def controller
@controller ||= view_context.controller
end
|
102
103
104
|
# File 'lib/view_component/base.rb', line 102
def format @variant
end
|
#helpers ⇒ Object
Provides a proxy to access helper methods through
89
90
91
|
# File 'lib/view_component/base.rb', line 89
def helpers
@helpers ||= view_context
end
|
#render(options = {}, args = {}, &block) ⇒ Object
76
77
78
79
80
81
82
|
# File 'lib/view_component/base.rb', line 76
def render(options = {}, args = {}, &block)
if options.is_a?(String) || (options.is_a?(Hash) && options.has_key?(:partial))
view_context.render(options, args, &block)
else
super
end
end
|
#render? ⇒ Boolean
70
71
72
|
# File 'lib/view_component/base.rb', line 70
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>
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
|
# File 'lib/view_component/base.rb', line 41
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
98
99
100
|
# File 'lib/view_component/base.rb', line 98
def view_cache_dependencies
[]
end
|
#virtual_path ⇒ Object
Removes the first part of the path and the extension.
94
95
96
|
# File 'lib/view_component/base.rb', line 94
def virtual_path
self.class.source_location.gsub(%r{(.*app/components)|(\.rb)}, "")
end
|
#with(area, content = nil, &block) ⇒ Object
106
107
108
109
110
111
112
113
114
115
116
117
|
# File 'lib/view_component/base.rb', line 106
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
|