Class: Curly::Presenter
- Inherits:
-
Object
- Object
- Curly::Presenter
- Defined in:
- lib/curly/presenter.rb
Overview
A base class that can be subclassed by concrete presenters.
A Curly presenter is responsible for delivering data to templates, in the form of simple strings. Each public instance method on the presenter class can be referenced in a template. When a template is evaluated with a presenter, the referenced methods will be called with no arguments, and the returned strings inserted in place of the components in the template.
Note that strings that are not HTML safe will be escaped.
A presenter is always instantiated with a context to which it delegates unknown messages, usually an instance of ActionView::Base provided by Rails. See Curly::TemplateHandler for a typical use.
Examples
class BlogPresenter < Curly::Presenter presents :post
def title
@post.title
end
def body
markdown(@post.body)
end
def
@post..full_name
end
end
presenter = BlogPresenter.new(context, post: post) presenter.author #=> "Jackie Chan"
Class Method Summary collapse
-
.available_components ⇒ Object
A list of components available to templates rendered with the presenter.
-
.cache_key ⇒ Object
The cache key for the presenter class.
-
.component_available?(name) ⇒ Boolean
Whether a component is available to templates rendered with the presenter.
-
.dependencies ⇒ Object
The set of view paths that the presenter depends on.
-
.depends_on(*dependencies) ⇒ Object
Indicate that the presenter depends a list of other views.
-
.presenter_for_name(name, namespace_prefixes = to_s.split('::')) ⇒ Object
Retrieve the named presenter with consideration for object scope.
-
.presenter_for_path(path) ⇒ Object
Returns the presenter class for the given path.
-
.presenter_name_for_path(path) ⇒ Object
The name of the presenter class for a given view path.
-
.version(version = nil) ⇒ Object
Get or set the version of the presenter.
Instance Method Summary collapse
-
#cache_duration ⇒ Object
The duration that the view should be cached for.
-
#cache_key ⇒ Object
The key that should be used to cache the view.
-
#cache_options ⇒ Object
The options that should be passed to the cache backend when caching the view.
-
#initialize(context, options = {}) ⇒ Presenter
constructor
Initializes the presenter with the given context and options.
-
#setup! ⇒ Object
Sets up the view.
Constructor Details
#initialize(context, options = {}) ⇒ Presenter
Initializes the presenter with the given context and options.
context - An ActionView::Base context. options - A Hash of options given to the presenter.
46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 |
# File 'lib/curly/presenter.rb', line 46 def initialize(context, = {}) @_context = context .stringify_keys! self.class.presented_names.each do |name| value = .fetch(name) do default_values.fetch(name) do block = default_blocks.fetch(name) do raise ArgumentError.new("required identifier `#{name}` missing") end instance_exec(name, &block) end end instance_variable_set("@#{name}", value) end end |
Dynamic Method Handling
This class handles dynamic methods through the method_missing method
#method_missing(method, *args, &block) ⇒ Object (private)
Delegates private method calls to the current view context.
The view context, an instance of ActionView::Base, is set by Rails.
344 345 346 |
# File 'lib/curly/presenter.rb', line 344 def method_missing(method, *args, &block) @_context.public_send(method, *args, &block) end |
Class Method Details
.available_components ⇒ Object
A list of components available to templates rendered with the presenter.
Returns an Array of String component names.
229 230 231 232 233 234 |
# File 'lib/curly/presenter.rb', line 229 def available_components @_available_components ||= begin methods = public_instance_methods - Curly::Presenter.public_instance_methods methods.map(&:to_s) end end |
.cache_key ⇒ Object
The cache key for the presenter class. Includes all dependencies as well.
Returns a String cache key.
282 283 284 |
# File 'lib/curly/presenter.rb', line 282 def cache_key @cache_key ||= compute_cache_key end |
.component_available?(name) ⇒ Boolean
Whether a component is available to templates rendered with the presenter.
Templates have components which correspond with methods defined on
the presenter. By default, only public instance methods can be
referenced, and any method defined on Curly::Presenter itself cannot be
referenced. This means that methods such as #cache_key
and #inspect
are not available. This is done for safety purposes.
This policy can be changed by overriding this method in your presenters.
name - The String name of the component.
Returns true if the method can be referenced by a template, false otherwise.
222 223 224 |
# File 'lib/curly/presenter.rb', line 222 def component_available?(name) available_components.include?(name) end |
.dependencies ⇒ Object
The set of view paths that the presenter depends on.
Examples
class Posts::ShowPresenter < Curly::Presenter version 2 depends_on 'posts/comment', 'posts/comment_form' end
Posts::ShowPresenter.dependencies #=> ['posts/comment', 'posts/comment_form']
Returns a Set of String view paths.
249 250 251 252 253 254 255 |
# File 'lib/curly/presenter.rb', line 249 def dependencies # The base presenter doesn't have any dependencies. return SortedSet.new if self == Curly::Presenter @dependencies ||= SortedSet.new @dependencies.union(superclass.dependencies) end |
.depends_on(*dependencies) ⇒ Object
Indicate that the presenter depends a list of other views.
deps - A list of String view paths that the presenter depends on.
Returns nothing.
262 263 264 265 |
# File 'lib/curly/presenter.rb', line 262 def depends_on(*dependencies) @dependencies ||= SortedSet.new @dependencies.merge(dependencies) end |
.presenter_for_name(name, namespace_prefixes = to_s.split('::')) ⇒ Object
Retrieve the named presenter with consideration for object scope. The namespace_prefixes are to acknowledge that sometimes we will have a subclass of Curly::Presenter receiving the .presenter_for_name and other times we will not (when we are receiving this message by way of the .presenter_for_path method).
173 174 175 176 177 178 179 180 181 182 183 184 185 186 187 188 189 190 191 192 193 194 195 196 197 198 199 200 201 202 203 204 205 |
# File 'lib/curly/presenter.rb', line 173 def presenter_for_name(name, namespace_prefixes = to_s.split('::')) full_class_name = name.camelcase << "Presenter" relative_namespace = full_class_name.split("::") class_name = relative_namespace.pop namespace = namespace_prefixes + relative_namespace # Because Rails' autoloading mechanism doesn't work properly with # namespace we need to loop through the namespace ourselves. Ideally, # `X::Y.const_get("Z")` would autoload `X::Z`, but only `X::Y::Z` is # attempted by Rails. This sucks, and hopefully we can find a better # solution in the future. begin full_name = namespace.join("::") << "::" << class_name full_name.constantize rescue NameError => e # Due to the way the exception hirearchy works, we need to check # that this exception is actually a `NameError` - since other # classes can inherit `NameError`, rescue will actually rescue # those classes as being under `NameError`, causing this block to # be executed for classes that aren't `NameError`s (but are rather # subclasses of it), which isn't the desired behavior. This # prevents anything but `NameError`s from triggering the resulting # code. `NoMethodError` is actually a subclass of `NameError`, # so a typo in a file (e.g. `present` instead of `presents`) can # cause the library to act as if the class was never defined. raise unless e.class == NameError if namespace.empty? raise Curly::PresenterNameError.new(e, name) end namespace.pop retry end end |
.presenter_for_path(path) ⇒ Object
Returns the presenter class for the given path.
path - The String path of a template.
Returns the Class or nil if the constant cannot be found.
158 159 160 161 162 163 164 165 166 |
# File 'lib/curly/presenter.rb', line 158 def presenter_for_path(path) begin # Assume that the path can be derived without a prefix; In other words # from the given path we can look up objects by namespace. presenter_for_name(path.camelize, []) rescue Curly::PresenterNameError nil end end |
.presenter_name_for_path(path) ⇒ Object
The name of the presenter class for a given view path.
path - The String path of a view.
Examples
Curly::TemplateHandler.presenter_name_for_path("foo/bar") #=> "Foo::BarPresenter"
Returns the String name of the matching presenter class.
149 150 151 |
# File 'lib/curly/presenter.rb', line 149 def presenter_name_for_path(path) "#{path}_presenter".camelize end |
.version(version = nil) ⇒ Object
Get or set the version of the presenter.
version - The Integer version that should be set. If nil, no version is set.
Returns the current Integer version of the presenter.
273 274 275 276 |
# File 'lib/curly/presenter.rb', line 273 def version(version = nil) @version = version if version.present? @version || 0 end |
Instance Method Details
#cache_duration ⇒ Object
The duration that the view should be cached for. Only relevant if
#cache_key
returns a non nil value.
If nil, the view will not have an expiration time set. See also
#cache_options
for a more flexible way to set cache options.
Examples
def cache_duration 10.minutes end
Returns the Fixnum duration of the cache item, in seconds, or nil if no duration should be set.
133 134 135 |
# File 'lib/curly/presenter.rb', line 133 def cache_duration nil end |
#cache_key ⇒ Object
The key that should be used to cache the view.
Unless #cache_key
returns nil, the result of rendering the template
that the presenter supports will be cached. The return value will be
part of the final cache key, along with a digest of the template itself.
Any object can be used as a cache key, so long as it
- is a String,
- responds to #cache_key itself, or
- is an Array or a Hash whose items themselves fit either of these criteria.
Returns the cache key Object or nil if no caching should be performed.
100 101 102 |
# File 'lib/curly/presenter.rb', line 100 def cache_key nil end |
#cache_options ⇒ Object
The options that should be passed to the cache backend when caching the view. The exact options may vary depending on the backend you're using.
The most common option is :expires_in
, which controls the duration of
time that the cached view should be considered fresh. Because it's so
common, you can set that option simply by defining #cache_duration
.
Note: if you set the :expires_in
option through this method, the
#cache_duration
value will be ignored.
Returns a Hash.
115 116 117 |
# File 'lib/curly/presenter.rb', line 115 def {} end |
#setup! ⇒ Object
Sets up the view.
Override this method in your presenter in order to do setup before the
template is rendered. One use case is to call content_for
in order
to inject content into other templates, e.g. a layout.
Examples
class Posts::ShowPresenter < Curly::Presenter presents :post
def setup!
content_for :page_title, @post.title
end
end
Returns nothing.
82 83 84 |
# File 'lib/curly/presenter.rb', line 82 def setup! # Does nothing. end |